Skip to main content
IBM Quantum Platform

QkDag

typedef struct QkDag QkDag

La QkDag structure expose une interface de bas niveau à la représentation sous forme de graphe acyclique dirigé (DAG) d'un circuit quantique par le transcompilateur Qiskit, destinée à être utilisée dans les passes du transcompilateur. Il n'expose que ce qui est défini dans le modèle de données interne de Qiskit. Il manque donc certaines fonctionnalités disponibles dans la classe de niveau DAGCircuit supérieur Python.

L'API C ne prend actuellement en charge que la création de DAG contenant des opérations définies dans le modèle de données Rust interne de Qiskit. En général, cela inclut uniquement les portes de la bibliothèque de portes standard, les opérations standard non unitaires (actuellement Barrier, Measure, Reset, et Delay) et UnitaryGate. Cette fonctionnalité sera étendue au fil du temps, à mesure que le modèle de données Rust sera développé pour prendre en charge nativement davantage de fonctionnalités.


Types de données

QkDagNodeType

enum QkDagNodeType

Le type de nœud dans un QkDag.

Les nœuds d'opération représentent une instruction appliquée. Les autres nœuds sont considérés comme des nœuds « filaires » et représentent les points finaux des chaînes de dépendance des données du DAG.

Valeurs :

énumérateur QkDagNodeType_Operation

Nœud opérationnel.

énumérateur QkDagNodeType_QubitIn

Nœud de départ du fil Qubit.

énumérateur QkDagNodeType_QubitOut

Nœud d'extrémité de fil Qubit.

énumérateur QkDagNodeType_ClbitIn

Nœud de départ du fil Clbit.

énumérateur QkDagNodeType_ClbitOut

Nœud d'extrémité de fil Clbit.

énumérateur QkDagNodeType_VarIn

Nœud classique à fil variable.

énumérateur QkDagNodeType_VarOut

Nœud d'extrémité de fil variable classique.

QkOperationKind

enum QkOperationKind

Le type d'opération.

Cette valeur est renvoyée lors de l'interrogation d'un nœud particulier du graphe avec qk_dag_op_node_kind, et est destinée à permettre à l'appelant de distribuer (par exemple via un « commutateur ») les appels spécifiques au type d'opération contenu.

Valeurs :

énumérateur QkOperationKind_Gate

énumérateur QkOperationKind_Barrier

énumérateur QkOperationKind_Delay

énumérateur QkOperationKind_Measure

énumérateur QkOperationKind_Reset

énumérateur QkOperationKind_Unitary

énumérateur QkOperationKind_PauliProductMeasurement

énumérateur QkOperationKind_ControlFlow

énumérateur QkOperationKind_Unknown

Cette variante est utilisée comme type opaque pour les opérations qui ne sont pas encore implémentées dans le modèle de données natif.

QkOperationKind_PauliProductRotation de recenseur

QkDagNeighbors

struct QkDagNeighbors

Une structure permettant de stocker les informations relatives aux successeurs et aux prédécesseurs récupérées respectivement à partir de qk_dag_successors et qk_dag_predecessors.

Cet objet est en lecture seule depuis C. Pour respecter les garanties de sécurité de qk_dag_neighbors_clear, vous ne devez pas écraser les données initialisées par qk_dag_successors ou qk_dag_predecessors, y compris les données pointées.

const uint32_t *voisins

Tableau de taille num_neighbors d'indices de nœuds.

taille_t nombre_de_voisins

La longueur du neighbors tableau.


Fonctions

qk_dag_new

QkDag *qk_dag_new(void)

Construisez un nouveau DAG vide.

Vous devez libérer le DAG renvoyé avec qk_dag_free lorsque vous avez terminé de l'utiliser.

Exemple

QkDag *empty = qk_dag_new();

Retours

Un pointeur vers le DAG créé.

qk_dag_add_quantum_register

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

Ajouter un registre quantique au DAG.

Exemple

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

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag et si reg n'est pas un pointeur valide et non nul vers un QkQuantumRegister.

Paramètres

  • dag – Pointeur vers le DAG.
  • reg – Pointeur vers le registre quantique.

qk_dag_add_classical_register

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

Ajoutez un registre classique au DAG.

Exemple

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

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag et si reg n'est pas un pointeur valide et non nul vers un QkClassicalRegister.

Paramètres

  • dag – Pointeur vers le DAG.
  • reg – Pointeur vers le registre classique.

qk_dag_num_qubits

uint32_t qk_dag_num_qubits(const QkDag *dag)

Obtenir le nombre de qubits contenus dans le DAG.

Exemple

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

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag.

Paramètres

  • dag – Pointeur vers le DAG.

Retours

Le nombre de qubits sur lesquels le DAG est défini.

qk_dag_num_clbits

uint32_t qk_dag_num_clbits(const QkDag *dag)

Obtenir le nombre de clbits contenus dans le DAG.

Exemple

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

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag.

Paramètres

  • dag – Pointeur vers le DAG.

Retours

Le nombre de clbits sur lesquels le DAG est défini.

qk_dag_num_op_nodes

size_t qk_dag_num_op_nodes(const QkDag *dag)

Renvoie le nombre total de nœuds d'opération dans le DAG.

Exemple

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

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag.

Paramètres

  • dag – Pointeur vers le DAG.

Retours

Nombre total d'instructions dans le DAG.

qk_dag_global_phase

QkParam *qk_dag_global_phase(const QkDag *dag)

Récupérer la phase globale du DAG.

Cette fonction renvoie une copie de la phase globale du DAG; cette valeur doit être libérée via :c:func:qk_param_free après utilisation.

Exemple

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

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag.

Paramètres

  • dag – Pointeur vers le DAG.

Retours

La phase globale du DAG.

qk_dag_set_global_phase

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

Définir la phase globale du DAG.

Cette fonction copie la nouvelle phase globale lors de sa définition; l'appelant conserve donc la propriété de cette QkParam phase, et la valeur de celle-ci doit être libérée via :c:func:qk_param_free après sa définition.

Exemple

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

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag et si phase n'est pas un pointeur valide et non nul vers un QkParam.

Paramètres

  • dag – Pointeur vers le DAG.
  • phase – Un pointeur vers la phase globale à définir.

Retours

QkExitCode_Success une fois la phase globale correctement définie. En cas d'échec, QkExitCode_ParameterError cette section décrit les erreurs génériques pouvant survenir lors de la recherche des symboles de paramètres, telles que des valeurs de paramètres non valides. Dans le cas contraire, QkExitCode_DagError cela indique que la cause de la défaillance est spécifique au DAG.

qk_dag_node_type

QkDagNodeType qk_dag_node_type(const QkDag *dag, uint32_t node)

Obtenir le type du nœud spécifié.

Le résultat peut être utilisé dans une instruction switch pour envoyer le traitement approprié lors de l'itération sur des nœuds de type inconnu.

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag.

Paramètres

  • dag – Pointeur vers le DAG.
  • node – Le nœud dont on souhaite obtenir le type.

Retours

Type de noeud.

qk_dag_qubit_in_node

uint32_t qk_dag_qubit_in_node(const QkDag *dag, uint32_t qubit)

Récupère l'index du nœud d'entrée du fil correspondant au qubit donné.

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag.

Paramètres

  • dag – Pointeur vers le DAG.
  • qubit – Le qubit dont vous souhaitez obtenir l'index du nœud d'entrée.

Retours

Le nœud d'entrée du fil qubit.

qk_dag_qubit_out_node

uint32_t qk_dag_qubit_out_node(const QkDag *dag, uint32_t qubit)

Récupérer l'index du nœud de sortie du fil correspondant au qubit donné.

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag.

Paramètres

  • dag – Pointeur vers le DAG.
  • qubit – Le qubit dont vous souhaitez obtenir l'index du nœud de sortie.

Retours

Le nœud de sortie du fil qubit.

qk_dag_clbit_in_node

uint32_t qk_dag_clbit_in_node(const QkDag *dag, uint32_t clbit)

Récupère l'index du nœud d'entrée du fil correspondant au clbit donné.

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag.

Paramètres

  • dag – Pointeur vers le DAG.
  • clbit – Le clbit permettant d'obtenir l'index du nœud d'entrée.

Retours

Le nœud d'entrée du fil clbit.

qk_dag_clbit_out_node

uint32_t qk_dag_clbit_out_node(const QkDag *dag, uint32_t clbit)

Récupère l'index du nœud de sortie du fil correspondant au clbit donné.

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag.

Paramètres

  • dag – Pointeur vers le DAG.
  • clbit – Le clbit pour obtenir l'index du nœud de sortie.

Retours

Le nœud de sortie du fil clbit.

qk_dag_wire_node_value

uint32_t qk_dag_wire_node_value(const QkDag *dag, uint32_t node)

Récupérer la valeur d'un nœud terminal de connexion.

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag.

Paramètres

  • dag – Pointeur vers le DAG.
  • node – Le nœud terminal dont vous souhaitez obtenir la valeur du câble.

Retours

La valeur (par exemple, qubit, clbit ou var) dans le nœud terminal.

qk_dag_op_node_num_qubits

uint32_t qk_dag_op_node_num_qubits(const QkDag *dag, uint32_t node)

Obtient le nombre de qubits du nœud d'opération spécifié.

Panique si le nœud n'est pas une opération.

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag.

Paramètres

  • dag – Pointeur vers le DAG.
  • node – Le nœud d'opération dont on souhaite obtenir le nombre de qubits.

Retours

Le nombre de qubits de l'opération.

qk_dag_op_node_num_clbits

uint32_t qk_dag_op_node_num_clbits(const QkDag *dag, uint32_t node)

Obtient le nombre de bits de contrôle du nœud d'opération spécifié.

Panique si le nœud n'est pas une opération.

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag.

Paramètres

  • dag – Pointeur vers le DAG.
  • node – Le nœud d'opération dont on souhaite obtenir le nombre de clbits.

Retours

Le nombre de clbits de l'opération.

qk_dag_op_node_num_params

uint32_t qk_dag_op_node_num_params(const QkDag *dag, uint32_t node)

Obtient le nombre de paramètres du nœud d'opération spécifié.

Panique si le nœud n'est pas une opération.

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag.

Paramètres

  • dag – Pointeur vers le DAG.
  • node – Le nœud d'opération dont vous souhaitez obtenir le nombre de paramètres.

Retours

Le nombre de paramètres de l'opération.

qk_dag_op_node_qubits

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

Récupérer les qubits du nœud d'opération spécifié.

Panique si le nœud n'est pas une opération.

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag.

Paramètres

  • dag – Pointeur vers le DAG.
  • node – Le nœud d'opération dont on souhaite obtenir les qubits.

Retours

Un pointeur vers les qubits. Utilisez qk_dag_op_node_num_qubits pour déterminer le nombre d'éléments.

qk_dag_op_node_clbits

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

Récupère les bits clbits du nœud d'opération spécifié.

Panique si le nœud n'est pas une opération.

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag.

Paramètres

  • dag – Pointeur vers le DAG.
  • node – Le nœud d'opération dont vous souhaitez obtenir les clbits.

Retours

Un pointeur vers les bits clbits. Utilisez qk_dag_op_node_num_clbits pour déterminer le nombre d'éléments.

qk_dag_apply_gate

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

Appliquez un QkGate au DAG.

Exemple

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

Sécurité

Les qubits``params types et doivent être des pointeurs vers un tableau de uint32_t et double respectivement, dont la longueur correspond aux attentes pour la porte standard. Si le tableau n'est pas suffisamment long, le comportement de cette fonction est indéfini, car elle lira en dehors des limites du tableau. Il peut s'agir d'un pointeur nul s'il n'y a pas de qubits ou de paramètres pour une porte donnée. Vous pouvez vérifier qk_gate_num_qubits et qk_gate_num_params pour déterminer combien de qubits et de paramètres sont nécessaires pour une porte donnée.

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag.

Paramètres

  • dag – Pointeur vers le DAG auquel appliquer la porte.
  • gate – L' StandardGate à appliquer.
  • qubits – Pointeur vers le tableau des indices uint32_t de qubits auxquels ajouter la porte. Il peut s'agir d'un pointeur nul s'il n'y a pas de qubits pour gate (par exemple QkGate_GlobalPhase).
  • params – Pointeur vers le tableau de double valeurs à utiliser pour les paramètres de la porte. Il peut s'agir d'un pointeur nul s'il n'y a pas de paramètres pour gate (par exemple QkGate_H).
  • avant – Si true, la porte est appliquée comme première opération sur les qubits spécifiés, plutôt que comme dernière opération.

Retours

L'index du nœud d'opération nouvellement ajouté.

qk_dag_apply_measure

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

Appliquer une mesure à un DAG.

Exemple

Mesurez tous les qubits dans l'index clbit correspondant à la fin du circuit.

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

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur aligné et non nul vers un valide QkDag, ou si qubit ou clbit sont hors de plage.

Paramètres

  • dag – Le circuit auquel s'appliquer.
  • qubit – L'index qubit à mesurer.
  • clbit – L'index clbit dans lequel stocker le résultat.
  • avant – Indique s'il faut appliquer la mesure au début du circuit. En général false.

Retours

L'index du nœud de l'instruction créée.

qk_dag_apply_reset

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

Appliquez une réinitialisation au DAG.

Exemples

Appliquer les réinitialisations initiales à tous les 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);
}

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur aligné et non nul vers un valide QkDag, ou si qubit est hors de la plage.

Paramètres

  • dag – Le circuit auquel s'appliquer.
  • qubit – L'index du qubit à réinitialiser.
  • avant – Indique s'il faut appliquer la réinitialisation au début du circuit. En général false.

Retours

L'index du nœud de l'instruction créée.

qk_dag_apply_barrier

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

Appliquez une barrière sur le DAG.

Exemples

Appliquez une barrière finale sur tous les qubits :

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

Appliquez une barrière au début d'un circuit sur les indices de qubits spécifiés :

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

Sécurité

Le comportement est indéfini si :

  • dag n'est pas un pointeur aligné et non nul vers un valide QkDag,
  • qubits n'est pas aligné ou n'est pas valide pour num_qubits les lectures d'index initialisés, dans les limites et non dupliqués, sauf si qubits est nul.

Paramètres

  • dag – Le circuit auquel s'appliquer.
  • qubits – Les indices de qubits auxquels appliquer la barrière. Cette valeur peut être nulle, auquel cas num_qubits n'est pas lu, et la barrière est appliquée à tous les qubits du DAG.
  • num_qubits – Nombre de qubits auxquels la barrière s'applique.
  • avant – Si la barrière doit être appliquée au début du circuit. En général false.

Retours

L'index du nœud de l'instruction créée.

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)

Appliquer une porte unitaire à un DAG.

Les valeurs dans matrix doivent former une matrice unitaire à priorité sur les lignes de taille correcte pour le nombre de qubits. Les données sont copiées à partir du pointeur et doivent uniquement être valides pour la lecture jusqu'à ce que cette fonction renvoie une valeur.

Voir : Conventions de circuit pour plus de détails sur les conventions d'étiquetage des bits et des matrices de Qiskit.

Sécurité

Le comportement est indéfini si l'une des conditions suivantes est remplie :

  • dag n'est pas un pointeur aligné et non nul vers un valide QkDag,
  • matrix n'est pas un pointeur aligné vers des valeurs 4**num_qubits initialisées,
  • qubits n'est pas un pointeur aligné vers des valeurs num_qubits initialisées.

Paramètres

  • dag – Le circuit auquel s'appliquer.
  • matrice – Une matrice unitaire initialisée de type row-major de taille totale 4**num_qubits.
  • qubits – Tableau d'indices uint32_t distincts des qubits.
  • num_qubits – Nombre de qubits auxquels la porte s'applique.
  • avant – Indique s'il faut appliquer la porte au début du circuit. En général false.

Retours

L'index du nœud de l'instruction créée.

qk_dag_op_node_gate_op

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

Récupérer la porte standard du nœud spécifié.

Panique si le nœud n'est pas une opération de porte standard.

Exemple

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

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag. Si out_params n'est pas NULL, il doit pointer vers un tampon suffisamment grand pour contenir tous les paramètres de la porte, sinon le comportement est indéfini car cette fonction écrira au-delà de ses limites. Vous pouvez vérifier qk_dag_op_node_num_params pour déterminer combien de paramètres sont requis pour un nœud d'opération donné.

Paramètres

  • dag – Pointeur vers le DAG.
  • node – Le nœud d'opération dont vous souhaitez obtenir la porte standard.
  • out_params – Un tampon à remplir avec les paramètres de la porte ou NULL s'ils ne sont pas souhaités.

Retours

La valeur du portail.

qk_dag_op_node_unitary

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

Copiez la matrice unitaire de l'indice de nœud correspondant.

Panique si le nœud n'est pas une porte unitaire.

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur non nul vers un valide QkDag, si out n'est pas aligné ou si out n'est pas valide pour 4**num_qubits les écritures de QkComplex64.

Paramètres

  • dag – Circuit à partir duquel lire.
  • node – L'index du nœud de l'instruction de matrice unitaire.
  • out – Mémoire allouée et alignée pour les valeurs 4**num_qubits complexes dans l'ordre des lignes, où num_qubits est le nombre de qubits auxquels la porte s'applique.

qk_dag_op_node_kind

QkOperationKind qk_dag_op_node_kind(const QkDag *dag, uint32_t node)

Obtenir le « type » d'un nœud d'opération.

Le résultat peut être utilisé dans une instruction switch pour distribuer le traitement approprié lors de l'itération sur les nœuds d'opération.

Panique si node n'est pas un nœud d'opération.

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag.

Paramètres

  • dag – Pointeur vers le DAG.
  • node – Le nœud d'opération dont on veut obtenir le « type ».

Retours

Le « type » du nœud.

qk_dag_successors

QkDagNeighbors qk_dag_successors(const QkDag *dag, uint32_t node)

Récupérer les successeurs du nœud spécifié.

Le tableau des successeurs et sa longueur sont renvoyés sous forme de QkDagNeighbors struct, où chaque élément du tableau correspond à un index de nœud DAG. Vous devez appeler la qk_dag_neighbors_clear fonction une fois terminé afin de libérer la mémoire allouée à la structure.

Exemple

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

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag.

Paramètres

  • dag – Pointeur vers le DAG.
  • node – Le nœud dont on souhaite obtenir les successeurs.

Retours

Une instance de la QkDagNeighbors structure contenant les informations sur les successeurs.

qk_dag_predecessors

QkDagNeighbors qk_dag_predecessors(const QkDag *dag, uint32_t node)

Récupérer les prédécesseurs du nœud spécifié.

Le tableau des prédécesseurs et sa longueur sont renvoyés sous forme de QkDagNeighbors struct, où chaque élément du tableau correspond à un index de nœud DAG. Vous devez appeler la qk_dag_neighbors_clear fonction une fois terminé afin de libérer la mémoire allouée à la structure.

Exemple

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

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag.

Paramètres

  • dag – Pointeur vers le DAG.
  • node – Le nœud dont on souhaite obtenir les prédécesseurs.

Retours

Une instance de la QkDagNeighbors structure contenant les informations sur les prédécesseurs.

qk_dag_neighbors_clear

void qk_dag_neighbors_clear(QkDagNeighbors *neighbors)

Effacez les champs de la structure QkDagNeighbors d'entrée.

La fonction désalloue la mémoire pointée par le neighbors champ et la définit sur NULL. Il définit également le num_neighbors champ sur 0.

Sécurité

Le comportement est indéfini si neighbors n'est pas un pointeur valide et non nul vers un QkDagNeighbors objet rempli avec ou qk_dag_successors qk_dag_predecessors.

Paramètres

  • voisins – Pointeur vers un QkDagNeighbors objet.

qk_dag_get_instruction

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

Renvoyer les détails d'une instruction dans le circuit.

Ceci est un miroir de qk_circuit_get_instruction. Vous pouvez également utiliser des méthodes individuelles telles que qk_dag_op_node_gate_op pour obtenir des propriétés individuelles.

Vous devez appeler qk_circuit_instruction_clear pour réinitialiser le QkCircuitInstruction avant de le réutiliser ou de le jeter.

Exemples

Parcourir un DAG pour trouver les qubits sur lesquels des mesures ont été effectuées :

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

Sécurité

Le comportement est indéfini si ou dag ne instruction sont pas des pointeurs valides, alignés et non nuls vers le type de données pertinent. Les champs instruction n'ont pas besoin d'être initialisés.

Paramètres

  • dag – Circuit à partir duquel récupérer l'instruction.
  • index – L'index du nœud. C'est une erreur de passer un index qui n'est pas un nœud op valide.
  • instruction – Un point indiquant où écrire le QkCircuitInstruction.

qk_dag_compose

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

Composez le other DAG sur dag l'instance avec l'option d'un sous-ensemble de fils d'entrée de other étant mappé sur un sous-ensemble de fils de sortie de dag.

other peut comprendre un nombre inférieur ou égal de fils pour chaque type.

Exemple

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

Sécurité

Le comportement est indéfini si dag ou ne other sont pas des pointeurs valides et non nuls vers un QkDag. Si qubit ni clbit ne sont NULL, il doit contenir une quantité inférieure ou égale à celle que possède le circuit.

Paramètres

  • dag – Pointeur vers le DAG à composer.
  • autre – Un pointeur vers le DAG à composer avec dag.
  • qubits – Une liste d'indices représentant les fils qubit à composer.
  • clbits – Une liste d'indices représentant les fils clbit à composer.

Retours

QkExitCode_Success en cas de décomposition réussie, sinon un code d'erreur spécifique au DAG indiquant la cause de l'échec.

qk_dag_free

void qk_dag_free(QkDag *dag)

Libérez le DAG.

Exemple

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

Sécurité

Le comportement est indéfini si dag n'est ni nul ni un pointeur valide vers un QkDag.

Paramètres

  • dag – Pointeur vers le DAG à libérer.

qk_dag_to_circuit

QkCircuit *qk_dag_to_circuit(const QkDag *dag)

Convertir un DAG donné en circuit.

Le nouveau circuit est copié à partir du DAG; la référence dag d'origine appartient toujours à l'appelant et doit toujours être libérée avec qk_dag_free. Vous devez libérer le circuit renvoyé avec qk_circuit_free lorsque vous avez terminé.

Exemple

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

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag.

Paramètres

  • dag – Pointeur vers le DAG à partir duquel créer le circuit.

Retours

Un pointeur vers le nouveau circuit.

qk_dag_topological_op_nodes

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

Renvoie les nœuds d'opération dans le DAG classés par ordre topologique.

Exemple

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

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un QkDag ou si out_order n'est pas un pointeur valide et non nul vers une séquence de éléments qk_dag_num_op_nodes(dag) consécutifs de uint32_t.

Paramètres

  • dag – Pointeur vers le DAG.
  • out_order – Pointeur vers un tableau qk_dag_num_op_nodes(dag) d'éléments de type uint32_t, dans lequel cette fonction écrira la sortie.

qk_dag_substitute_node_with_dag

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

Remplacer un nœud dans un QkDag par un sous-circuit spécifié par un autre QkDag

Exemple

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

Sécurité

Le comportement est indéfini si dag et ne replacement sont pas des pointeurs valides et non nuls vers un QkDag.

Paramètres

  • dag – Pointeur vers le DAG.
  • node – L'index du nœud de l'opération à remplacer par l'autre QkDag. Il doit s'agir de l'index d'un nœud d'opération dans dag et le nombre de qargs et de cargs doit correspondre au nombre de qubits et de clbits dans replacement.
  • remplacement – L'autre QkDag à remplacer node par. Ce dag doit avoir le même nombre de qubits que l'opération pour node. L'ordre des bits du nœud sera traité dans l'ordre, donc qargs[0] pour node sera mappé à qubits[0] dans replacement, qargs[1] à qubits[0], etc. Le même principe s'applique également aux bits classiques.

qk_dag_copy_empty_like

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

Renvoie une copie de soi-même avec la même structure, mais vide.

Cette structure comprend :

  • nom et autres métadonnées
  • phase globale
  • durée
  • tous les qubits et clbits, y compris les registres.

Exemple

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

Sécurité

Le comportement est indéfini si dag n'est pas un pointeur valide vers un QkDag.

Paramètres

  • dag – Pointeur vers le DAG à copier.
  • vars_mode – Mode de gestion des variables classiques.
  • blocks_mode – Mode de gestion des blocs.

Retours

Le pointeur vers le circuit DAG copié.

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)

Remplacer un bloc contigu non vide de nœuds dans un QkDag par une porte unitaire unique correspondant à la matrice unitaire spécifiée.

Lors du remplacement, les nœuds du bloc sont supprimés et remplacés par un nouveau nœud agissant sur les qubits concernés.

Exemple

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

Sécurité

Le comportement est indéfini si l'une des conditions suivantes est remplie :

  • dag n'est pas un pointeur aligné et non nul vers un valide QkDag,
  • qubits n'est pas un pointeur aligné vers des valeurs num_qubits initialisées.
  • matrix n'est pas un pointeur aligné vers des valeurs 4**num_qubits initialisées,
  • block_ids n'est pas un pointeur aligné sur des valeurs num_block_ids initialisées.

Paramètres

  • dag – Pointeur vers le DAG.
  • num_block_ids – Nombre d'entrées dans block_ids. Ce nombre doit être différent de zéro.
  • block_ids – Pointeur vers un tableau non vide de nœuds à remplacer.
  • matrice – Pointeur vers une matrice unitaire initialisée, de type « row-major », de taille 4**num_qubits.
  • num_qubits – Le nombre de qubits sur lesquels agit la porte unitaire obtenue.
  • qubits – Pointeur vers un tableau d'indices de qubits uint32_t distincts. Chaque entrée spécifie l'indice du qubit DAG qui correspond à la position respective de l'argument dans la porte unitaire.
  • cycle_check – Si true, la fonction vérifie si le remplacement du nœud fourni block_ids par un seul nœud introduirait un cycle dans le DAG (ce qui rendrait le DAG invalide). Si un cycle est créé, le DAG reste inchangé et UINT32_MAX est renvoyé. Cette vérification entraîne une perte de performances. Si vous pouvez garantir que le bloc fourni block_ids est contigu et qu'il ne créera pas de cycle lorsqu'il sera réduit à un seul nœud, cette valeur peut être définie sur false.

Retours

L'index du nœud d'opération nouvellement ajouté, ou UINT32_MAX si cycle_check est true et que le remplacement entraînerait un cycle.

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)

Remplacer une opération dans un nœud d'un graphe QkDag par une porte unitaire correspondant à la matrice unitaire spécifiée.

La nouvelle opération doit correspondre à la forme de l'opération remplacée. Les qargs et les cargs du nœud resteront inchangés.

Exemple

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

Sécurité

Le comportement est indéfini si l'une des conditions suivantes est remplie :

  • dag n'est pas un pointeur aligné et non nul vers un valide QkDag,
  • matrix n'est pas un pointeur aligné vers des valeurs 4**num_qubits initialisées,

Paramètres

  • dag – Pointeur vers le DAG.
  • nœud – Le nœud dont l'opération est remplacée. Le nombre de qubits dans l'opération de substitution doit être égal à num_qubits et le nombre de clbits doit être 0.
  • matrice – Pointeur vers une matrice unitaire initialisée, de type « row-major », de taille 4**num_qubits.
  • num_qubits – Le nombre de qubits sur lesquels agit l'opérateur unitaire.

qk_dag_to_python

PyObject *qk_dag_to_python(QkDag *dag)

Transférez la propriété d'un QkDag objet à Python.

Il n'est pas sûr d'utiliser le QkDag pointeur après avoir appelé cette fonction. En particulier, vous ne devez pas essayer de le nettoyer ou de le dégager. L'appelant doit être le propriétaire de l'objet QkDag, et non pas détenir une référence empruntée (par exemple, un objet QkDag * récupéré à partir de qk_dag_borrow_from_python n'est pas considéré comme étant de sa propriété).

Sécurité

L'appelant doit être connecté à un interprète d' Python. Le comportement est indéfini si dag n'est pas un pointeur valide et non nul vers un objet initialisé et appartenant à l'utilisateur QkDag.

Paramètres

  • dag – L'objet concerné.

Retours

Une référence de type « owned- Python » à l'objet.

qk_dag_borrow_from_python

QkDag *qk_dag_borrow_from_python(PyObject *ob)

Récupérer un QkDag pointeur à partir d'un objet Python.

Cette opération emprunte une référence à un objet de type Python et en extrait le QkDag pointeur, à condition que celui-ci soit du type approprié. Le pointeur renvoyé est emprunté au ob pointeur. Si le type PyObject n'est pas correct, la valeur de retour est NULL et l'état d'exception de l'interpréteur Python est activé.

Vous devez être connecté à un interpréteur Python pour pouvoir appeler cette fonction.

Vous pouvez également utiliser qk_dag_convert_from_python, qui est logiquement identique à cette fonction, mais qui peut être directement utilisé comme fonction de « conversion » pour la PyArg_Parse* famille de fonctions de conversion de l' Python.

Sécurité

L'appelant doit être connecté à un interprète d' Python. Le comportement est indéfini si ob n'est pas un pointeur valide et non nul vers un objet de type Python.

Paramètres

  • ob – Un objet de type « Python » emprunté.

Retours

Un pointeur vers l'objet natif, ou NULL si l'objet de l' Python ation n'est pas du bon type.

qk_dag_convert_from_python

int qk_dag_convert_from_python(PyObject *object, void *address)

Récupérer un pointeur DAG à partir d'un objet Python.

Cette fonction emprunte une référence à Python et en extrait le QkDag pointeur vers address, si celui-ci est du type approprié. Le pointeur renvoyé est emprunté au object pointeur. Si PyObject n'est pas du type correct, la valeur de retour est 1, l'état d'exception de l'interpréteur Python est activé et address reste inchangé.

Vous devez être connecté à un interpréteur Python pour pouvoir appeler cette fonction.

Vous pouvez également utiliser qk_dag_borrow_from_python, qui est logiquement identique à ceci, mais qui présente une syntaxe plus naturelle pour une utilisation directe.

Sécurité

L'appelant doit être connecté à un interprète d' Python. Le comportement est indéfini si object n'est pas un pointeur valide et non nul vers un objet Python, ou si address n'est pas un pointeur vers des données modifiables du type approprié.

Paramètres

  • objet – Un objet emprunté de type « Python ».
  • adresse – Emplacement où enregistrer les données de sortie.

Retours

1 en cas de réussite, 0 en cas d'échec.

Cette page a-t-elle été utile ?
Signaler un bogue, une coquille ou proposer du contenu sur GitHub.