QkDag
typedef struct QkDag QkDagA QkDag estrutura expõe uma interface de baixo nível para a representação do gráfico acíclico direcionado (DAG) do transpilador Qiskit de um circuito quântico para uso em passagens do transpilador. Ele expõe apenas o que está definido no modelo de dados interno do Qiskit. Portanto, faltam algumas funcionalidades que estão disponíveis na classe de nível superior PythonDAGCircuit .
Atualmente, a API C só suporta a construção de DAGs que contenham operações definidas no modelo de dados Rust interno do Qiskit. Geralmente, isso inclui apenas portas na biblioteca padrão de portas, operações padrão não unitárias (atualmente Barrier, Measure, Reset e Delay) e UnitaryGate. Essa funcionalidade será ampliada ao longo do tempo, à medida que o modelo de dados Rust for expandido para oferecer suporte nativo a mais funcionalidades.
Tipos de dados
QkDagNodeType
enum QkDagNodeType
O tipo de nó em um QkDag.
Os nós de operação representam uma instrução aplicada. Os demais nós são considerados nós “wire” e representam os pontos finais das cadeias de dependência de dados do DAG.
Valores:
enumerador QkDagNodeType_Operation
Nó de operação.
enumerador QkDagNodeType_QubitIn
Nó inicial do fio qubit.
enumerador QkDagNodeType_QubitOut
Nó terminal do fio qubit.
enumerador QkDagNodeType_ClbitIn
Nó inicial do fio Clbit.
enumerador QkDagNodeType_ClbitOut
Nó terminal do fio Clbit.
enumerador QkDagNodeType_VarIn
Nó clássico de início de fio variável.
enumerador QkDagNodeType_VarOut
Nó terminal de fio variável clássico.
QkOperationKind
enum QkOperationKind
O tipo de operação.
Isso é retornado ao consultar um nó específico no gráfico com qk_dag_op_node_kinde tem como objetivo permitir que o chamador despache (por exemplo, por meio de um “switch”) chamadas específicas para o tipo de operação contida.
Valores:
enumerador QkOperationKind_Gate
enumerador QkOperationKind_Barrier
enumerador QkOperationKind_Delay
enumerador QkOperationKind_Measure
enumerador QkOperationKind_Reset
enumerador QkOperationKind_Unitary
enumerador QkOperationKind_PauliProductMeasurement
enumerador QkOperationKind_ControlFlow
enumerador QkOperationKind_Unknown
Esta variante é usada como um tipo opaco para operações ainda não implementadas no modelo de dados nativo.
QkOperationKind_PauliProductRotation, recenseador
QkDagNeighbors
struct QkDagNeighbors
Uma estrutura para armazenar informações sobre sucessores e predecessores recuperadas de qk_dag_successors e qk_dag_predecessors, respectivamente.
Este objeto é somente leitura a partir de C. Para satisfazer as garantias de segurança do qk_dag_neighbors_clear, você não deve sobrescrever nenhum dado inicializado pelo qk_dag_successors ou qk_dag_predecessors, incluindo quaisquer dados apontados.
const uint32_t *vizinhos
Matriz de tamanho num_neighbors de índices de nós.
tamanho_t número_de_vizinhos
O comprimento da neighbors matriz.
Funções
qk_dag_new
QkDag *qk_dag_new(void)
Construa um novo DAG vazio.
Você deve liberar o DAG retornado com qk_dag_free quando terminar de usá-lo.
Exemplo
QkDag *empty = qk_dag_new();Retorna
Um ponteiro para o DAG criado.
qk_dag_add_quantum_register
void qk_dag_add_quantum_register(QkDag *dag, const QkQuantumRegister *reg)
Adicione um registro quântico ao DAG.
Exemplo
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(1024, "my_register");
qk_dag_add_quantum_register(dag, qr);
qk_quantum_register_free(qr);
qk_dag_free(dag);Segurança
O comportamento é indefinido se não dag for um ponteiro válido e diferente de nulo para um QkDag e se não reg for um ponteiro válido e diferente de nulo para um QkQuantumRegister.
Parâmetros
- dag – Um ponteiro para o DAG.
- reg – Um ponteiro para o registro quântico.
qk_dag_add_classical_register
void qk_dag_add_classical_register(QkDag *dag, const QkClassicalRegister *reg)
Adicione um registro clássico ao DAG.
Exemplo
QkDag *dag = qk_dag_new();
QkClassicalRegister *cr = qk_classical_register_new(24, "my_register");
qk_dag_add_classical_register(dag, cr);
qk_classical_register_free(cr);
qk_dag_free(dag);Segurança
O comportamento é indefinido se não dag for um ponteiro válido e diferente de nulo para um QkDag e se não reg for um ponteiro válido e diferente de nulo para um QkClassicalRegister.
Parâmetros
- dag – Um ponteiro para o DAG.
- reg – Um ponteiro para o registro clássico.
qk_dag_num_qubits
uint32_t qk_dag_num_qubits(const QkDag *dag)
Obtenha o número de qubits que o DAG contém.
Exemplo
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(24, "my_register");
qk_dag_add_quantum_register(dag, qr);
uint32_t num_qubits = qk_dag_num_qubits(dag); // num_qubits==24
qk_quantum_register_free(qr);
qk_dag_free(dag);Segurança
O comportamento é indefinido se não dag for um ponteiro válido e diferente de nulo para um QkDag.
Parâmetros
- dag – Um ponteiro para o DAG.
Retorna
O número de qubits em que o DAG é definido.
qk_dag_num_clbits
uint32_t qk_dag_num_clbits(const QkDag *dag)
Obtenha o número de clbits que o DAG contém.
Exemplo
QkDag *dag = qk_dag_new();
QkClassicalRegister *cr = qk_classical_register_new(24, "my_register");
qk_dag_add_classical_register(dag, cr);
uint32_t num_clbits = qk_dag_num_clbits(dag); // num_clbits==24
qk_classical_register_free(cr);
qk_dag_free(dag);Segurança
O comportamento é indefinido se não dag for um ponteiro válido e diferente de nulo para um QkDag.
Parâmetros
- dag – Um ponteiro para o DAG.
Retorna
O número de clbits em que o DAG é definido.
qk_dag_num_op_nodes
size_t qk_dag_num_op_nodes(const QkDag *dag)
Retorne o número total de nós de operação no DAG.
Exemplo
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(1, "my_register");
qk_dag_add_quantum_register(dag, qr);
uint32_t qubit[1] = {0};
qk_dag_apply_gate(dag, QkGate_H, qubit, NULL, false);
size_t num = qk_dag_num_op_nodes(dag); // 1
qk_dag_free(dag);
qk_quantum_register_free(qr);Segurança
O comportamento é indefinido se não dag for um ponteiro válido e diferente de nulo para um QkDag.
Parâmetros
- dag – Um ponteiro para o DAG.
Retorna
O número total de instruções no DAG.
qk_dag_node_type
QkDagNodeType qk_dag_node_type(const QkDag *dag, uint32_t node)
Obter o tipo do nó especificado.
O resultado pode ser usado em uma instrução switch para enviar o tratamento adequado ao iterar sobre nós de tipo desconhecido.
Segurança
O comportamento é indefinido se não dag for um ponteiro válido e diferente de nulo para um QkDag.
Parâmetros
- dag – Um ponteiro para o DAG.
- nó – O nó do qual se deseja obter o tipo.
Retorna
O tipo do nó.
qk_dag_qubit_in_node
uint32_t qk_dag_qubit_in_node(const QkDag *dag, uint32_t qubit)
Recupera o índice do nó de entrada do fio correspondente ao qubit fornecido.
Segurança
O comportamento é indefinido se não dag for um ponteiro válido e diferente de nulo para um QkDag.
Parâmetros
- dag – Um ponteiro para o DAG.
- qubit – O qubit para obter o índice do nó de entrada.
Retorna
O nó de entrada do fio qubit.
qk_dag_qubit_out_node
uint32_t qk_dag_qubit_out_node(const QkDag *dag, uint32_t qubit)
Recupera o índice do nó de saída do fio correspondente ao qubit fornecido.
Segurança
O comportamento é indefinido se não dag for um ponteiro válido e diferente de nulo para um QkDag.
Parâmetros
- dag – Um ponteiro para o DAG.
- qubit – O qubit para obter o índice do nó de saída.
Retorna
O nó de saída do fio qubit.
qk_dag_clbit_in_node
uint32_t qk_dag_clbit_in_node(const QkDag *dag, uint32_t clbit)
Recupera o índice do nó de entrada do fio correspondente ao clbit fornecido.
Segurança
O comportamento é indefinido se não dag for um ponteiro válido e diferente de nulo para um QkDag.
Parâmetros
- dag – Um ponteiro para o DAG.
- clbit – O clbit para obter o índice do nó de entrada.
Retorna
O nó de entrada do fio clbit.
qk_dag_clbit_out_node
uint32_t qk_dag_clbit_out_node(const QkDag *dag, uint32_t clbit)
Recupera o índice do nó de saída do fio correspondente ao clbit fornecido.
Segurança
O comportamento é indefinido se não dag for um ponteiro válido e diferente de nulo para um QkDag.
Parâmetros
- dag – Um ponteiro para o DAG.
- clbit – O clbit para obter o índice do nó de saída.
Retorna
O nó de saída do fio clbit.
qk_dag_wire_node_value
uint32_t qk_dag_wire_node_value(const QkDag *dag, uint32_t node)
Recupera o valor de um nó terminal de fio.
Segurança
O comportamento é indefinido se não dag for um ponteiro válido e diferente de nulo para um QkDag.
Parâmetros
- dag – Um ponteiro para o DAG.
- nó – O nó final para obter o valor do fio.
Retorna
O valor (por exemplo, qubit, clbit ou var) dentro do nó de ponto final.
qk_dag_op_node_num_qubits
uint32_t qk_dag_op_node_num_qubits(const QkDag *dag, uint32_t node)
Obtém o número de qubits do nó de operação especificado.
Entra em pânico se o nó não for uma operação.
Segurança
O comportamento é indefinido se não dag for um ponteiro válido e diferente de nulo para um QkDag.
Parâmetros
- dag – Um ponteiro para o DAG.
- node – O nó de operação para obter o número de qubits.
Retorna
O número de qubits da operação.
qk_dag_op_node_num_clbits
uint32_t qk_dag_op_node_num_clbits(const QkDag *dag, uint32_t node)
Obtém o número de clbits do nó de operação especificado.
Entra em pânico se o nó não for uma operação.
Segurança
O comportamento é indefinido se não dag for um ponteiro válido e diferente de nulo para um QkDag.
Parâmetros
- dag – Um ponteiro para o DAG.
- node – O nó de operação para obter o número de clbits.
Retorna
O número de bits da operação.
qk_dag_op_node_num_params
uint32_t qk_dag_op_node_num_params(const QkDag *dag, uint32_t node)
Obtém o número de parâmetros do nó de operação especificado.
Entra em pânico se o nó não for uma operação.
Segurança
O comportamento é indefinido se não dag for um ponteiro válido e diferente de nulo para um QkDag.
Parâmetros
- dag – Um ponteiro para o DAG.
- node – O nó de operação para obter o número de parâmetros.
Retorna
O número de parâmetros da operação.
qk_dag_op_node_qubits
const uint32_t *qk_dag_op_node_qubits(const QkDag *dag, uint32_t node)
Recupera os qubits do nó de operação especificado.
Entra em pânico se o nó não for uma operação.
Segurança
O comportamento é indefinido se não dag for um ponteiro válido e diferente de nulo para um QkDag.
Parâmetros
- dag – Um ponteiro para o DAG.
- node – O nó de operação para obter os qubits.
Retorna
Um ponteiro para os qubits. Use qk_dag_op_node_num_qubits para determinar o número de elementos.
qk_dag_op_node_clbits
const uint32_t *qk_dag_op_node_clbits(const QkDag *dag, uint32_t node)
Recupera os bits de cl do nó de operação especificado.
Entra em pânico se o nó não for uma operação.
Segurança
O comportamento é indefinido se não dag for um ponteiro válido e diferente de nulo para um QkDag.
Parâmetros
- dag – Um ponteiro para o DAG.
- node – O nó de operação do qual obter os clbits.
Retorna
Um ponteiro para os clbits. Use qk_dag_op_node_num_clbits para determinar o número de elementos.
qk_dag_apply_gate
uint32_t qk_dag_apply_gate(QkDag *dag, QkGate gate, const uint32_t *qubits, const double *params, bool front)
Aplique um QkGate ao DAG.
Exemplo
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(1, "my_register");
qk_dag_add_quantum_register(dag, qr);
uint32_t qubit[1] = {0};
qk_dag_apply_gate(dag, QkGate_H, qubit, NULL, false);
qk_dag_free(dag);
qk_quantum_register_free(qr);Segurança
Espera-se que os qubits``params tipos e sejam um ponteiro para uma matriz de uint32_t e, double respectivamente, onde o comprimento corresponde às expectativas para o gate padrão. Se a matriz não tiver comprimento suficiente, o comportamento desta função é indefinido, pois ela irá ler fora dos limites da matriz. Pode ser um ponteiro nulo se não houver qubits ou parâmetros para um determinado portão. Você pode verificar qk_gate_num_qubits e qk_gate_num_params para determinar quantos qubits e parâmetros são necessários para um determinado portão.
O comportamento é indefinido se não dag for um ponteiro válido e diferente de nulo para um QkDag.
Parâmetros
- dag – Um ponteiro para o DAG ao qual aplicar o gate.
- gate – O endereço StandardGate para se inscrever.
- qubits – O ponteiro para a matriz de índices
uint32_tde qubits aos quais adicionar o portão. Isso pode ser um ponteiro nulo se não houver qubits paragate(por exemploQkGate_GlobalPhase). - params – O ponteiro para a matriz de
doublevalores a serem usados para os parâmetros da porta. Isso pode ser um ponteiro nulo se não houver parâmetros paragate(por exemploQkGate_H). - frente – Se
true, o portão é aplicado como a primeira operação nos qubits especificados, em vez de como a última.
Retorna
O índice do nó de operação recém-adicionado.
qk_dag_apply_measure
uint32_t qk_dag_apply_measure(QkDag *dag, uint32_t qubit, uint32_t clbit, bool front)
Aplique uma medida a um DAG.
Exemplo
Meça todos os qubits no índice clbit correspondente no final do circuito.
uint32_t num_qubits = qk_dag_num_qubits(dag);
for (uint32_t i = 0; i < num_qubits; i++) {
qk_dag_apply_measure(dag, i, i, false);
}Segurança
O comportamento é indefinido se não dag for um ponteiro alinhado e diferente de nulo para um válido QkDag, ou se qubit ou clbit estiverem fora do intervalo.
Parâmetros
- dag – O circuito ao qual se aplica.
- qubit – O índice qubit a ser medido.
- clbit – O índice clbit para armazenar o resultado.
- frente – Se a medida deve ser aplicada no início do circuito. Normalmente
false.
Retorna
O índice do nó da instrução criada.
qk_dag_apply_reset
uint32_t qk_dag_apply_reset(QkDag *dag, uint32_t qubit, bool front)
Aplique uma reinicialização ao DAG.
Exemplos
Aplique reinicializações iniciais em todos os qubits.
uint32_t num_qubits = qk_dag_num_qubits(dag);
for (uint32_t qubit = 0; qubit < num_qubits; qubit++) {
qk_dag_apply_reset(dag, qubit, true);
}Segurança
O comportamento é indefinido se não dag for um ponteiro alinhado e diferente de nulo para um válido QkDag, ou se qubit estiver fora do intervalo.
Parâmetros
- dag – O circuito ao qual se aplica.
- qubit – O índice do qubit a ser reiniciado.
- frente – Se deve aplicar a reinicialização no início do circuito. Normalmente
false.
Retorna
O índice do nó da instrução criada.
qk_dag_apply_barrier
uint32_t qk_dag_apply_barrier(QkDag *dag, const uint32_t *qubits, uint32_t num_qubits, bool front)
Aplique uma barreira ao DAG.
Exemplos
Aplique uma barreira final em todos os qubits:
qk_dag_apply_barrier(dag, NULL, qk_dag_num_qubits(dag), false);Aplique uma barreira no início de um circuito em índices qubit especificados:
uint32_t qubits[] = {0, 2, 4, 5};
uint32_t num_qubits = sizeof(qubits) / sizeof(qubits[0]);
qk_dag_apply_barrier(dag, qubits, num_qubits, true);Segurança
O comportamento é indefinido se:
dagnão é um ponteiro alinhado e diferente de nulo para um válidoQkDag,qubitsnão está alinhado ou não é válido paranum_qubitsleituras de índices inicializados, dentro dos limites e não duplicados, a menos quequbitsseja nulo.
Parâmetros
- dag – O circuito ao qual se aplica.
- qubits – Os índices qubit aos quais aplicar a barreira. Isso pode ser nulo, caso em
num_qubitsque não é lido, e a barreira é aplicada a todos os qubits no DAG. - num_qubits – A quantos qubits a barreira se aplica.
- frente – Se deve aplicar a barreira no início do circuito. Normalmente
false.
Retorna
O índice do nó da instrução criada.
qk_dag_apply_unitary
uint32_t qk_dag_apply_unitary(QkDag *dag, const QkComplex64 *matrix, const uint32_t *qubits, uint32_t num_qubits, bool front)
Aplique um gate unitário a um DAG.
Os valores em matrix devem formar uma matriz unitária row-major do tamanho correto para o número de qubits. Os dados são copiados do ponteiro e só precisam ser válidos para leitura até que essa função retorne.
Consulte: Convenções de circuito para obter detalhes sobre as convenções de rotulagem de bits e matrizes do Qiskit.
Segurança
O comportamento é indefinido se qualquer uma das seguintes condições se verificar:
dagnão é um ponteiro alinhado e diferente de nulo para um válidoQkDag,matrixnão é um ponteiro alinhado para valores4**num_qubitsinicializados,qubitsnão é um ponteiro alinhado para valoresnum_qubitsinicializados.
Parâmetros
- dag – O circuito ao qual se aplica.
- matriz – Uma matriz unitária inicializada com prioridade nas linhas, de tamanho total
4**num_qubits. - qubits – Uma matriz de índices
uint32_tdistintos dos qubits. - num_qubits – O número de qubits aos quais o portão se aplica.
- frente – Se deve aplicar o gate no início do circuito. Normalmente
false.
Retorna
O índice do nó da instrução criada.
qk_dag_op_node_gate_op
QkGate qk_dag_op_node_gate_op(const QkDag *dag, uint32_t node, double *out_params)
Recuperar o gate padrão do nó especificado.
Entra em pânico se o nó não for uma operação de porta padrão.
Exemplo
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(1, "my_register");
qk_dag_add_quantum_register(dag, qr);
uint32_t qubit[1] = {0};
uint32_t h_gate_idx = qk_dag_apply_gate(dag, QkGate_H, qubit, NULL, false);
QkGate gate = qk_dag_op_node_gate_op(dag, h_gate_idx, NULL);
qk_dag_free(dag);
qk_quantum_register_free(qr);Segurança
O comportamento é indefinido se não dag for um ponteiro válido e diferente de nulo para um QkDag. Se out_params não for NULL, deve apontar para um buffer grande o suficiente para armazenar todos os parâmetros do gate, caso contrário, o comportamento é indefinido, pois esta função irá escrever além dos seus limites. Você pode verificar qk_dag_op_node_num_params para determinar quantos parâmetros são necessários para qualquer nó de operação.
Parâmetros
- dag – Um ponteiro para o DAG.
- nó – O nó de operação para obter o portão padrão.
- out_params – Um buffer a ser preenchido com os parâmetros do gate ou NULL se eles não forem desejados.
Retorna
O valor do gate.
qk_dag_op_node_unitary
void qk_dag_op_node_unitary(const QkDag *dag, uint32_t node, QkComplex64 *out)
Copie a matriz unitária do índice do nó correspondente.
Entra em pânico se o nó não for um portão unitário.
Segurança
O comportamento é indefinido se não dag for um ponteiro diferente de nulo para um válido QkDag, se out não estiver alinhado ou se não out for válido para 4**num_qubits gravações de QkComplex64.
Parâmetros
- dag – O circuito a partir do qual se deve ler.
- nó – O índice do nó da instrução da matriz unitária.
- out – Memória alocada e alinhada para valores
4**num_qubitscomplexos em ordem row-major, ondenum_qubitsé o número de qubits aos quais o gate se aplica.
qk_dag_op_node_kind
QkOperationKind qk_dag_op_node_kind(const QkDag *dag, uint32_t node)
Obtenha o “tipo” de um nó de operação.
O resultado pode ser usado em uma instrução switch para despachar o tratamento adequado ao iterar sobre os nós de operação.
Entra em pânico se não node for um nó de operação.
Segurança
O comportamento é indefinido se não dag for um ponteiro válido e diferente de nulo para um QkDag.
Parâmetros
- dag – Um ponteiro para o DAG.
- nó – O nó de operação para obter o “tipo” de.
Retorna
O “tipo” do nó.
qk_dag_successors
QkDagNeighbors qk_dag_successors(const QkDag *dag, uint32_t node)
Recupera os sucessores do nó especificado.
A matriz de sucessores e seu comprimento são retornados como uma QkDagNeighbors estrutura, onde cada elemento da matriz corresponde a um índice de nó DAG. Você deve chamar a qk_dag_neighbors_clear função quando terminar para liberar a memória alocada para a estrutura.
Exemplo
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(2, "qr");
qk_dag_add_quantum_register(dag, qr);
qk_quantum_register_free(qr);
uint32_t node_cx = qk_dag_apply_gate(dag, QkGate_CX, (uint32_t[]){0, 1}, NULL, false);
QkDagNeighbors successors = qk_dag_successors(dag, node_cx);
qk_dag_neighbors_clear(&successors);
qk_dag_free(dag);Segurança
O comportamento é indefinido se não dag for um ponteiro válido e diferente de nulo para um QkDag.
Parâmetros
- dag – Um ponteiro para o DAG.
- nó – O nó do qual obter os sucessores.
Retorna
Uma instância da QkDagNeighbors estrutura com as informações dos sucessores.
qk_dag_predecessors
QkDagNeighbors qk_dag_predecessors(const QkDag *dag, uint32_t node)
Recupera os predecessores do nó especificado.
A matriz de predecessores e seu comprimento são retornados como uma QkDagNeighbors estrutura, onde cada elemento da matriz corresponde a um índice de nó DAG. Você deve chamar a qk_dag_neighbors_clear função quando terminar para liberar a memória alocada para a estrutura.
Exemplo
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(2, "qr");
qk_dag_add_quantum_register(dag, qr);
qk_quantum_register_free(qr);
uint32_t node_cx = qk_dag_apply_gate(dag, QkGate_CX, (uint32_t[]){0, 1}, NULL, false);
QkDagNeighbors predecessors = qk_dag_predecessors(dag, node_cx);
qk_dag_neighbors_clear(&predecessors);
qk_dag_free(dag);Segurança
O comportamento é indefinido se não dag for um ponteiro válido e diferente de nulo para um QkDag.
Parâmetros
- dag – Um ponteiro para o DAG.
- node – O nó para obter os predecessores.
Retorna
Uma instância da QkDagNeighbors estrutura com as informações dos predecessores.
qk_dag_neighbors_clear
void qk_dag_neighbors_clear(QkDagNeighbors *neighbors)
Limpe os campos da estrutura de QkDagNeighbors entrada.
A função desaloca a memória apontada pelo neighbors campo e a define como NULL. Ele também define o num_neighbors campo como 0.
Segurança
O comportamento é indefinido se não neighbors for um ponteiro válido e diferente de nulo para um QkDagNeighbors objeto preenchido com ou qk_dag_successors qk_dag_predecessors.
Parâmetros
- vizinhos – Um ponteiro para um
QkDagNeighborsobjeto.
qk_dag_get_instruction
void qk_dag_get_instruction(const QkDag *dag, uint32_t index, QkCircuitInstruction *instruction)
Retorne os detalhes de uma instrução no circuito.
Este é um espelho de qk_circuit_get_instruction. Você também pode usar métodos individuais, como qk_dag_op_node_gate_op para obter propriedades individuais.
Você deve ligar qk_circuit_instruction_clear para redefinir o QkCircuitInstruction antes de reutilizá-lo ou descartá-lo.
Exemplos
Itere através de um DAG para encontrar quais qubits têm medidas:
bool *measured = calloc(qk_dag_num_qubits(dag), sizeof(*measured));
uint32_t num_ops = qk_dag_num_op_nodes(dag);
uint32_t *ops = malloc(num_ops * sizeof(*ops));
qk_dag_topological_op_nodes(dag, ops);
// Storage space for the instruction.
QkCircuitInstruction inst;
for (uint32_t i = 0; i < num_ops; i++) {
qk_dag_get_instruction(dag, ops[i], &inst);
if (!strcmp(inst.name, "measure"))
measured[inst.qubits[0]] = true;
qk_circuit_instruction_clear(&inst);
}
free(ops);
free(measured);Segurança
O comportamento é indefinido se ou dag não instruction forem ponteiros válidos, alinhados e diferentes de nulo para o tipo de dados relevante. Os instruction campos não precisam ser inicializados.
Parâmetros
- dag – O circuito do qual a instrução deve ser recuperada.
- índice – O índice do nó. É um erro passar um índice que não é um nó operacional válido.
- instrução – Um ponto para onde escrever o
QkCircuitInstruction.
qk_dag_compose
QkExitCode qk_dag_compose(QkDag *dag, const QkDag *other, const uint32_t *qubits, const uint32_t *clbits)
Componha o other DAG na dag instância com a opção de um subconjunto de fios de entrada other sendo mapeado para um subconjunto de fios de saída dag.
other pode incluir um número menor ou igual de fios para cada tipo.
Exemplo
// Build the following dag
// rqr_0: ──■───────
// │ ┌───┐
// rqr_1: ──┼──┤ Y ├
// ┌─┴─┐└───┘
// rqr_2: ┤ X ├─────
// └───┘
QkDag *dag_right = qk_dag_new();
QkQuantumRegister *rqr = qk_quantum_register_new(3, "rqr");
qk_dag_add_quantum_register(dag_right, rqr);
qk_dag_add_classical_register(dag_right, rcr);
qk_dag_apply_gate(dag_right, QkGate_CX, (uint32_t[]){0, 2}, NULL, false);
qk_dag_apply_gate(dag_right, QkGate_Y, (uint32_t[]){1}, NULL, false);
// Build the following dag
// ┌───┐
// lqr_0: ──┤ H ├───
// ┌─┴───┴──┐
// lqr_1: ┤ P(0.1) ├
// └────────┘
QkDag *dag_left = qk_dag_new();
QkQuantumRegister *lqr = qk_quantum_register_new(2, "lqr");
qk_dag_add_quantum_register(dag_left, lqr);
qk_dag_add_classical_register(dag_left, lcr);
qk_dag_apply_gate(dag_left, QkGate_H, (uint32_t[]){0}, NULL, false);
qk_dag_apply_gate(dag_left, QkGate_Phase, (uint32_t[]){1}, (double[]){0.1}, false);
// Compose left circuit onto right circuit
// Should result in circuit
// ┌───┐
// rqr_0: ──■──┤ H ├──────────
// │ ├───┤┌────────┐
// rqr_1: ──┼──┤ Y ├┤ P(0.1) ├
// ┌─┴─┐└───┘└────────┘
// rqr_2: ┤ X ├───────────────
// └───┘
qk_dag_compose(dag_right, dag_left, NULL, NULL);
// Clean up after you're done
qk_dag_free(dag_left);
qk_dag_free(dag_right);
qk_quantum_register_free(lqr);
qk_quantum_register_free(rqr);Segurança
O comportamento é indefinido se dag ou não other forem ponteiros válidos e diferentes de nulo para um QkDag. Se qubit nem clbit forem NULL, deve conter uma quantidade menor ou igual à que o circuito possui.
Parâmetros
- dag – Um ponteiro para o DAG a ser composto.
- outro – Um ponteiro para o DAG a ser composto
dag. - qubits – Uma lista de índices que representam os fios qubit a serem compostos.
- clbits – Uma lista de índices que representam os fios clbit a serem compostos.
Retorna
QkExitCode_Success após a decomposição bem-sucedida, caso contrário, um código de erro específico do DAG indicando a causa da falha.
qk_dag_free
void qk_dag_free(QkDag *dag)
Liberte o DAG.
Exemplo
QkDag *dag = qk_dag_new();
qk_dag_free(dag);Segurança
O comportamento é indefinido se não dag for nulo ou um ponteiro válido para um QkDag.
Parâmetros
- dag – Um ponteiro para o DAG a ser liberado.
qk_dag_to_circuit
QkCircuit *qk_dag_to_circuit(const QkDag *dag)
Converta um determinado DAG em um circuito.
O novo circuito é copiado do DAG; a referência dag original ainda pertence ao chamador e ainda precisa ser liberada com qk_dag_free. Você deve liberar o circuito retornado com qk_circuit_free quando terminar de usá-lo.
Exemplo
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(2, "qr");
qk_dag_add_quantum_register(dag, qr);
qk_quantum_register_free(qr);
QkCircuit *qc = qk_dag_to_circuit(dag);
qk_circuit_free(qc);
qk_dag_free(dag);Segurança
O comportamento é indefinido se não dag for um ponteiro válido e diferente de nulo para um QkDag.
Parâmetros
- dag – Um ponteiro para o DAG a partir do qual criar o circuito.
Retorna
Um indicador para o novo circuito.
qk_dag_topological_op_nodes
void qk_dag_topological_op_nodes(const QkDag *dag, uint32_t *out_order)
Retorne os nós de operação no DAG listados em ordem topológica.
Exemplo
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(1, "my_register");
qk_dag_add_quantum_register(dag, qr);
uint32_t qubit[1] = {0};
qk_dag_apply_gate(dag, QkGate_H, qubit, NULL, false);
qk_dag_apply_gate(dag, QkGate_S, qubit, NULL, false);
// get the number of operation nodes
uint32_t num_ops = qk_dag_num_op_nodes(dag); // 2
uint32_t *out_order = malloc(sizeof(uint32_t) * num_ops);
// get operation nodes listed in topological order
qk_dag_topological_op_nodes(dag, out_order);
// do something with the ordered nodes
for (uint32_t i = 0; i < num_ops; i++) {
QkGate gate = qk_dag_op_node_gate_op(dag, out_order[i], NULL);
printf("The gate at location %u is %u.\n", i, gate);
}
// free the out_order array, register, and dag pointer when done
free(out_order);
qk_quantum_register_free(qr);
qk_dag_free(dag);Segurança
O comportamento é indefinido se não dag for um ponteiro válido e diferente de nulo para um QkDag ou se não out_order for um ponteiro válido e diferente de nulo para uma sequência de qk_dag_num_op_nodes(dag) elementos consecutivos de uint32_t.
Parâmetros
- dag – Um ponteiro para o DAG.
- out_order – Um ponteiro para uma matriz de
qk_dag_num_op_nodes(dag)elementos do tipouint32_t, onde esta função irá gravar a saída.
qk_dag_substitute_node_with_dag
void qk_dag_substitute_node_with_dag(QkDag *dag, uint32_t node, const QkDag *replacement)
Substituir um nó em um QkDag por um subcircuito especificado por outro QkDag
Exemplo
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(1, "my_register");
qk_dag_add_quantum_register(dag, qr);
uint32_t qubit[1] = {0};
uint32_t node_to_replace = qk_dag_apply_gate(dag, QkGate_H, qubit, NULL, false);
qk_dag_apply_gate(dag, QkGate_S, qubit, NULL, false);
// Build replacement dag for H
QkDag *replacement = qk_dag_new();
QkQuantumRegister *replacement_qr = qk_quantum_register_new(1, "other");
qk_dag_add_quantum_register(replacement, replacement_qr);
double pi_param[1] = {3.14159};
qk_dag_apply_gate(replacement, QkGate_RZ, qubit, pi_param, false);
qk_dag_apply_gate(replacement, QkGate_SX, qubit, NULL, false);
qk_dag_apply_gate(replacement, QkGate_RZ, qubit, pi_param, false);
qk_dag_substitute_node_with_dag(dag, node_to_replace, replacement);
// Free the replacement dag, register, dag, and register
qk_quantum_register_free(replacement_qr);
qk_dag_free(replacement);
qk_quantum_register_free(qr);
qk_dag_free(dag);Segurança
O comportamento é indefinido se dag e não replacement forem ponteiros válidos e diferentes de nulo para um QkDag.
Parâmetros
- dag – Um ponteiro para o DAG.
- nó – O índice do nó da operação a ser substituída pela outra
QkDag. Este deve ser o índice do nó para um nó de operação emdage a contagem de qargs e cargs deve corresponder ao número de qubits e clbits emreplacement. - substituição – O outro
QkDagpara substituirnode. Este dag deve ter o mesmo número de qubits que a operação paranode. A ordenação dos bits do nó será tratada em ordem, portanto,node``qargs[0]para será mapeado paraqubits[0]emreplacement,qargs[1]paraqubits[0], etc. O mesmo padrão se aplica também aos bits clássicos.
qk_dag_copy_empty_like
QkDag *qk_dag_copy_empty_like(const QkDag *dag, QkVarsMode vars_mode, QkBlocksMode blocks_mode)
Retorna uma cópia de si mesmo com a mesma estrutura, mas vazia.
Essa estrutura inclui:
- nome e outros metadados
- fase global
- duração
- todos os qubits e clbits, incluindo os registros.
Exemplo
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(1, "my_register");
qk_dag_add_quantum_register(dag, qr);
uint32_t qubit[1] = {0};
qk_dag_apply_gate(dag, QkGate_H, qubit, NULL, false);
// As the DAG does not contain any control-flow instructions,
// vars_mode and blocks_mode do not have any effect.
QkDag *copied_dag = qk_dag_copy_empty_like(dag, QkVarsMode_Alike, QkBlocksMode_Drop);
uint32_t num_ops_in_copied_dag = qk_dag_num_op_nodes(copied_dag); // 0
// do something with copied_dag
qk_quantum_register_free(qr);
qk_dag_free(dag);
qk_dag_free(copied_dag);Segurança
O comportamento é indefinido se não dag for um ponteiro válido para um QkDag.
Parâmetros
- dag – Um ponteiro para o DAG a ser copiado.
- vars_mode – O modo para lidar com variáveis clássicas.
- blocks_mode – O modo para lidar com blocos.
Retorna
O ponteiro para o circuito DAG copiado.
qk_dag_replace_block_with_unitary
uint32_t qk_dag_replace_block_with_unitary(QkDag *dag, uint32_t num_block_ids, const uint32_t *block_ids, const QkComplex64 *matrix, uint32_t num_qubits, const uint32_t *qubits, bool cycle_check)
Substitua um bloco contíguo não vazio de nós em um QkDag por um único portão unitário correspondente à matriz unitária especificada.
Após a substituição, os nós do bloco são removidos e substituídos por um novo nó que atua sobre os qubits em questão.
Exemplo
// Create a DAG with H, T, S, T, H gates on the second qubit
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(2, "qr");
qk_dag_add_quantum_register(dag, qr);
uint32_t qubit[1] = {1};
qk_dag_apply_gate(dag, QkGate_H, qubit, NULL, false);
uint32_t idx1 = qk_dag_apply_gate(dag, QkGate_T, qubit, NULL, false);
uint32_t idx2 = qk_dag_apply_gate(dag, QkGate_S, qubit, NULL, false);
uint32_t idx3 = qk_dag_apply_gate(dag, QkGate_T, qubit, NULL, false);
qk_dag_apply_gate(dag, QkGate_H, qubit, NULL, false);
// Replace the inner T, S, T gates by a unitary gate (representing Z)
uint32_t replaced_ids[3] = {idx1, idx2, idx3};
static const QkComplex64 mat_z[4] = {{1, 0}, {0, 0}, {0, 0}, {-1, 0}};
uint32_t new_node_idx =
qk_dag_replace_block_with_unitary(dag, 3, replaced_ids, mat_z, 1, qubit, false);
// free the register and dag pointer when done
qk_quantum_register_free(qr);
qk_dag_free(dag);Segurança
O comportamento é indefinido se qualquer uma das seguintes condições se verificar:
dagnão é um ponteiro alinhado e diferente de nulo para um válidoQkDag,qubitsnão é um ponteiro alinhado para valoresnum_qubitsinicializados.matrixnão é um ponteiro alinhado para valores4**num_qubitsinicializados,block_idsnão é um ponteiro alinhado a valoresnum_block_idsinicializados.
Parâmetros
- dag – Ponteiro para o DAG.
- num_block_ids – Número de entradas em
block_ids. Esse número não pode ser zero. - block_ids – Ponteiro para uma matriz não vazia de nós a serem substituídos.
- matriz – Ponteiro para uma matriz unitária com disposição por linhas, inicializada, de tamanho
4**num_qubits. - num_qubits – O número de qubits sobre os quais a porta unitária resultante atua.
- qubits – Ponteiro para uma matriz de índices de qubits
uint32_tdistintos. Cada entrada especifica o índice do qubit DAG que corresponde à respectiva posição do argumento na porta unitária. - cycle_check – Se
true, a função verifica se a substituição do nó fornecidoblock_idspor um único nó introduziria um ciclo no DAG (o que invalidaria o DAG). Se for criado um ciclo, o DAG permanece inalterado eUINT32_MAXé retornado. Essa verificação acarreta uma perda de desempenho. Se for possível garantir que o bloco fornecidoblock_idsé contíguo e não criará um ciclo ao ser reduzido a um único nó, esse valor pode ser definido comofalse.
Retorna
O índice do nó de operação recém-adicionado, ou UINT32_MAX se cycle_check for true e a substituição introduzir um ciclo.
qk_dag_substitute_node_with_unitary
void qk_dag_substitute_node_with_unitary(QkDag *dag, uint32_t node, const QkComplex64 *matrix, uint32_t num_qubits)
Substitua uma operação em um nó de uma rede QkDag por uma porta unitária correspondente à matriz unitária especificada.
A nova operação deve ter a mesma forma que a operação substituída. Os qargs e cargs do nó permanecerão os mesmos.
Exemplo
// Create a DAG with a Z-gate
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(2, "qr");
qk_dag_add_quantum_register(dag, qr);
uint32_t idx_z = qk_dag_apply_gate(dag, QkGate_Z, (uint32_t[]){1}, NULL, false);
static const QkComplex64 mat[4] = {{1, 0}, {0, 0}, {0, 0}, {-1, 0}};
// Replace the Z-gate by a unitary matrix
qk_dag_substitute_node_with_unitary(dag, idx_z, mat, 1);
// free the register and dag pointer when done
qk_quantum_register_free(qr);
qk_dag_free(dag);Segurança
O comportamento é indefinido se qualquer uma das seguintes condições se verificar:
dagnão é um ponteiro alinhado e diferente de nulo para um válidoQkDag,matrixnão é um ponteiro alinhado para valores4**num_qubitsinicializados,
Parâmetros
- dag – Ponteiro para o DAG.
- nó – O nó cuja operação é substituída. O número de qubits na operação substituída deve ser igual a
num_qubitse o número de clbits deve ser0. - matriz – Ponteiro para uma matriz unitária com disposição por linhas, inicializada, de tamanho
4**num_qubits. - num_qubits – O número de qubits sobre os quais a operação unitária atua.
qk_dag_to_python
PyObject *qk_dag_to_python(QkDag *dag)
Passe a propriedade de um QkDag objeto para Python.
Não é seguro usar o QkDag ponteiro após chamar esta função. Em particular, você não deve tentar apagá-lo ou liberá-lo. O chamador deve ser o proprietário do objeto QkDag, e não possuir uma referência emprestada (por exemplo, um objeto QkDag * recuperado de um retrieved from não qk_dag_borrow_from_python é de sua propriedade).
Segurança
O chamador deve estar conectado a um intérprete do tipo Python. O comportamento é indefinido se não dag for um ponteiro válido e diferente de nulo para um objeto inicializado e de propriedade do usuário QkDag.
Parâmetros
- dag – O objeto em questão.
Retorna
Uma referência de propriedade do tipo Python ao objeto.
qk_dag_borrow_from_python
QkDag *qk_dag_borrow_from_python(PyObject *ob)
Recuperar um QkDag ponteiro de um objeto Python.
Isso utiliza uma referência de tipo Python e extrai o QkDag ponteiro correspondente, caso seja do tipo correto. O ponteiro retornado é obtido do ponteiro ob . Se o não PyObject for do tipo correto, o valor de retorno é NULL e o estado de exceção do interpretador do Python é definido.
Você deve estar conectado a um interpretador Python para chamar esta função.
Você também pode usar qk_dag_convert_from_python, que é, em termos lógicos, exatamente igual a esta função, mas pode ser usada diretamente como uma função “conversora” para a PyArg_Parse* família de funções conversoras do Python.
Segurança
O chamador deve estar conectado a um intérprete do tipo Python. O comportamento é indefinido se não ob for um ponteiro válido e diferente de nulo para um objeto Python.
Parâmetros
- ob – Um objeto de empréstimo do tipo
Python.
Retorna
Um ponteiro para o objeto nativo, ou NULL se o objeto Python for do tipo incorreto.
qk_dag_convert_from_python
int qk_dag_convert_from_python(PyObject *object, void *address)
Recuperar um ponteiro DAG de um objeto Python.
Isso utiliza uma referência do tipo Python e extrai o QkDag ponteiro correspondente para address``,, caso seja do tipo correto. O ponteiro retornado é obtido do ponteiro object . Se o não PyObject for do tipo correto, o valor de retorno é 1, o estado de exceção do interpretador do Python é definido e address permanece inalterado.
Você deve estar conectado a um interpretador Python para chamar esta função.
Você também pode usar qk_dag_borrow_from_python, que é, na prática, exatamente o mesmo que isto, mas com uma sintaxe mais natural para uso direto.
Segurança
O chamador deve estar conectado a um intérprete do tipo Python. O comportamento é indefinido se não object for um ponteiro válido e diferente de nulo para um objeto Python, ou se não address for um ponteiro para dados graváveis do tipo correto.
Parâmetros
- objeto – Um objeto
Pythonobtido por empréstimo. - endereço – O local onde a saída deve ser gravada.
Retorna
1 em caso de sucesso, 0 em caso de falha.