QkDag
typedef struct QkDag QkDagLa QkDag estructura expone una interfaz de bajo nivel a la representación del gráfico acíclico dirigido (DAG) del transpilador Qiskit de un circuito cuántico para su uso en pasadas del transpilador. Solo expone lo que se define en el modelo de datos interno de Qiskit. Por lo tanto, le faltan algunas funciones que están disponibles en la clase de nivel DAGCircuit superior Python.
Actualmente, la API C solo admite la creación de DAG que contengan operaciones definidas en el modelo de datos interno Rust de Qiskit. Por lo general, esto incluye solo puertas de la biblioteca de puertas estándar, operaciones estándar no unitarias (actualmente Barrier, Measure, Reset, y Delay) y UnitaryGate. Esta funcionalidad se ampliará con el tiempo a medida que el modelo de datos de Rust se amplíe para admitir de forma nativa más funcionalidades.
Tipos de datos
QkDagNodeType
enum QkDagNodeType
El tipo de nodo en un QkDag.
Los nodos de operación representan una instrucción aplicada. El resto de los nodos se consideran nodos «de conexión» y representan los extremos de las cadenas de dependencia de datos del DAG.
Valores:
enumerador QkDagNodeType_Operation
Nodo de operación.
enumerador QkDagNodeType_QubitIn
Nodo de inicio del cable Qubit.
enumerador QkDagNodeType_QubitOut
Nodo terminal del cable Qubit.
enumerador QkDagNodeType_ClbitIn
Nodo inicial del cable Clbit.
enumerador QkDagNodeType_ClbitOut
Nodo terminal de cable Clbit.
enumerador QkDagNodeType_VarIn
Nodo clásico de inicio de cable variable.
enumerador QkDagNodeType_VarOut
Nodo terminal de cable variable clásico.
QkOperationKind
enum QkOperationKind
El tipo de operación.
Esto se devuelve al consultar un nodo concreto del gráfico con qk_dag_op_node_kind, y su finalidad es permitir al llamante distribuir (por ejemplo, mediante un «switch») llamadas específicas para el tipo de operación contenida.
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 se utiliza como tipo opaco para operaciones que aún no se han implementado en el modelo de datos nativo.
encuestador QkOperationKind_PauliProductRotation
QkDagNeighbors
struct QkDagNeighbors
Una estructura para almacenar información sobre sucesores y predecesores obtenida de qk_dag_successors y qk_dag_predecessors, respectivamente.
Este objeto es de solo lectura desde C. Para cumplir con las garantías de seguridad de qk_dag_neighbors_clear, no debe sobrescribir ningún dato inicializado por qk_dag_successors o qk_dag_predecessors, incluidos los datos a los que se apunta.
const uint32_t *vecinos
Matriz de tamaño num_neighbors de índices de nodos.
tamaño_t número_vecinos
La longitud de la neighbors matriz.
Funciones
qk_dag_new
QkDag *qk_dag_new(void)
Construye un nuevo DAG vacío.
Debe liberar el DAG devuelto con qk_dag_free cuando haya terminado de utilizarlo.
Ejemplo
QkDag *empty = qk_dag_new();Devuelve
Un puntero al DAG creado.
qk_dag_add_quantum_register
void qk_dag_add_quantum_register(QkDag *dag, const QkQuantumRegister *reg)
Añadir un registro cuántico al DAG.
Ejemplo
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);Seguridad
El comportamiento es indefinido si no dag es un puntero válido y distinto de nulo a un QkDag y si no reg es un puntero válido y distinto de nulo a un QkQuantumRegister.
Parámetros
- dag : un puntero al DAG.
- reg : un puntero al registro cuántico.
qk_dag_add_classical_register
void qk_dag_add_classical_register(QkDag *dag, const QkClassicalRegister *reg)
Añadir un registro clásico al DAG.
Ejemplo
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);Seguridad
El comportamiento es indefinido si no dag es un puntero válido y distinto de nulo a un QkDag y si no reg es un puntero válido y distinto de nulo a un QkClassicalRegister.
Parámetros
- dag : un puntero al DAG.
- reg – Un puntero al registro clásico.
qk_dag_num_qubits
uint32_t qk_dag_num_qubits(const QkDag *dag)
Obtenga el número de qubits que contiene el DAG.
Ejemplo
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);Seguridad
El comportamiento es indefinido si no dag es un puntero válido y distinto de nulo a un QkDag.
Parámetros
- dag : un puntero al DAG.
Devuelve
El número de qubits en los que se define el DAG.
qk_dag_num_clbits
uint32_t qk_dag_num_clbits(const QkDag *dag)
Obtenga el número de clbits que contiene el DAG.
Ejemplo
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);Seguridad
El comportamiento es indefinido si no dag es un puntero válido y distinto de nulo a un QkDag.
Parámetros
- dag : un puntero al DAG.
Devuelve
El número de clbits en los que se define el DAG.
qk_dag_num_op_nodes
size_t qk_dag_num_op_nodes(const QkDag *dag)
Devuelve el número total de nodos de operación en el DAG.
Ejemplo
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);Seguridad
El comportamiento es indefinido si no dag es un puntero válido y distinto de nulo a un QkDag.
Parámetros
- dag : un puntero al DAG.
Devuelve
El número total de instrucciones en el DAG.
qk_dag_node_type
QkDagNodeType qk_dag_node_type(const QkDag *dag, uint32_t node)
Obtener el tipo del nodo especificado.
El resultado se puede utilizar en una instrucción switch para enviar el manejo adecuado al iterar sobre nodos de tipo desconocido.
Seguridad
El comportamiento es indefinido si no dag es un puntero válido y distinto de nulo a un QkDag.
Parámetros
- dag : un puntero al DAG.
- nodo : el nodo del que se desea obtener el tipo.
Devuelve
El tipo del nodo.
qk_dag_qubit_in_node
uint32_t qk_dag_qubit_in_node(const QkDag *dag, uint32_t qubit)
Recupera el índice del nodo de entrada del cable correspondiente al qubit dado.
Seguridad
El comportamiento es indefinido si no dag es un puntero válido y distinto de nulo a un QkDag.
Parámetros
- dag : un puntero al DAG.
- qubit : el qubit del que se obtiene el índice del nodo de entrada.
Devuelve
El nodo de entrada del cable cuántico.
qk_dag_qubit_out_node
uint32_t qk_dag_qubit_out_node(const QkDag *dag, uint32_t qubit)
Recupera el índice del nodo de salida del cable correspondiente al qubit dado.
Seguridad
El comportamiento es indefinido si no dag es un puntero válido y distinto de nulo a un QkDag.
Parámetros
- dag : un puntero al DAG.
- qubit : el qubit del que se obtiene el índice del nodo de salida.
Devuelve
El nodo de salida del cable cuántico.
qk_dag_clbit_in_node
uint32_t qk_dag_clbit_in_node(const QkDag *dag, uint32_t clbit)
Recupera el índice del nodo de entrada del cable correspondiente al clbit dado.
Seguridad
El comportamiento es indefinido si no dag es un puntero válido y distinto de nulo a un QkDag.
Parámetros
- dag : un puntero al DAG.
- clbit : el clbit para obtener el índice del nodo de entrada.
Devuelve
El nodo de entrada del cable clbit.
qk_dag_clbit_out_node
uint32_t qk_dag_clbit_out_node(const QkDag *dag, uint32_t clbit)
Recupera el índice del nodo de salida del cable correspondiente al clbit dado.
Seguridad
El comportamiento es indefinido si no dag es un puntero válido y distinto de nulo a un QkDag.
Parámetros
- dag : un puntero al DAG.
- clbit : el clbit del que se obtiene el índice del nodo de salida.
Devuelve
El nodo de salida del cable clbit.
qk_dag_wire_node_value
uint32_t qk_dag_wire_node_value(const QkDag *dag, uint32_t node)
Recuperar el valor de un nodo de punto final de cable.
Seguridad
El comportamiento es indefinido si no dag es un puntero válido y distinto de nulo a un QkDag.
Parámetros
- dag : un puntero al DAG.
- nodo : el nodo final del que se obtiene el valor del cable.
Devuelve
El valor (por ejemplo, qubit, clbit o var) dentro del nodo del punto final.
qk_dag_op_node_num_qubits
uint32_t qk_dag_op_node_num_qubits(const QkDag *dag, uint32_t node)
Obtiene el número de qubits del nodo de operación especificado.
Entra en pánico si el nodo no es una operación.
Seguridad
El comportamiento es indefinido si no dag es un puntero válido y distinto de nulo a un QkDag.
Parámetros
- dag : un puntero al DAG.
- nodo : el nodo de operación del que se desea obtener el número de qubits.
Devuelve
El número de qubits de la operación.
qk_dag_op_node_num_clbits
uint32_t qk_dag_op_node_num_clbits(const QkDag *dag, uint32_t node)
Obtiene el número de clbits del nodo de operación especificado.
Entra en pánico si el nodo no es una operación.
Seguridad
El comportamiento es indefinido si no dag es un puntero válido y distinto de nulo a un QkDag.
Parámetros
- dag : un puntero al DAG.
- nodo : el nodo de operación del que se obtiene el número de clbits.
Devuelve
El número de clbits de la operación.
qk_dag_op_node_num_params
uint32_t qk_dag_op_node_num_params(const QkDag *dag, uint32_t node)
Obtiene el número de parámetros del nodo de operación especificado.
Entra en pánico si el nodo no es una operación.
Seguridad
El comportamiento es indefinido si no dag es un puntero válido y distinto de nulo a un QkDag.
Parámetros
- dag : un puntero al DAG.
- nodo : el nodo de operación del que se obtiene el número de parámetros.
Devuelve
El número de parámetros de la operación.
qk_dag_op_node_qubits
const uint32_t *qk_dag_op_node_qubits(const QkDag *dag, uint32_t node)
Recupera los qubits del nodo de operación especificado.
Entra en pánico si el nodo no es una operación.
Seguridad
El comportamiento es indefinido si no dag es un puntero válido y distinto de nulo a un QkDag.
Parámetros
- dag : un puntero al DAG.
- nodo : el nodo de operación del que se obtienen los qubits.
Devuelve
Un puntero a los qubits. Utilice qk_dag_op_node_num_qubits para determinar el número de elementos.
qk_dag_op_node_clbits
const uint32_t *qk_dag_op_node_clbits(const QkDag *dag, uint32_t node)
Recupera los clbits del nodo de operación especificado.
Entra en pánico si el nodo no es una operación.
Seguridad
El comportamiento es indefinido si no dag es un puntero válido y distinto de nulo a un QkDag.
Parámetros
- dag : un puntero al DAG.
- nodo : el nodo de operación del que se obtienen los clbits.
Devuelve
Un puntero a clbits. Utilice qk_dag_op_node_num_clbits para determinar el 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)
Aplicar un QkGate al DAG.
Ejemplo
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);Seguridad
Se espera que los qubits``params tipos y sean punteros a una matriz de uint32_t y double respectivamente, donde la longitud coincida con las expectativas para la puerta estándar. Si la matriz no es lo suficientemente larga, el comportamiento de esta función es indefinido, ya que leerá fuera de los límites de la matriz. Puede ser un puntero nulo si no hay qubits o parámetros para una puerta determinada. Puede consultar qk_gate_num_qubits y qk_gate_num_params para determinar cuántos qubits y parámetros se requieren para una puerta determinada.
El comportamiento es indefinido si no dag es un puntero válido y distinto de nulo a un QkDag.
Parámetros
- dag : un puntero al DAG al que se aplicará la puerta.
- gate – El « StandardGate » que se debe aplicar.
- qubits : el puntero a la matriz de índices
uint32_tde qubits a los que se va a añadir la puerta. Esto puede ser un puntero nulo si no hay qubits paragate(por ejemplo,QkGate_GlobalPhase). - params : el puntero a la matriz de
doublevalores que se utilizarán para los parámetros de la puerta. Esto puede ser un puntero nulo si no hay parámetros paragate(por ejemplo,QkGate_H). - front – Si
true, la puerta se aplica como la primera operación en los qubits especificados, en lugar de como la última.
Devuelve
El índice del nodo de operación recién añadido.
qk_dag_apply_measure
uint32_t qk_dag_apply_measure(QkDag *dag, uint32_t qubit, uint32_t clbit, bool front)
Aplicar una medida a un DAG.
Ejemplo
Mida todos los qubits en el índice clbit correspondiente al final del 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);
}Seguridad
El comportamiento es indefinido si no dag es un puntero alineado y distinto de nulo a un válido QkDag, o si qubit o clbit están fuera de rango.
Parámetros
- dag – El circuito al que se aplica.
- qubit : el índice qubit que se va a medir.
- clbit : el índice clbit en el que se almacenará el resultado.
- front : si se debe aplicar la medida al inicio del circuito. Normalmente
false.
Devuelve
El índice de nodo de la instrucción creada.
qk_dag_apply_reset
uint32_t qk_dag_apply_reset(QkDag *dag, uint32_t qubit, bool front)
Aplica un restablecimiento al DAG.
Ejemplos
Aplicar reinicios iniciales en todos los 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);
}Seguridad
El comportamiento es indefinido si no dag es un puntero alineado y distinto de nulo a un válido QkDag, o si qubit está fuera de rango.
Parámetros
- dag – El circuito al que se aplica.
- qubit : el índice del qubit que se va a restablecer.
- front : si se debe aplicar el reinicio al inicio del circuito. Normalmente
false.
Devuelve
El índice de nodo de la instrucción creada.
qk_dag_apply_barrier
uint32_t qk_dag_apply_barrier(QkDag *dag, const uint32_t *qubits, uint32_t num_qubits, bool front)
Aplica una barrera al DAG.
Ejemplos
Aplicar una barrera final en todos los qubits:
qk_dag_apply_barrier(dag, NULL, qk_dag_num_qubits(dag), false);Aplica una barrera al comienzo de un circuito en índices de qubits específicos:
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);Seguridad
El comportamiento es indefinido si:
dagno es un puntero alineado y distinto de nulo a un válidoQkDag,qubitsno está alineado o no es válido paranum_qubitslecturas de índices inicializados, dentro de los límites y no duplicados, a menos quequbitssea nulo.
Parámetros
- dag – El circuito al que se aplica.
- qubits : los índices de qubits a los que se aplicará la barrera. Esto puede ser nulo, en cuyo caso no
num_qubitsse lee, y la barrera se aplica a todos los qubits del DAG. - num_qubits : a cuántos qubits se aplica la barrera.
- frente : si se debe aplicar la barrera al inicio del circuito. Normalmente
false.
Devuelve
El índice de nodo de la instrucción creada.
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)
Aplicar una puerta unitaria a un DAG.
Los valores en matrix deben formar una matriz unitaria de tamaño correcto para el número de qubits. Los datos se copian desde el puntero y solo deben ser válidos para lecturas hasta que esta función regrese.
Véase: Convenciones de circuitos para obtener más detalles sobre las convenciones de etiquetado de bits y matrices de Qiskit.
Seguridad
El comportamiento es indefinido si se da cualquiera de las siguientes condiciones:
dagno es un puntero alineado y distinto de nulo a un válidoQkDag,matrixno es un puntero alineado a valores4**num_qubitsinicializados,qubitsno es un puntero alineado con valoresnum_qubitsinicializados.
Parámetros
- dag – El circuito al que se aplica.
- matriz : una matriz unitaria inicializada con prioridad de filas y un tamaño
4**num_qubitstotal de. - qubits : una matriz de índices
uint32_tdistintos de los qubits. - num_qubits : el número de qubits a los que se aplica la puerta.
- front : si se debe aplicar la puerta al inicio del circuito. Normalmente
false.
Devuelve
El índice de nodo de la instrucción creada.
qk_dag_op_node_gate_op
QkGate qk_dag_op_node_gate_op(const QkDag *dag, uint32_t node, double *out_params)
Recuperar la puerta estándar del nodo especificado.
Entra en pánico si el nodo no es una operación de puerta estándar.
Ejemplo
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);Seguridad
El comportamiento es indefinido si no dag es un puntero válido y distinto de nulo a un QkDag. Si out_params no es NULL, debe apuntar a un búfer lo suficientemente grande como para contener todos los parámetros de la puerta; de lo contrario, el comportamiento es indefinido, ya que esta función escribirá más allá de sus límites. Puede comprobar qk_dag_op_node_num_params para determinar cuántos parámetros se requieren para cualquier nodo de operación dado.
Parámetros
- dag : un puntero al DAG.
- nodo : el nodo de operación del que se obtiene la puerta estándar.
- out_params : un búfer que se rellenará con los parámetros de la puerta o NULL si no se desean.
Devuelve
El valor de la puerta.
qk_dag_op_node_unitary
void qk_dag_op_node_unitary(const QkDag *dag, uint32_t node, QkComplex64 *out)
Copia la matriz unitaria del índice de nodo correspondiente.
Entra en pánico si el nodo no es una puerta unitaria.
Seguridad
El comportamiento es indefinido si no dag es un puntero distinto de nulo a un válido QkDag, si out no está alineado o si no out es válido para 4**num_qubits escrituras de QkComplex64.
Parámetros
- dag : el circuito desde el que se lee.
- nodo : el índice del nodo de la instrucción de matriz unitaria.
- out – Memoria asignada y alineada para valores
4**num_qubitscomplejos en orden de fila mayor, dondenum_qubitses el número de qubits al que se aplica la puerta.
qk_dag_op_node_kind
QkOperationKind qk_dag_op_node_kind(const QkDag *dag, uint32_t node)
Obtener el «tipo» de un nodo de operación.
El resultado se puede utilizar en una instrucción switch para enviar el manejo adecuado al iterar sobre los nodos de operación.
Entra en pánico si no node es un nodo de operación.
Seguridad
El comportamiento es indefinido si no dag es un puntero válido y distinto de nulo a un QkDag.
Parámetros
- dag : un puntero al DAG.
- nodo : el nodo de operación del que se obtiene el «tipo».
Devuelve
El «tipo» del nodo.
qk_dag_successors
QkDagNeighbors qk_dag_successors(const QkDag *dag, uint32_t node)
Recupera los sucesores del nodo especificado.
La matriz de sucesores y su longitud se devuelven como una QkDagNeighbors estructura, donde cada elemento de la matriz corresponde a un índice de nodo DAG. Debe llamar a la qk_dag_neighbors_clear función cuando haya terminado para liberar la memoria asignada a la estructura.
Ejemplo
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);Seguridad
El comportamiento es indefinido si no dag es un puntero válido y distinto de nulo a un QkDag.
Parámetros
- dag : un puntero al DAG.
- nodo : el nodo del que se obtienen los sucesores.
Devuelve
Una instancia de la QkDagNeighbors estructura con la información de los sucesores.
qk_dag_predecessors
QkDagNeighbors qk_dag_predecessors(const QkDag *dag, uint32_t node)
Recupera los predecesores del nodo especificado.
La matriz de predecesores y su longitud se devuelven como una QkDagNeighbors estructura, donde cada elemento de la matriz corresponde a un índice de nodo DAG. Debe llamar a la qk_dag_neighbors_clear función cuando haya terminado para liberar la memoria asignada a la estructura.
Ejemplo
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);Seguridad
El comportamiento es indefinido si no dag es un puntero válido y distinto de nulo a un QkDag.
Parámetros
- dag : un puntero al DAG.
- nodo : el nodo del que se obtienen los predecesores.
Devuelve
Una instancia de la QkDagNeighbors estructura con la información de los predecesores.
qk_dag_neighbors_clear
void qk_dag_neighbors_clear(QkDagNeighbors *neighbors)
Borrar los campos de la estructura de QkDagNeighbors entrada.
La función desasigna la memoria apuntada por el neighbors campo y la establece en NULL. También establece el num_neighbors campo en 0.
Seguridad
El comportamiento es indefinido si no neighbors es un puntero válido y distinto de nulo a un QkDagNeighbors objeto rellenado con o qk_dag_successors qk_dag_predecessors.
Parámetros
- vecinos : un puntero a un
QkDagNeighborsobjeto.
qk_dag_get_instruction
void qk_dag_get_instruction(const QkDag *dag, uint32_t index, QkCircuitInstruction *instruction)
Devuelve los detalles de una instrucción en el circuito.
Esto es un espejo de qk_circuit_get_instruction. También puede utilizar métodos individuales como qk_dag_op_node_gate_op para obtener propiedades individuales.
Debe llamar qk_circuit_instruction_clear para restablecer el QkCircuitInstruction antes de volver a utilizarlo o desecharlo.
Ejemplos
Iterar a través de un DAG para encontrar qué qubits tienen 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);Seguridad
El comportamiento es indefinido si o dag no instruction son punteros válidos, alineados y distintos de nulo al tipo de datos relevante. Los campos de no instruction es necesario inicializarlos.
Parámetros
- dag : el circuito desde el que se recupera la instrucción.
- índice : el índice del nodo. Es un error pasar un índice que no es un nodo operativo válido.
- instrucción : un punto donde escribir el
QkCircuitInstruction.
qk_dag_compose
QkExitCode qk_dag_compose(QkDag *dag, const QkDag *other, const uint32_t *qubits, const uint32_t *clbits)
Componer el other DAG en la dag instancia con la opción de que un subconjunto de cables de entrada de other se asigne a un subconjunto de cables de salida de dag.
other puede incluir un número menor o igual de cables para cada tipo.
Ejemplo
// 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);Seguridad
El comportamiento es indefinido si dag o no other son punteros válidos y distintos de nulo a un QkDag. Si qubit ni clbit son NULL, debe contener una cantidad menor o igual a la que posee el circuito.
Parámetros
- dag : un puntero al DAG que se va a componer.
- otro : un puntero al DAG con el que
dagcomponer. - qubits : una lista de índices que representan los cables qubit sobre los que se va a componer.
- clbits : una lista de índices que representan los cables clbit sobre los que componer.
Devuelve
QkExitCode_Success tras una descomposición satisfactoria; de lo contrario, un código de error específico de DAG que indica la causa del fallo.
qk_dag_free
void qk_dag_free(QkDag *dag)
Libera el DAG.
Ejemplo
QkDag *dag = qk_dag_new();
qk_dag_free(dag);Seguridad
El comportamiento es indefinido si no dag es nulo ni un puntero válido a un QkDag.
Parámetros
- dag : un puntero al DAG que se va a liberar.
qk_dag_to_circuit
QkCircuit *qk_dag_to_circuit(const QkDag *dag)
Convertir un DAG dado en un circuito.
El nuevo circuito se copia del DAG; la referencia dag original sigue siendo propiedad del llamante y sigue siendo necesario liberarla con qk_dag_free. Debe liberar el circuito devuelto con qk_circuit_free cuando haya terminado de utilizarlo.
Ejemplo
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);Seguridad
El comportamiento es indefinido si no dag es un puntero válido y distinto de nulo a un QkDag.
Parámetros
- dag : un puntero al DAG desde el que crear el circuito.
Devuelve
Un indicador del nuevo circuito.
qk_dag_topological_op_nodes
void qk_dag_topological_op_nodes(const QkDag *dag, uint32_t *out_order)
Devuelve los nodos de operación en el DAG ordenados por orden topológico.
Ejemplo
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);Seguridad
El comportamiento es indefinido si no dag es un puntero válido y distinto de nulo a un QkDag o si no out_order es un puntero válido y distinto de nulo a una secuencia de qk_dag_num_op_nodes(dag) elementos consecutivos de uint32_t.
Parámetros
- dag : un puntero al DAG.
- out_order : un puntero a una matriz de
qk_dag_num_op_nodes(dag)elementos de tipouint32_t, donde esta función escribirá la salida.
qk_dag_substitute_node_with_dag
void qk_dag_substitute_node_with_dag(QkDag *dag, uint32_t node, const QkDag *replacement)
Sustituir un nodo de un circuito QkDag por un subcircuito especificado por otro QkDag
Ejemplo
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);Seguridad
El comportamiento es indefinido si dag y no replacement son punteros válidos y distintos de nulo a un QkDag.
Parámetros
- dag : un puntero al DAG.
- nodo : el índice del nodo de la operación que se va a sustituir por el otro
QkDag. Este debe ser el índice de nodo para un nodo de operación endagy el recuento de qargs y cargs debe coincidir con el número de qubits y clbits enreplacement. - reemplazo – El otro
QkDagpara reemplazarnodecon. Este dag debe tener el mismo número de qubits que la operación paranode. El orden de los bits del nodo se gestionará por orden, por lo queqargs[0]paranodese asignará aqubits[0]enreplacement,qargs[1]aqubits[0], etc. El mismo patrón se aplica también a los bits clásicos.
qk_dag_copy_empty_like
QkDag *qk_dag_copy_empty_like(const QkDag *dag, QkVarsMode vars_mode, QkBlocksMode blocks_mode)
Devuelve una copia de sí mismo con la misma estructura, pero vacía.
Esa estructura incluye:
- nombre y otros metadatos
- fase global
- duración
- todos los qubits y clbits, incluidos los registros.
Ejemplo
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);Seguridad
El comportamiento es indefinido si no dag es un puntero válido a un QkDag.
Parámetros
- dag : un puntero al DAG que se va a copiar.
- vars_mode : modo para manejar variables clásicas.
- blocks_mode : modo para gestionar bloques.
Devuelve
El puntero al 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)
Sustituye un bloque contiguo no vacío de nodos en un QkDag por una única puerta unitaria correspondiente a la matriz unitaria especificada.
Al realizar la sustitución, los nodos del bloque se eliminan y se sustituyen por un nuevo nodo que actúa sobre los qubits indicados.
Ejemplo
// 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);Seguridad
El comportamiento es indefinido si se da cualquiera de las siguientes condiciones:
dagno es un puntero alineado y distinto de nulo a un válidoQkDag,qubitsno es un puntero alineado con valoresnum_qubitsinicializados.matrixno es un puntero alineado a valores4**num_qubitsinicializados,block_idsno es un puntero alineado a valoresnum_block_idsinicializados.
Parámetros
- dag – Puntero al DAG.
- num_block_ids – Número de entradas en
block_ids. Este número debe ser distinto de cero. - block_ids : puntero a una matriz no vacía de nodos que se van a sustituir.
- matriz – Puntero a una matriz unitaria inicializada con orden de filas de tamaño
4**num_qubits. - num_qubits : el número de qubits sobre los que actúa la puerta unitaria resultante.
- qubits : puntero a una matriz de índices de qubits
uint32_tdistintos. Cada entrada especifica el índice del qubit DAG que corresponde a la posición del argumento respectivo en la puerta unitaria. - cycle_check – Si
truese activa, la función comprueba si sustituir el nodo proporcionadoblock_idspor un único nodo introduciría un ciclo en el DAG (lo que invalidaría el DAG). Si se creara un ciclo, el DAG no se modificaría yUINT32_MAXse devolvería tal cual. Esta comprobación conlleva una pérdida de rendimiento. Si puedes garantizar que el bloque proporcionadoblock_idses contiguo y que no dará lugar a un ciclo al reducirse a un único nodo, se puede establecer enfalse.
Devuelve
El índice del nodo de operación recién añadido, o UINT32_MAX si cycle_check es true y la sustitución daría lugar a un 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)
Sustituye una operación en un nodo de un grafo QkDag por una puerta unitaria correspondiente a la matriz unitaria especificada.
La nueva operación debe tener la misma forma que la operación sustituida. Los qargs y cargs del nodo seguirán siendo los mismos.
Ejemplo
// 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);Seguridad
El comportamiento es indefinido si se da cualquiera de las siguientes condiciones:
dagno es un puntero alineado y distinto de nulo a un válidoQkDag,matrixno es un puntero alineado a valores4**num_qubitsinicializados,
Parámetros
- dag – Puntero al DAG.
- nodo : el nodo cuya operación se sustituye. El número de qubits en la operación sustituida debe ser igual a
num_qubitsy el número de clbits debe ser0. - matriz – Puntero a una matriz unitaria inicializada con orden de filas de tamaño
4**num_qubits. - num_qubits : el número de qubits sobre los que actúa el operador unitario.
qk_dag_to_python
PyObject *qk_dag_to_python(QkDag *dag)
Pasa la propiedad de un QkDag objeto a « Python ».
No es seguro utilizar el QkDag puntero después de llamar a esta función. En particular, no debes intentar borrarlo ni liberarlo. El autor de la llamada debe ser el propietario del objeto QkDag, y no tener una referencia prestada (por ejemplo, un objeto QkDag * recuperado de no qk_dag_borrow_from_python es de su propiedad).
Seguridad
La persona que llama debe estar conectada a un intérprete de Python. El comportamiento es indefinido si no dag es un puntero válido y no nulo a un objeto inicializado y del que se tiene propiedad QkDag.
Parámetros
- dag – El objeto en cuestión.
Devuelve
Una referencia de tipo « Python » al objeto.
qk_dag_borrow_from_python
QkDag *qk_dag_borrow_from_python(PyObject *ob)
Obtener un QkDag puntero de un objeto Python.
Esto toma prestada una referencia de tipo « Python » y extrae el QkDag puntero correspondiente, siempre que sea del tipo adecuado. El puntero devuelto se toma prestado del ob puntero. Si el PyObject tipo no es el correcto, el valor de retorno es NULL y se establece el estado de excepción del intérprete de Python.
Para llamar a esta función, debes estar conectado a un intérprete de Python.
También puedes utilizar qk_dag_convert_from_python, que lógicamente es exactamente igual que esta función, pero que se puede emplear directamente como función «convertidora» para la PyArg_Parse* familia de funciones de conversión de Python.
Seguridad
La persona que llama debe estar conectada a un intérprete de Python. El comportamiento es indefinido si no ob es un puntero válido y no nulo a un objeto Python.
Parámetros
- ob : un objeto de tipo « Python » tomado de otro lenguaje.
Devuelve
Un puntero al objeto nativo, o bien, NULL si el objeto Python es de un tipo incorrecto.
qk_dag_convert_from_python
int qk_dag_convert_from_python(PyObject *object, void *address)
Recuperar un puntero DAG de un objeto Python.
Esto toma prestada una referencia de tipo « Python » y extrae el QkDag puntero correspondiente a address, siempre que sea del tipo correcto. El puntero devuelto se toma prestado del object puntero. Si no es PyObject del tipo correcto, el valor de retorno es 1, se establece el estado de excepción del intérprete de Python, y address no sufre cambios.
Para llamar a esta función, debes estar conectado a un intérprete de Python.
También puedes usar qk_dag_borrow_from_python, que, lógicamente, es exactamente lo mismo que esto, pero con una sintaxis más natural para su uso directo.
Seguridad
La persona que llama debe estar conectada a un intérprete de Python. El comportamiento es indefinido si no object es un puntero válido y no nulo a un objeto Python, o si no address es un puntero a datos modificables del tipo correcto.
Parámetros
- objeto : un objeto de tipo
Pythontomado en préstamo. - dirección : la ubicación en la que se escribirá la salida.
Devuelve
1 si se realiza correctamente, 0 si falla.