Skip to main content
IBM Quantum Platform

QkDag

typedef struct QkDag QkDag

La QkDag struttura espone un'interfaccia di basso livello alla rappresentazione del grafico aciclico diretto (DAG) del transpiler Qiskit di un circuito quantistico da utilizzare nei passaggi del transpiler. Espone solo ciò che è definito nel modello di dati interno di Qiskit. Pertanto manca alcune funzionalità disponibili nella classe di DAGCircuit livello superiore Python.

L'API C attualmente supporta solo la creazione di DAG che contengono operazioni definite nel modello di dati Rust interno di Qiskit. In genere questo include solo i gate presenti nella libreria standard dei gate, le operazioni standard non unitarie (attualmente Barrier, Measure, Reset, e Delay) e UnitaryGate. Questa funzionalità verrà ampliata nel tempo, man mano che il modello di dati Rust verrà esteso per supportare in modo nativo ulteriori funzionalità.


Tipi di dati

QkDagNodeType

enum QkDagNodeType

Il tipo di nodo in un QkDag.

I nodi operativi rappresentano un'istruzione applicata. Il resto dei nodi sono considerati nodi "wire" e rappresentano i punti finali delle catene di dipendenza dei dati del DAG.

Valori:

enumeratore QkDagNodeType_Operation

Nodo operativo.

enumeratore QkDagNodeType_QubitIn

Nodo di inizio cavo Qubit.

enumeratore QkDagNodeType_QubitOut

Nodo terminale del cavo Qubit.

enumeratore QkDagNodeType_ClbitIn

Nodo iniziale del filo Clbit.

enumeratore QkDagNodeType_ClbitOut

Nodo terminale del cavo Clbit.

enumeratore QkDagNodeType_VarIn

Nodo classico con avvio a filo variabile.

enumeratore QkDagNodeType_VarOut

Nodo terminale classico a filo variabile.

QkOperationKind

enum QkOperationKind

Il tipo di operazione.

Questo viene restituito quando si interroga un particolare nodo nel grafico con qk_dag_op_node_kind, e ha lo scopo di consentire al chiamante di inviare (ad esempio tramite uno "switch") chiamate specifiche per il tipo di operazione contenuta.

Valori:

enumeratore QkOperationKind_Gate

enumeratore QkOperationKind_Barrier

enumeratore QkOperationKind_Delay

enumeratore QkOperationKind_Measure

enumeratore QkOperationKind_Reset

enumeratore QkOperationKind_Unitary

enumeratore QkOperationKind_PauliProductMeasurement

enumeratore QkOperationKind_ControlFlow

enumeratore QkOperationKind_Unknown

Questa variante è utilizzata come tipo opaco per operazioni non ancora implementate nel modello di dati nativo.

censitore QkOperationKind_PauliProductRotation

QkDagNeighbors

struct QkDagNeighbors

Una struttura per memorizzare le informazioni sui successori e sui predecessori recuperate rispettivamente da qk_dag_successors e qk_dag_predecessors.

Questo oggetto è di sola lettura da C. Per soddisfare le garanzie di sicurezza di qk_dag_neighbors_clear, non è consentito sovrascrivere alcun dato inizializzato da qk_dag_successors o qk_dag_predecessors, compresi i dati puntati.

const uint32_t *vicini

Matrice di dimensione num_neighbors degli indici dei nodi.

dimensione_t numero_vicini

La lunghezza neighbors dell'array.


Funzioni

qk_dag_new

QkDag *qk_dag_new(void)

Costruisci un nuovo DAG vuoto.

Una volta terminato, è qk_dag_free necessario liberare il DAG restituito con.

Esempio

QkDag *empty = qk_dag_new();

Risultati

Un puntatore al DAG creato.

qk_dag_add_quantum_register

void qk_dag_add_quantum_register(QkDag *dag, const QkQuantumRegister *reg)

Aggiungi un registro quantistico al DAG.

Esempio

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);

Sicurezza

Il comportamento è indefinito se non dag è un puntatore valido e diverso da null a un QkDag e se non reg è un puntatore valido e diverso da null a un QkQuantumRegister.

Parametri

  • dag – Un puntatore al DAG.
  • reg – Un puntatore al registro quantistico.

qk_dag_add_classical_register

void qk_dag_add_classical_register(QkDag *dag, const QkClassicalRegister *reg)

Aggiungi un registro classico al DAG.

Esempio

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);

Sicurezza

Il comportamento è indefinito se non dag è un puntatore valido e diverso da null a un QkDag e se non reg è un puntatore valido e diverso da null a un QkClassicalRegister.

Parametri

  • dag – Un puntatore al DAG.
  • reg – Un puntatore al registro classico.

qk_dag_num_qubits

uint32_t qk_dag_num_qubits(const QkDag *dag)

Ottieni il numero di qubit contenuti nel DAG.

Esempio

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);

Sicurezza

Il comportamento è indefinito se non dag è un puntatore valido e non nullo a un QkDag.

Parametri

  • dag – Un puntatore al DAG.

Risultati

Il numero di qubit su cui è definito il DAG.

qk_dag_num_clbits

uint32_t qk_dag_num_clbits(const QkDag *dag)

Ottieni il numero di clbit contenuti nel DAG.

Esempio

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);

Sicurezza

Il comportamento è indefinito se non dag è un puntatore valido e non nullo a un QkDag.

Parametri

  • dag – Un puntatore al DAG.

Risultati

Il numero di clbit su cui è definito il DAG.

qk_dag_num_op_nodes

size_t qk_dag_num_op_nodes(const QkDag *dag)

Restituisce il numero totale di nodi operativi nel DAG.

Esempio

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);

Sicurezza

Il comportamento è indefinito se non dag è un puntatore valido e non nullo a un QkDag.

Parametri

  • dag – Un puntatore al DAG.

Risultati

Il numero totale di istruzioni nel DAG.

qk_dag_global_phase

QkParam *qk_dag_global_phase(const QkDag *dag)

Recupera la fase globale del DAG.

Questa funzione restituisce una copia della fase globale del DAG e il valore deve essere liberato tramite :c:func:qk_param_free dopo l'utilizzo.

Esempio

QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(24, "my_register");
qk_dag_add_quantum_register(dag, qr);
QkParam *global_phase = qk_dag_global_phase(dag);
qk_param_free(global_phase);
qk_quantum_register_free(qr);
qk_dag_free(dag);

Sicurezza

Il comportamento è indefinito se non dag è un puntatore valido e non nullo a un QkDag.

Parametri

  • dag – Un puntatore al DAG.

Risultati

La fase globale del DAG.

qk_dag_set_global_phase

QkExitCode qk_dag_set_global_phase(QkDag *dag, const QkParam *phase)

Imposta la fase globale del DAG.

Questa funzione copia la nuova fase globale al momento della sua impostazione, pertanto chi la chiama mantiene la proprietà della QkParam fase, e il valore della fase deve essere liberato tramite :c:func:qk_param_free dopo l'impostazione.

Esempio

QkDag *dag = qk_dag_new();
QkParam *new_global_phase = qk_param_from_double(1.23);
qk_dag_set_global_phase(dag, new_global_phase);
qk_param_free(new_global_phase);
qk_dag_free(dag);

Sicurezza

Il comportamento è indefinito se dag non è un puntatore valido e non nullo a un QkDag e se phase non è un puntatore valido e non nullo a un QkParam.

Parametri

  • dag – Un puntatore al DAG.
  • fase – Un puntatore alla fase globale da impostare.

Risultati

QkExitCode_Success una volta impostata correttamente la fase globale. In caso di errore, QkExitCode_ParameterError descrive gli errori generici che si verificano quando si tenta di tracciare i simboli dei parametri, come ad esempio valori di parametro non validi. In caso contrario, QkExitCode_DagError indica una causa dell'errore specifica del DAG.

qk_dag_node_type

QkDagNodeType qk_dag_node_type(const QkDag *dag, uint32_t node)

Ottieni il tipo del nodo specificato.

Il risultato può essere utilizzato in un'istruzione switch per inviare la gestione corretta durante l'iterazione su nodi di tipo sconosciuto.

Sicurezza

Il comportamento è indefinito se non dag è un puntatore valido e non nullo a un QkDag.

Parametri

  • dag – Un puntatore al DAG.
  • nodo – Il nodo di cui ottenere il tipo.

Risultati

Il tipo del nodo.

qk_dag_qubit_in_node

uint32_t qk_dag_qubit_in_node(const QkDag *dag, uint32_t qubit)

Recupera l'indice del nodo di ingresso del filo corrispondente al qubit specificato.

Sicurezza

Il comportamento è indefinito se non dag è un puntatore valido e non nullo a un QkDag.

Parametri

  • dag – Un puntatore al DAG.
  • qubit – Il qubit da cui ottenere l'indice del nodo di input.

Risultati

Il nodo di ingresso del filo qubit.

qk_dag_qubit_out_node

uint32_t qk_dag_qubit_out_node(const QkDag *dag, uint32_t qubit)

Recupera l'indice del nodo di uscita del filo corrispondente al qubit specificato.

Sicurezza

Il comportamento è indefinito se non dag è un puntatore valido e non nullo a un QkDag.

Parametri

  • dag – Un puntatore al DAG.
  • qubit – Il qubit da cui ottenere l'indice del nodo di output.

Risultati

Il nodo di uscita del filo qubit.

qk_dag_clbit_in_node

uint32_t qk_dag_clbit_in_node(const QkDag *dag, uint32_t clbit)

Recupera l'indice del nodo di ingresso del cavo corrispondente al clbit specificato.

Sicurezza

Il comportamento è indefinito se non dag è un puntatore valido e non nullo a un QkDag.

Parametri

  • dag – Un puntatore al DAG.
  • clbit – Il clbit da cui ottenere l'indice del nodo di input.

Risultati

Il nodo di ingresso del cavo clbit.

qk_dag_clbit_out_node

uint32_t qk_dag_clbit_out_node(const QkDag *dag, uint32_t clbit)

Recupera l'indice del nodo di uscita del cavo corrispondente al clbit specificato.

Sicurezza

Il comportamento è indefinito se non dag è un puntatore valido e non nullo a un QkDag.

Parametri

  • dag – Un puntatore al DAG.
  • clbit – Il clbit da cui ottenere l'indice del nodo di output.

Risultati

Il nodo di uscita del cavo clbit.

qk_dag_wire_node_value

uint32_t qk_dag_wire_node_value(const QkDag *dag, uint32_t node)

Recupera il valore di un nodo endpoint wire.

Sicurezza

Il comportamento è indefinito se non dag è un puntatore valido e non nullo a un QkDag.

Parametri

  • dag – Un puntatore al DAG.
  • nodo – Il nodo finale da cui ottenere il valore del cavo.

Risultati

Il valore (ad esempio qubit, clbit o var) all'interno del nodo endpoint.

qk_dag_op_node_num_qubits

uint32_t qk_dag_op_node_num_qubits(const QkDag *dag, uint32_t node)

Ottiene il numero di qubit del nodo operativo specificato.

Va nel panico se il nodo non è un'operazione.

Sicurezza

Il comportamento è indefinito se non dag è un puntatore valido e non nullo a un QkDag.

Parametri

  • dag – Un puntatore al DAG.
  • nodo – Il nodo operativo da cui ottenere il numero di qubit.

Risultati

Il numero di qubit dell'operazione.

qk_dag_op_node_num_clbits

uint32_t qk_dag_op_node_num_clbits(const QkDag *dag, uint32_t node)

Ottiene il numero di clbit del nodo operativo specificato.

Va nel panico se il nodo non è un'operazione.

Sicurezza

Il comportamento è indefinito se non dag è un puntatore valido e non nullo a un QkDag.

Parametri

  • dag – Un puntatore al DAG.
  • nodo – Il nodo operativo da cui ottenere il numero di clbit.

Risultati

Il numero di clbit dell'operazione.

qk_dag_op_node_num_params

uint32_t qk_dag_op_node_num_params(const QkDag *dag, uint32_t node)

Ottiene il numero di parametri del nodo operazione specificato.

Va nel panico se il nodo non è un'operazione.

Sicurezza

Il comportamento è indefinito se non dag è un puntatore valido e non nullo a un QkDag.

Parametri

  • dag – Un puntatore al DAG.
  • nodo – Il nodo operativo da cui ottenere il numero di parametri.

Risultati

Il numero di parametri dell'operazione.

qk_dag_op_node_qubits

const uint32_t *qk_dag_op_node_qubits(const QkDag *dag, uint32_t node)

Recupera i qubit del nodo operativo specificato.

Va nel panico se il nodo non è un'operazione.

Sicurezza

Il comportamento è indefinito se non dag è un puntatore valido e non nullo a un QkDag.

Parametri

  • dag – Un puntatore al DAG.
  • nodo – Il nodo operativo da cui ottenere i qubit.

Risultati

Un puntatore ai qubit. Utilizzare qk_dag_op_node_num_qubits per determinare il numero di elementi.

qk_dag_op_node_clbits

const uint32_t *qk_dag_op_node_clbits(const QkDag *dag, uint32_t node)

Recupera i clbit del nodo operativo specificato.

Va nel panico se il nodo non è un'operazione.

Sicurezza

Il comportamento è indefinito se non dag è un puntatore valido e non nullo a un QkDag.

Parametri

  • dag – Un puntatore al DAG.
  • nodo – Il nodo operativo da cui ottenere i clbit.

Risultati

Un puntatore ai clbits. Utilizzare qk_dag_op_node_num_clbits per determinare il numero di elementi.

qk_dag_apply_gate

uint32_t qk_dag_apply_gate(QkDag *dag, QkGate gate, const uint32_t *qubits, const double *params, bool front)

Applicare un QkGate al DAG.

Esempio

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);

Sicurezza

I tipi qubits``params e devono essere puntatori a un array di uint32_t e double rispettivamente, dove la lunghezza corrisponde alle aspettative per il gate standard. Se l'array non è sufficientemente lungo, il comportamento di questa funzione è indefinito poiché leggerà al di fuori dei limiti dell'array. Può essere un puntatore nullo se non ci sono qubit o parametri per un dato gate. È possibile controllare qk_gate_num_qubits e qk_gate_num_params per determinare quanti qubit e parametri sono necessari per un determinato gate.

Il comportamento è indefinito se non dag è un puntatore valido e non nullo a un QkDag.

Parametri

  • dag – Un puntatore al DAG a cui applicare il gate.
  • gate – L' StandardGate o da compilare.
  • qubit – Il puntatore all'array degli indici uint32_t dei qubit su cui aggiungere il gate. Questo può essere un puntatore nullo se non ci sono qubit per gate (ad esempio QkGate_GlobalPhase).
  • params – Il puntatore all'array di double valori da utilizzare per i parametri del gate. Questo può essere un puntatore nullo se non ci sono parametri per gate (ad esempio QkGate_H).
  • front – Se true, il gate viene applicato come prima operazione sui qubit specificati, anziché come ultima.

Risultati

L'indice del nodo operativo appena aggiunto.

qk_dag_apply_measure

uint32_t qk_dag_apply_measure(QkDag *dag, uint32_t qubit, uint32_t clbit, bool front)

Applicare una misura a un DAG.

Esempio

Misura tutti i qubit nell'indice clbit corrispondente alla fine 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);
}

Sicurezza

Il comportamento è indefinito se non dag è un puntatore allineato e diverso da null a un valido QkDag, oppure se qubit o clbit sono fuori intervallo.

Parametri

  • dag – Il circuito a cui applicarsi.
  • qubit – L'indice qubit da misurare.
  • clbit – L'indice clbit in cui memorizzare il risultato.
  • front – Se applicare la misura all'inizio del circuito. Di solito false.

Risultati

L'indice del nodo dell'istruzione creata.

qk_dag_apply_reset

uint32_t qk_dag_apply_reset(QkDag *dag, uint32_t qubit, bool front)

Applicare un ripristino al DAG.

Esempi

Applicare i reset iniziali su tutti i qubit.

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);
}

Sicurezza

Il comportamento è indefinito se non dag è un puntatore allineato e diverso da null a un valido QkDag, oppure se qubit è fuori intervallo.

Parametri

  • dag – Il circuito a cui applicarsi.
  • qubit – L'indice qubit da reimpostare.
  • frontale – Se applicare il reset all'inizio del circuito. Di solito false.

Risultati

L'indice del nodo dell'istruzione creata.

qk_dag_apply_barrier

uint32_t qk_dag_apply_barrier(QkDag *dag, const uint32_t *qubits, uint32_t num_qubits, bool front)

Applicare una barriera al DAG.

Esempi

Applicare una barriera finale su tutti i qubit:

qk_dag_apply_barrier(dag, NULL, qk_dag_num_qubits(dag), false);

Applicare una barriera all'inizio di un circuito su indici qubit specificati:

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);

Sicurezza

Il comportamento è indefinito se:

  • dag non è un puntatore allineato e diverso da zero a un valido QkDag,
  • qubits non è allineato o non è valido per num_qubits le letture di indici inizializzati, entro i limiti e non duplicati, a meno che qubits non sia nullo.

Parametri

  • dag – Il circuito a cui applicarsi.
  • qubit – Gli indici dei qubit a cui applicare la barriera. Questo valore può essere nullo, nel qual caso non num_qubits viene letto e la barriera viene applicata a tutti i qubit nel DAG.
  • num_qubits – A quanti qubit si applica la barriera.
  • frontale – Se applicare la barriera all'inizio del circuito. Di solito false.

Risultati

L'indice del nodo dell'istruzione creata.

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)

Applicare un gate unitario a un DAG.

I valori in matrix devono formare una matrice unitaria row-major delle dimensioni corrette per il numero di qubit. I dati vengono copiati dal puntatore e devono essere validi per la lettura solo fino al ritorno di questa funzione.

Vedi: Convenzioni dei circuiti per i dettagli sulle convenzioni di etichettatura dei bit e delle matrici di Qiskit.

Sicurezza

Il comportamento è indefinito se si verifica una delle seguenti condizioni:

  • dag non è un puntatore allineato e diverso da zero a un valido QkDag,
  • matrix non è un puntatore allineato a 4**num_qubits valori inizializzati,
  • qubits non è un puntatore allineato ai num_qubits valori inizializzati.

Parametri

  • dag – Il circuito a cui applicarsi.
  • matrice – Una matrice unitaria inizializzata con priorità sulle righe di dimensione totale 4**num_qubits.
  • qubit – Un array di indici uint32_t distinti dei qubit.
  • num_qubits – Il numero di qubit a cui si applica il gate.
  • frontale – Se applicare il gate all'inizio del circuito. Di solito false.

Risultati

L'indice del nodo dell'istruzione creata.

qk_dag_op_node_gate_op

QkGate qk_dag_op_node_gate_op(const QkDag *dag, uint32_t node, double *out_params)

Recupera il gate standard del nodo specificato.

Va in panico se il nodo non è un'operazione di gate standard.

Esempio

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);

Sicurezza

Il comportamento è indefinito se non dag è un puntatore valido e non nullo a un QkDag. Se out_params non è NULL, deve puntare a un buffer sufficientemente grande da contenere tutti i parametri del gate, altrimenti il comportamento è indefinito poiché questa funzione scriverà oltre i suoi limiti. È possibile verificare qk_dag_op_node_num_params per determinare quanti parametri sono richiesti per un dato nodo operativo.

Parametri

  • dag – Un puntatore al DAG.
  • nodo – Il nodo operativo da cui ottenere il gate standard.
  • out_params – Un buffer da riempire con i parametri del gate o NULL se non sono richiesti.

Risultati

Il valore del gate.

qk_dag_op_node_unitary

void qk_dag_op_node_unitary(const QkDag *dag, uint32_t node, QkComplex64 *out)

Copia la matrice unitaria dell'indice del nodo corrispondente.

Va nel panico se il nodo non è un gate unitario.

Sicurezza

Il comportamento è indefinito se non dag è un puntatore non nullo a un valido QkDag, se out non è allineato o se non out è valido per 4**num_qubits scritture di QkComplex64.

Parametri

  • dag – Il circuito da cui leggere.
  • nodo – L'indice del nodo dell'istruzione della matrice unitaria.
  • out – Memoria allocata e allineata per 4**num_qubits valori complessi in ordine row-major, dove num_qubits è il numero di qubit a cui si applica il gate.

qk_dag_op_node_kind

QkOperationKind qk_dag_op_node_kind(const QkDag *dag, uint32_t node)

Ottieni il "tipo" di un nodo operativo.

Il risultato può essere utilizzato in un'istruzione switch per inviare la gestione corretta durante l'iterazione sui nodi operativi.

Va nel panico se non node è un nodo operativo.

Sicurezza

Il comportamento è indefinito se non dag è un puntatore valido e non nullo a un QkDag.

Parametri

  • dag – Un puntatore al DAG.
  • nodo – Il nodo operativo da cui ottenere il "tipo".

Risultati

Il "tipo" del nodo.

qk_dag_successors

QkDagNeighbors qk_dag_successors(const QkDag *dag, uint32_t node)

Recupera i successori del nodo specificato.

L'array dei successori e la sua lunghezza vengono restituiti come una QkDagNeighbors struttura, in cui ogni elemento dell'array corrisponde a un indice di nodo DAG. È necessario chiamare la qk_dag_neighbors_clear funzione al termine per liberare la memoria allocata per la struttura.

Esempio

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);

Sicurezza

Il comportamento è indefinito se non dag è un puntatore valido e non nullo a un QkDag.

Parametri

  • dag – Un puntatore al DAG.
  • nodo – Il nodo da cui ottenere i successori.

Risultati

Un'istanza della QkDagNeighbors struttura con le informazioni sui successori.

qk_dag_predecessors

QkDagNeighbors qk_dag_predecessors(const QkDag *dag, uint32_t node)

Recupera i predecessori del nodo specificato.

L'array dei predecessori e la sua lunghezza vengono restituiti come una QkDagNeighbors struttura, in cui ogni elemento dell'array corrisponde a un indice di nodo DAG. È necessario chiamare la qk_dag_neighbors_clear funzione al termine per liberare la memoria allocata per la struttura.

Esempio

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);

Sicurezza

Il comportamento è indefinito se non dag è un puntatore valido e non nullo a un QkDag.

Parametri

  • dag – Un puntatore al DAG.
  • nodo – Il nodo da cui ottenere i predecessori.

Risultati

Un'istanza della QkDagNeighbors struttura con le informazioni sui predecessori.

qk_dag_neighbors_clear

void qk_dag_neighbors_clear(QkDagNeighbors *neighbors)

Cancella i campi della struttura di QkDagNeighbors input.

La funzione dealloca la memoria puntata dal neighbors campo e la imposta su NULL. Imposta anche il num_neighbors campo su 0.

Sicurezza

Il comportamento è indefinito se non neighbors è un puntatore valido e non nullo a un QkDagNeighbors oggetto popolato con o qk_dag_successors qk_dag_predecessors.

Parametri

  • vicini – Un puntatore a un QkDagNeighbors oggetto.

qk_dag_get_instruction

void qk_dag_get_instruction(const QkDag *dag, uint32_t index, QkCircuitInstruction *instruction)

Restituisce i dettagli relativi a un'istruzione nel circuito.

Questo è un mirror di qk_circuit_get_instruction. È inoltre possibile utilizzare metodi individuali come qk_dag_op_node_gate_op per ottenere singole proprietà.

È necessario chiamare qk_circuit_instruction_clear per reimpostare il QkCircuitInstruction prima di riutilizzarlo o smaltirlo.

Esempi

Iterare attraverso un DAG per trovare quali qubit hanno misure su di essi:

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);

Sicurezza

Il comportamento è indefinito se o dag non instruction sono puntatori validi, allineati e non nulli al tipo di dati pertinente. I campi instruction non devono essere inizializzati.

Parametri

  • dag – Il circuito da cui recuperare l'istruzione.
  • indice – L'indice del nodo. È un errore passare un indice che è un nodo non valido.
  • istruzione – Un punto in cui scrivere il QkCircuitInstruction.

qk_dag_compose

QkExitCode qk_dag_compose(QkDag *dag, const QkDag *other, const uint32_t *qubits, const uint32_t *clbits)

Comporre il other DAG dag sull'istanza con l'opzione di mappare un sottoinsieme other dei fili di ingresso di su un sottoinsieme dei fili di uscita di dag.

other può includere un numero inferiore o uguale di fili per ciascun tipo.

Esempio

// 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);

Sicurezza

Il comportamento è indefinito se dag o non other sono puntatori validi e non nulli a un QkDag. Se qubitclbit sono NULL, deve contenere un importo inferiore o uguale a quello posseduto dal circuito.

Parametri

  • dag – Un puntatore al DAG su cui comporre.
  • altro – Un puntatore al DAG con cui dagcomporre.
  • qubit – Un elenco di indici che rappresentano i fili qubit su cui comporre.
  • clbits – Un elenco di indici che rappresentano i fili clbit su cui comporre.

Risultati

QkExitCode_Success in caso di decomposizione riuscita, altrimenti un codice di errore specifico DAG che indica la causa dell'errore.

qk_dag_free

void qk_dag_free(QkDag *dag)

Libera il DAG.

Esempio

QkDag *dag = qk_dag_new();
qk_dag_free(dag);

Sicurezza

Il comportamento è indefinito se non dag è né nullo né un puntatore valido a un QkDag.

Parametri

  • dag – Un puntatore al DAG da liberare.

qk_dag_to_circuit

QkCircuit *qk_dag_to_circuit(const QkDag *dag)

Converti un dato DAG in un circuito.

Il nuovo circuito viene copiato dal DAG; il riferimento dag originale rimane di proprietà del chiamante e deve ancora essere liberato con qk_dag_free. Una volta terminato, è necessario qk_circuit_free liberare il circuito restituito con.

Esempio

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);

Sicurezza

Il comportamento è indefinito se non dag è un puntatore valido e non nullo a un QkDag.

Parametri

  • dag – Un puntatore al DAG da cui creare il circuito.

Risultati

Un puntatore al nuovo circuito.

qk_dag_topological_op_nodes

void qk_dag_topological_op_nodes(const QkDag *dag, uint32_t *out_order)

Restituisce i nodi operativi nel DAG elencati in ordine topologico.

Esempio

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);

Sicurezza

Il comportamento è indefinito se non dag è un puntatore valido e non nullo a un QkDag o se non out_order è un puntatore valido e non nullo a una sequenza di qk_dag_num_op_nodes(dag) elementi consecutivi di uint32_t.

Parametri

  • dag – Un puntatore al DAG.
  • out_order – Un puntatore a un array di qk_dag_num_op_nodes(dag) elementi di tipo uint32_t, dove questa funzione scriverà l'output.

qk_dag_substitute_node_with_dag

void qk_dag_substitute_node_with_dag(QkDag *dag, uint32_t node, const QkDag *replacement)

Sostituire un nodo in un circuito QkDag con un sottocircuito specificato da un altro QkDag

Esempio

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);

Sicurezza

Il comportamento è indefinito se dag e non replacement sono puntatori validi e non nulli a un QkDag.

Parametri

  • dag – Un puntatore al DAG.
  • nodo – L'indice del nodo dell'operazione da sostituire con l'altro QkDag. Questo deve essere l'indice del nodo per un nodo operativo in dag e il conteggio qargs e cargs deve corrispondere al numero di qubit e clbit in replacement.
  • sostituzione – L'altro QkDag da sostituire node con. Questo dag deve avere lo stesso numero di qubit dell'operazione per node. L'ordinamento dei bit dei nodi sarà gestito in ordine, quindi qargs[0] per node sarà mappato su qubits[0] in replacement, qargs[1] su qubits[0], ecc. Lo stesso schema si applica anche ai bit classici.

qk_dag_copy_empty_like

QkDag *qk_dag_copy_empty_like(const QkDag *dag, QkVarsMode vars_mode, QkBlocksMode blocks_mode)

Restituisce una copia di sé stessa con la stessa struttura ma vuota.

Tale struttura comprende:

  • nome e altri metadati
  • fase globale
  • durata
  • tutti i qubit e i clbit, compresi i registri.

Esempio

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);

Sicurezza

Il comportamento è indefinito se non dag è un puntatore valido a un QkDag.

Parametri

  • dag – Un puntatore al DAG da copiare.
  • vars_mode – La modalità per la gestione delle variabili classiche.
  • blocks_mode – La modalità di gestione dei blocchi.

Risultati

Il puntatore al circuito DAG copiato.

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)

Sostituisci un blocco contiguo non vuoto di nodi in un QkDag con un singolo gate unitario corrispondente alla matrice unitaria specificata.

Al momento della sostituzione, i nodi presenti nel blocco vengono rimossi e sostituiti da un nuovo nodo che agisce sui qubit specificati.

Esempio

// 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);

Sicurezza

Il comportamento è indefinito se si verifica una delle seguenti condizioni:

  • dag non è un puntatore allineato e diverso da zero a un valido QkDag,
  • qubits non è un puntatore allineato ai num_qubits valori inizializzati.
  • matrix non è un puntatore allineato a 4**num_qubits valori inizializzati,
  • block_ids non è un puntatore allineato a valori num_block_ids inizializzati.

Parametri

  • dag – Puntatore al DAG.
  • num_block_ids – Numero di voci in block_ids. Questo numero deve essere diverso da zero.
  • block_ids – Puntatore a un array non vuoto di nodi da sostituire.
  • matrice – Puntatore a una matrice unitaria con disposizione delle righe inizializzata di dimensione 4**num_qubits.
  • num_qubits – Il numero di qubit su cui agisce il gate unitario risultante.
  • qubit – Puntatore a un array di indici di qubit uint32_t distinti. Ogni voce specifica l'indice del qubit DAG corrispondente alla rispettiva posizione dell'argomento nel gate unitario.
  • cycle_check – Se true, la funzione verifica se la sostituzione del nodo specificato block_ids con un singolo nodo introdurrebbe un ciclo nel DAG (il che renderebbe il DAG non valido). Se venisse creato un ciclo, il DAG rimane invariato e UINT32_MAX viene restituito. Questo controllo comporta una perdita di prestazioni. Se è possibile garantire che il blocco fornito block_ids sia contiguo e non crei un ciclo una volta ridotto a un singolo nodo, è possibile impostare questo valore su false.

Risultati

L'indice del nodo di operazione appena aggiunto, oppure UINT32_MAX se cycle_check è true e la sostituzione comporterebbe 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)

Sostituisci un'operazione in un nodo di un grafo QkDag con una porta unitaria corrispondente alla matrice unitaria specificata.

La nuova operazione dovrebbe corrispondere alla forma dell'operazione sostituita. I qarg e i carg del nodo rimarranno invariati.

Esempio

// 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);

Sicurezza

Il comportamento è indefinito se si verifica una delle seguenti condizioni:

  • dag non è un puntatore allineato e diverso da zero a un valido QkDag,
  • matrix non è un puntatore allineato a 4**num_qubits valori inizializzati,

Parametri

  • dag – Puntatore al DAG.
  • nodo – Il nodo la cui operazione viene sostituita. Il numero di qubit nell'operazione sostituita dovrebbe essere pari a num_qubits e il numero di clbit dovrebbe essere 0.
  • matrice – Puntatore a una matrice unitaria con disposizione delle righe inizializzata di dimensione 4**num_qubits.
  • num_qubits – Il numero di qubit su cui agisce l'operatore unitario.

qk_dag_to_python

PyObject *qk_dag_to_python(QkDag *dag)

Trasferisci la proprietà di un QkDag oggetto a Python.

Non è sicuro utilizzare il QkDag puntatore dopo aver chiamato questa funzione. In particolare, non dovresti cercare di ripulirlo o liberarlo. Chi effettua la chiamata deve essere il proprietario dell'oggetto QkDag, non possedere un riferimento preso in prestito (ad esempio, un oggetto QkDag * recuperato da non qk_dag_borrow_from_python è di sua proprietà).

Sicurezza

Chi chiama deve essere collegato a un interprete dell' Python. Il comportamento è indefinito se non dag è un puntatore non nullo valido a un oggetto inizializzato e di proprietà dell'utente QkDag.

Parametri

  • dag – L'oggetto di proprietà.

Risultati

Un riferimento di tipo " Python " all'oggetto.

qk_dag_borrow_from_python

QkDag *qk_dag_borrow_from_python(PyObject *ob)

Recupera un QkDag puntatore da un oggetto Python.

Questa operazione prende in prestito un riferimento a un oggetto di tipo Python ed estrae il QkDag puntatore corrispondente, se è del tipo corretto. Il puntatore restituito viene preso in prestito dal ob puntatore. Se il non PyObject è del tipo corretto, il valore restituito è NULL e viene impostato lo stato di eccezione dell'interprete di Python.

Per chiamare questa funzione è necessario essere collegati a un interprete Python.

È inoltre possibile utilizzare qk_dag_convert_from_python, che dal punto di vista logico è esattamente identico a questa funzione, ma può essere utilizzato direttamente come funzione di "conversione" per la PyArg_Parse* famiglia di funzioni di conversione di Python.

Sicurezza

Chi chiama deve essere collegato a un interprete dell' Python. Il comportamento è indefinito se non ob è un puntatore valido e non nullo a un oggetto Python.

Parametri

  • ob – Un oggetto preso in prestito dall' Python.

Risultati

Un puntatore all'oggetto nativo, oppure NULL se l'oggetto Python è di tipo errato.

qk_dag_convert_from_python

int qk_dag_convert_from_python(PyObject *object, void *address)

Recupera un puntatore DAG da un oggetto Python.

Questa operazione prende in prestito un riferimento di tipo Python ed estrae il QkDag puntatore corrispondente in address,, se è del tipo corretto. Il puntatore restituito viene preso in prestito dal object puntatore. Se il tipo PyObject non è corretto, il valore restituito è 1, viene impostato lo stato di eccezione dell'interprete di Python e e address rimane invariato.

Per chiamare questa funzione è necessario essere collegati a un interprete Python.

Puoi anche usare qk_dag_borrow_from_python, che dal punto di vista logico è esattamente uguale a questo, ma presenta una sintassi più intuitiva per l'uso diretto.

Sicurezza

Chi chiama deve essere collegato a un interprete dell' Python. Il comportamento è indefinito se non object è un puntatore valido e non nullo a un oggetto Python, oppure se non address è un puntatore a dati scrivibili del tipo corretto.

Parametri

  • oggetto – Un oggetto Python preso in prestito.
  • destinazione – La posizione in cui scrivere l'output.

Risultati

1 in caso di successo, 0 in caso di fallimento.

Questa pagina è stata utile?
Segnala un bug, un errore di battitura o richiedi contenuti su GitHub.