Skip to main content
IBM Quantum Platform

Passages du transpilateur

La transpilation est le processus de réécriture d'un circuit d'entrée donné pour qu'il corresponde à la topologie d'un dispositif quantique spécifique et/ou pour optimiser le circuit en vue de son exécution sur un système quantique.

La plupart des circuits doivent subir une série de transformations qui les rendent compatibles avec un dispositif cible donné et les optimisent pour réduire les effets du bruit sur les résultats obtenus. La réécriture des circuits quantiques en fonction des contraintes matérielles et l'optimisation des performances sont loin d'être triviales. Le flux logique dans la chaîne d'outils de réécriture ne doit pas nécessairement être linéaire et peut souvent comporter des sous-boucles itératives, des branches conditionnelles et d'autres comportements complexes.

Dans Qiskit, le transpileur est construit en exécutant une série de passes qui effectuent chacune une tâche singulière d'analyse ou de transformation d'un circuit quantique. La documentation Python transpiler contient une explication plus détaillée du processus de transpilation.

L'API C de Qiskit propose des fonctions de passe de transcompilateur sous deux formes : celles qui opèrent sur un QkDag et un autre ensemble qui opère sur un QkCircuit. Les fonctions basées sur le DAG, qui respectent la convention de nommage qk_transpiler_pass_*, acceptent un QkDag ainsi qu'un QkTarget et tous les paramètres de configuration spécifiques au passage. Ces fonctions constituent le choix recommandé lors de l'enchaînement de plusieurs passes, par exemple lors de la création d'un pipeline de transpilation personnalisé, car elles opèrent directement sur l'objet DAG et permettent de le transmettre efficacement d'une passe à l'autre au sein d'une session de transpilation. En revanche, les fonctions basées sur des circuits, conformément à la convention qk_transpiler_pass_standalone_* de nommage, opèrent sur un QkCircuit et sont destinées à l'exécution de passes individuelles de manière isolée. Bien qu'elles puissent également servir à créer des flux de travail personnalisés, chaque appel entraîne une charge supplémentaire, car le circuit d'entrée doit être converti en graphe orienté par arête (DAG) en interne et, si un circuit transformé est renvoyé, le DAG obtenu doit ensuite être reconverti en circuit.


Fonctions basées sur les DAG

qk_transpiler_pass_elide_permutations

QkTranspileLayout *qk_transpiler_pass_elide_permutations(QkDag *dag)

Exécutez le passage de transcompilation « ElidePermutations » sur un DAG.

Le passage du transcompilateur « ElidePermutations » supprime toutes les opérations de permutation d'un DAG pré-disposition.

Cette étape est destinée à être exécutée avant la définition d'une configuration (mappage des qubits virtuels vers les qubits physiques) au cours du pipeline de transpilation. Ce passage parcourt le DAG et, lorsqu'il rencontre une porte de permutation, il permute les qubits virtuels dans le DAG et supprime la porte de permutation. Cela permettra de supprimer efficacement toutes les portes de permutation présentes dans le DAG avant l'exécution de la mise en page. Cette optimisation n'est pas applicable une fois la mise en page définie et ne doit pas être exécutée dans ce cas.

Exemple

QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(4, "qr");
qk_dag_add_quantum_register(dag, qr);
for (uint32_t i = 0; i < qk_dag_num_qubits(dag) - 1; i++) {
    uint32_t qargs[2] = {i, i + 1};
    for (uint32_t j = 0; j < i + 1; j++) {
        qk_dag_apply_gate(dag, QkGate_CX, qargs, NULL, false);
    }
}
QkTranspileLayout *elide_result = qk_transpiler_pass_elide_permutations(dag);
if (elide_result != NULL) {
    qk_transpile_layout_free(elide_result);
}
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 – Un pointeur vers le DAG sur lequel exécuter l' ElidePermutations. Si des modifications sont apportées, l'objet pointé est modifié directement. Si des portes sont supprimées, cette fonction libère les allocations du DAG d'origine.

Retours

l'objet de disposition contenant la permutation de sortie induite par les portes omises dans le DAG. Si aucune élision n'est effectuée, ce pointeur sera nul et le DAG d'entrée restera inchangé. Il incombe à l'appelant de libérer la mise en page renvoyée en appelant qk_transpile_layout_free.

qk_transpiler_pass_check_gate_direction

bool qk_transpiler_pass_check_gate_direction(const QkDag *dag, const QkTarget *target)

Exécutez le CheckGateDirection pass sur un circuit DAG.

La passe vérifie si les directions des portes à deux qubits sont conformes aux directions des portes spécifiées dans une cible donnée.

Exemple

QkTarget *target = qk_target_new(2);
uint32_t qargs[3] = {0,1};

QkTargetEntry *cx_entry = qk_target_entry_new(QkGate_CX);
qk_target_entry_add_property(cx_entry, qargs, 2, 0.0, 0.0);
qk_target_add_instruction(target, cx_entry);

QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(2, "qr");
qk_dag_add_quantum_register(dag, qr);
qk_dag_apply_gate(dag, QkGate_CX, (uint32_t[]){1,0}, NULL, false);

bool direction_ok = qk_transpiler_pass_check_gate_direction(dag, target);
qk_quantum_register_free(qr);
qk_dag_free(dag);
qk_target_free(target);

Sécurité

Le comportement est indéfini si dag ou ne target sont pas des pointeurs valides et non nuls vers des objets QkDag``QkTarget et respectivement.

Paramètres

  • dag – Un pointeur vers le circuit DAG sur lequel exécuter le passage « CheckGateDirection ».
  • target - Un pointeur sur la cible utilisée pour vérifier les directions de la porte.

Retours

bool - true si les directions de toutes les portes à deux qubits du circuit sont conformes aux contraintes cibles spécifiées.

qk_transpiler_pass_gate_direction

void qk_transpiler_pass_gate_direction(QkDag *dag, const QkTarget *target)

Exécutez le GateDirection pass sur un DAG.

La passe GateDirection modifie les portes asymétriques pour qu'elles correspondent aux directions de couplage du matériel. Ce laissez-passer permet de remplacer les portes cx, cz, ecr, swap, rzx, rxx, ryy et rzz à l'aide d'identités prédéfinies.

Exemple

QkTarget *target = qk_target_new(3);

uint32_t qargs[2] = {0,1};

QkTargetEntry *cx_entry = qk_target_entry_new(QkGate_CX);
qk_target_entry_add_property(cx_entry, qargs, 2, 0.0, 0.0);
qk_target_add_instruction(target, cx_entry);

QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(3, "qr");
qk_dag_add_quantum_register(dag, qr);
qk_dag_apply_gate(dag, QkGate_CX, (uint32_t[]){1,0}, NULL, false);  

qk_transpiler_pass_gate_direction(dag, target);
qk_quantum_register_free(qr);
qk_dag_free(dag);
qk_target_free(target);

Sécurité

Le comportement est indéfini si dag ou ne target sont pas des pointeurs valides et non nuls vers des objets QkDag``QkTarget et respectivement.

Paramètres

  • dag – Un pointeur vers le circuit DAG sur lequel exécuter le passage « GateDirection ». Le DAG sera modifié in situ par cette opération.
  • target - Un pointeur sur la cible utilisée pour vérifier les directions de la porte.

qk_transpiler_pass_optimize_1q_sequences

void qk_transpiler_pass_optimize_1q_sequences(QkDag *dag, const QkTarget *target)

Exécute le passage « Optimize1qGatesDecomposition » en mode autonome sur un circuit DAG.

Optimize1qGatesDecomposition optimise les séquences de portes d'un seul qubit en re-synthétisant l'unité sous les contraintes des portes de base et des taux d'erreur de la cible.

La décision de remplacer ou non la chaîne d'origine dépend de plusieurs facteurs :

  • Si la chaîne d'origine était hors base.
  • Si la chaîne d'origine était de base mais que la chaîne de remplacement présente des taux d'erreur plus faibles.
  • Si la chaîne d'origine est une identité (la chaîne est supprimée).

L'erreur est la multiplication combinée des erreurs des portes individuelles sur le qubit sur lequel elle opère.

Cette fonction est multithread et peut, par défaut, créer un pool de threads dont le nombre correspond à celui des cœurs de processeur. Vous pouvez régler le nombre de threads à l'aide de la RAYON_NUM_THREADS variable d'environnement. Par exemple, définir RAYON_NUM_THREADS=4 cette valeur limiterait le pool de threads à 4 threads.

Exemple

QkTarget *target = qk_target_new(1);
double u_errors[3] = {0., 1e-4, 1e-4};
for (int idx = 0; idx < 3; idx++) {
    QkTargetEntry *u_entry = qk_target_entry_new(QkGate_U);
    uint32_t qargs[1] = {0};
    qk_target_entry_add_property(u_entry, qargs, 1, NAN, u_errors[idx]);
    qk_target_add_instruction(target, u_entry);
}

// Build circuit
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(1, "qr");
qk_dag_add_quantum_register(dag, qr);
uint32_t qubits[1] = {0};
for (int iter = 0; iter < 3; iter++) {
    qk_dag_apply_gate(dag, QkGate_H, qubits, NULL, false);
}

// Run transpiler pass
qk_transpiler_pass_optimize_1q_sequences(dag, target);

// Clean up
qk_target_free(target);
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 et si target n'est pas un pointeur valide vers un QkTarget.

Paramètres

  • dag – Un pointeur vers QkDag l'objet à transformer.
  • target - Un pointeur sur l'objet QkTarget ou un pointeur nul. Dans le cas où un pointeur nul est fourni et que les erreurs de porte sont inconnues, la passe choisira la séquence avec le moins de portes, et prendra en charge toutes les portes de base sur son ensemble de base d'Euler.

qk_transpiler_pass_remove_diagonal_gates_before_measure

void qk_transpiler_pass_remove_diagonal_gates_before_measure(QkDag *dag)

Exécutez le RemoveDiagonalGatesBeforeMeasure pass sur un circuit DAG.

Transpiler pass pour supprimer les portes diagonales (comme RZ, T, Z, etc.) avant une mesure. Y compris les portes diagonales 2Q.

Exemple

QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(1, "qr");
QkClassicalRegister *cr = qk_classical_register_new(1, "cr");
qk_dag_add_quantum_register(dag, qr);
qk_dag_add_classical_register(dag, cr);
qk_dag_apply_gate(dag, QkGate_Z, (uint32_t[1]){0}, NULL, false);
qk_dag_apply_measure(dag, 0, 0, false);
qk_transpiler_pass_remove_diagonal_gates_before_measure(dag);
// ...
qk_dag_free(dag);
qk_quantum_register_free(qr);
qk_classical_register_free(cr);

Sécurité

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

Paramètres

  • dag – Un pointeur vers le DAG sur lequel exécuter cette passe. Le DAG sera modifié in situ par cette opération.

qk_transpiler_pass_remove_identity_equivalent

void qk_transpiler_pass_remove_identity_equivalent(QkDag *dag, const QkTarget *target, double approximation_degree)

Exécutez le passage de transcompilation « RemoveIdentityEquivalent » sur un circuit DAG.

Supprime les portes dont l'effet est proche d'une opération d'identité jusqu'à une phase globale et jusqu'à la tolérance spécifiée. Les portes paramétrées ne sont pas prises en compte dans cette passe.

Pour une fidélité de coupure ff, cette passe élimine les portes dont la fidélité moyenne par rapport à l'identité est inférieure à ff. Concrètement, une porte GG est supprimée si Fˉ<f\bar F < f

barF=1+dFprocess1+d, Fprocess=Tr(G)2d2bar{F} = \frac{1 + d F_{\text{process}}}{1 + d},\ F_{\text{process}} = \frac{|\mathrm{Tr}(G)|^2}{d^2}

d=2nd = 2^n est la dimension de la porte pour nn qubits.

Cette fonction est multithread et peut, par défaut, créer un pool de threads dont le nombre correspond à celui des cœurs de processeur. Vous pouvez régler le nombre de threads à l'aide de la variable d'environnement RAYON_NUM_THREADS. Par exemple, en définissant RAYON\_NUM\_THREADS=4, on limiterait le pool de threads à 4 threads.

Exemple

QkTarget *target = qk_target_new(5);
uint32_t current_num_qubits = qk_target_num_qubits(target);
QkTargetEntry *cx_entry = qk_target_entry_new(QkGate_CX);
for (uint32_t i = 0; i < current_num_qubits - 1; i++) {
    uint32_t qargs[2] = {i, i + 1};
    double inst_error = 0.0090393 * (current_num_qubits - i);
    double inst_duration = 0.020039;
    qk_target_entry_add_property(cx_entry, qargs, 2, inst_duration, inst_error);
}
QkExitCode result_cx = qk_target_add_instruction(target, cx_entry);
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(4, "qr");
qk_dag_add_quantum_register(dag, qr);
for (uint32_t i = 0; i < qk_dag_num_qubits(dag) - 1; i++) {
    uint32_t qargs[2] = {i, i + 1};
    for (uint32_t j = 0; j<i+1; j++) {
    qk_dag_apply_gate(dag, QkGate_CX, qargs, NULL, false);
    }
}
uint32_t rz_qargs[1] = {1,};
double rz_params[1] = {0.,};
qk_dag_apply_gate(dag, QkGate_RZ, rz_qargs, rz_params, false);
qk_transpiler_pass_remove_identity_equivalent(dag, target, 1.0);
qk_quantum_register_free(qr);
qk_dag_free(dag);
qk_target_free(target);

Sécurité

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

Paramètres

  • dag – Un pointeur vers le DAG sur lequel exécuter l' RemoveIdentityEquivalent. Le DAG indiqué sera mis à jour avec le DAG modifié si le passage parvient à supprimer des portes.
  • target - La cible de la passe RemoveIdentityEquivalent. Si approximation_degree est réglé sur NAN , la tolérance pour déterminer si une opération est équivalente à l'identité sera réglée sur le taux d'erreur signalé dans la cible. Dans le cas contraire, le site target n'est pas utilisé car la tolérance est indépendante de la cible.
  • approximation_degree - Le degré à approximer pour la vérification de l'équivalence. Il peut s'agir d'une valeur à virgule flottante comprise entre 0 et 1, ou de NAN. Si la valeur est 1, l'approximation n'est pas supérieure à la précision de la virgule flottante. Pour une valeur < 1, elle est utilisée comme facteur d'échelle pour la fidélité de coupure. Si la valeur est NAN , cela correspond approximativement à la fidélité de la porte spécifiée dans target.

qk_transpiler_pass_split_2q_unitaries

QkTranspileLayout *qk_transpiler_pass_split_2q_unitaries(QkDag *dag, double requested_fidelity, bool split_swaps)

Exécuter le passage de transcompilation « Split2QUnitaries » sur un circuit 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 – Un pointeur modifiable vers le circuit DAG sur lequel exécuter la fonction Split2QUnitaries. Si des portes sont optimisées, cela sera remplacé par le nouveau DAG.
  • requested_fidelity - Tolérance autorisée pour le fractionnement des unités de deux qubits et des décompositions de portes.
  • split_swaps - Indique s'il faut tenter de diviser les portes d'échange, ce qui entraîne une permutation des qubits.

Retours

Si des éléments unitaires équivalents à un échange sont scindés, cette fonction renvoie un pointeur vers un TranspileLayout contenant la permutation induite par cette optimisation du DAG. Si aucune unité équivalente n'est scindée, ce pointeur sera nul.

qk_transpiler_pass_2q_peephole_optimization

void qk_transpiler_pass_2q_peephole_optimization(QkDag *dag, const QkTarget *target, double approximation_degree)

Lancez la passe de compilation du transpileur « TwoQubitPeepholeOptimization ».

Ce passage du transpileur est conçu pour effectuer une optimisation unitaire « peephole » à deux qubits. Cette étape identifie tous les blocs de 2 qubits du circuit, calcule l'opérateur unitaire correspondant à chaque bloc, puis synthétise cet opérateur unitaire. Si l'opération unitaire à deux qubits synthétisée est « meilleure » que le sous-circuit d'origine, ce sous-circuit est alors utilisé pour remplacer le sous-circuit d'origine. L'heuristique utilisée pour déterminer la meilleure option examine d'abord le nombre de portes à deux qubits dans le circuit et privilégie la synthèse comportant le moins de portes à deux qubits; si ce nombre est identique, elle examine ensuite la fidélité estimée du circuit et choisit le sous-circuit présentant la fidélité estimée la plus élevée; enfin, si nécessaire, elle choisit le sous-circuit comportant le moins de portes au total.

Si la cible est surcomplète, la passe testera tous les décomposeurs pris en charge pour toutes les portes prises en charge sur un qubit donné. La décomposition qui présente les meilleures performances attendues selon l'heuristique ci-dessus sera sélectionnée et utilisée pour remplacer le bloc.

Cette passe est conçue pour être exécutée sur un circuit physique, et on suppose que les opérations effectuées sur un qubit donné correspondent au qubit matériel de la cible. Cependant, le résultat de cette étape peut ne pas utiliser d’opérations matérielles; plus précisément, des portes à un seul qubit peuvent être générées en dehors des opérations prises en charge par la cible, généralement uniquement si une porte paramétrée prise en charge par celle-ci TwoQubitControlledUDecomposer est utilisée pour la synthèse. Ainsi, si cette passe est exécutée au cours d'une étape d'optimisation physique (telle que l'étape d'optimisation ), elle doit être associée à des passes telles que BasisTranslator et/ou Optimize1qGatesDecomposition afin de garantir que ces portes à un seul qubit non conformes soient remplacées par des opérations prises en charge par le matériel avant la fin de l'étape.

Ce passage est multithread et effectuera l'analyse en parallèle, en utilisant tous les cœurs disponibles sur votre système local. Vous pouvez consulter le guide de configuration pour obtenir plus de détails sur la manière de contrôler le comportement du multithreading de Qiskit de manière plus générale, ce qui permettra également de contrôler cette étape

Exemple

QkTarget *target = qk_target_new(2);
uint32_t current_num_qubits = qk_target_num_qubits(target);
QkTargetEntry *cx_entry = qk_target_entry_new(QkGate_CX);
for (uint32_t i = 0; i < current_num_qubits - 1; i++) {
    uint32_t qargs[2] = {i, i + 1};
    double inst_error = 0.0090393 * (current_num_qubits - i);
    double inst_duration = 0.020039;
    qk_target_entry_add_property(cx_entry, qargs, 2, inst_duration, inst_error);
}
QkExitCode result_cx = qk_target_add_instruction(target, cx_entry);
QkCircuit *qc = qk_circuit_new(2, 0);
uint32_t forward[2] = {0, 1};
uint32_t reverse[2] = {1, 0};
for (int i = 0; i < 10; i++) {
    if (i % 2) {
        qk_circuit_gate(qc, QkGate_CX, forward, NULL);
    } else {
        qk_circuit_gate(qc, QkGate_CX, reverse, NULL);
    }
}
QkDag *dag = qk_circuit_to_dag(qc);
qk_circuit_free(qc);

qk_transpiler_pass_2q_peephole_optimization(dag, target, 1.0);
qk_dag_free(dag);
qk_target_free(target);

Sécurité

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

Il n'est pas recommandé d'appeler cette fonction dans un contexte où le circuit DAG contient des objets appartenant à Python. Comme cette fonction est multithread en interne, s'il existe dans le circuit des portes gérées par « Python », les threads de travail pourraient devoir acquérir le GIL pour accéder aux attributs de ces portes, ce qui entraînerait un blocage. Vous devez utiliser la classe d'espace TwoQubitPeepholeOptimization « Python » pour exécuter cette passe si certains éléments du circuit sont gérés par « Python ».

Paramètres

  • dag – Un pointeur vers le circuit DAG sur lequel exécuter la fonction « TwoQubitPeepholeOptimization »
  • target – Un pointeur vers la cible sur laquelle exécuter « TwoQubitPeepholeOptimization »
  • degree_of_approximation – cadran heuristique utilisé pour l'approximation de circuits (approximation de 1.0=no, approximation de 0.0=maximal ). L'approximation permet de réduire la taille du circuit synthétisé, au prix d'un écart par rapport à l'opérateur unitaire d'origine. Si NAN, l'approximation de la cible repose sur les fidélités des portes dans le target.

Fonctions basées sur des circuits

qk_transpiler_pass_standalone_basis_translator

void qk_transpiler_pass_standalone_basis_translator(QkCircuit *circuit, const QkTarget *target, size_t min_qubits)

Faire passer le transpondeur BasisTranslator sur un circuit.

Le transpileur BasisTranslator traduit les portes vers une base cible en recherchant un ensemble de traductions à partir de la norme EquivalenceLibrary.

Exemple

#include <qiskit.h>

QkCircuit *circuit = qk_circuit_new(3, 0);
qk_circuit_gate(circuit, QkGate_CCX, (uint32_t[3]){0, 1, 2}, NULL);

// Create a Target with global properties.
QkTarget *target = qk_target_new(3);
qk_target_add_instruction(target, qk_target_entry_new(QkGate_H));
qk_target_add_instruction(target, qk_target_entry_new(QkGate_T));
qk_target_add_instruction(target, qk_target_entry_new(QkGate_Tdg));
qk_target_add_instruction(target, qk_target_entry_new(QkGate_CX));

// Run pass
qk_transpiler_pass_standalone_basis_translator(circuit, target, 0);

// Free the circuit and target pointers once you're done
qk_circuit_free(circuit);
qk_target_free(target);

Sécurité

Le comportement est indéfini si circuit et/ou target ne sont pas des pointeurs valides et non nuls vers QkCircuit ou QkTarget.

Paramètres

  • circuit - Un pointeur sur le circuit sur lequel BasisTranslator doit fonctionner. Le circuit sera muté sur place, sauf s'il se trouve déjà dans la base cible, auquel cas il restera inchangé.
  • target - La cible à partir de laquelle nous obtiendrons les portes de base.
  • min_qubits – Nombre minimal de qubits requis pour les opérations du circuit d'entrée à traduire.

qk_transpiler_pass_standalone_commutative_cancellation

QkExitCode qk_transpiler_pass_standalone_commutative_cancellation(QkCircuit *circuit, const QkTarget *target, double approximation_degree)

Faire passer le transpondeur CommutativeCancellation sur un circuit.

Ce passage annule les portes redondantes (auto-adjointes) grâce aux relations de commutation.

Cette fonction est multithread et peut, par défaut, créer un pool de threads dont le nombre correspond à celui des cœurs de processeur. Vous pouvez régler le nombre de threads à l'aide de la RAYON_NUM_THREADS variable d'environnement. Par exemple, définir RAYON_NUM_THREADS=4 cette valeur limiterait le pool de threads à 4 threads.

Exemple

QkCircuit *qc = qk_circuit_new(4, 0);
uint32_t cx_qargs[2] = {0, 1};
qk_circuit_gate(qc, QkGate_CX, cx_qargs, NULL);
qk_circuit_gate(qc, QkGate_Z, (uint32_t[]){0}, NULL);
qk_circuit_gate(qc, QkGate_CX, cx_qargs, NULL);
qk_transpiler_pass_standalone_commutative_cancellation(qc, NULL, 1.0);

Sécurité

Le comportement est indéfini si circuit ou target n'est pas valide, QkCircuit et QkTarget. QkCircuit n'est pas censé être nul et le comportement est indéfini s'il l'est.

Paramètres

  • circuit - Un pointeur sur le circuit sur lequel CommutativeCancellation doit fonctionner. Ce pointeur de circuit sera mis à jour avec le circuit modifié si la passe est en mesure de supprimer des portes.
  • target - Cette passe tente d'accumuler toutes les rotations Z dans une porte RZ, P ou U1, en fonction de ce qui est déjà utilisé dans le circuit. Si aucune porte n'est présente dans le circuit, cet argument cible (facultatif) est utilisé comme solution de repli pour décider de la porte à utiliser. Si aucun des éléments RZ, P ou U1 ne se trouve dans le circuit ou dans la cible, les rotations Z d'un qubit unique ne seront pas optimisées.
  • approximation_degree - Le degré d'approximation utilisé lors de l'analyse des commutations. Doit se situer à l'intérieur de (0, 1].

Retours

Code de retour entier où 0 représente l'absence d'erreur et 1 est utilisé pour indiquer qu'une erreur a été rencontrée pendant l'exécution de la passe.

qk_transpiler_pass_standalone_consolidate_blocks

void qk_transpiler_pass_standalone_consolidate_blocks(QkCircuit *circuit, const QkTarget *target, double approximation_degree, bool force_consolidate)

Faire fonctionner la passe ConsolidateBlocks sur un circuit.

ConsolidateBlocks est une passe de transpilation qui consolide des blocs consécutifs de portes opérant sur les mêmes qubits en une porte unitaire, qui sera ensuite resynthétisée, ce qui conduira à un sous-circuit plus optimal.

Sécurité

Le comportement est indéfini si circuit n'est pas un pointeur valide et non nul vers QkCircuit et si target n'est pas un pointeur valide vers QkTarget.

Paramètres

  • circuit - Un pointeur sur le circuit sur lequel ConsolidateBlocks doit fonctionner.
  • target - Un pointeur sur la cible sur laquelle ConsolidateBlocks doit être exécuté.
  • approximation_degree - Une valeur flottante entre [0.0, 1.0] ou NaN qui prend par défaut la valeur 1.0. Plus c'est bas, plus il y a d'approximations.
  • force_consolidate - Force la consolidation des blocs.

qk_transpiler_pass_standalone_convert_to_pauli_rotations

void qk_transpiler_pass_standalone_convert_to_pauli_rotations(QkCircuit *circuit)

Effectuez le ConvertToPauliRotations passage sur place sur un circuit.

Cette opération convertit toutes les portes standard (comportant moins de 4 qubits) du circuit en une séquence de QkPauliProductRotation portes et les mesures en QkPauliProductMeasurement instructions. Notez que cette étape génère une erreur si le circuit contient des portes non standard. La procédure recommandée consiste à effectuer d'abord une transposition vers une base standard, en conservant autant que possible les portes de rotation (telles que QkGate_RXX et autres), puis à lancer cette passe.

Sécurité

Le comportement est indéfini si circuit n'est pas valide, pointeurs non nuls vers un QkCircuit.

Paramètres

  • circuit – Un pointeur vers le circuit sur lequel exécuter le passage.

qk_transpiler_pass_standalone_elide_permutations

QkTranspileLayout *qk_transpiler_pass_standalone_elide_permutations(QkCircuit *circuit)

Faire passer le transpondeur ElidePermutations sur un circuit.

Pour plus d'informations sur le pass, consultez la qk_transpiler_pass_elide_permutations fonction.

Sécurité

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

Paramètres

  • circuit - Un pointeur sur le circuit sur lequel ElidePermutations doit fonctionner. Si des modifications sont apportées, l'objet pointé est modifié à sa place. Dans le cas où des portes sont élidées, les allocations du circuit d'origine sont libérées par cette fonction.

Retours

l'objet de disposition contenant la permutation de sortie induite par les portes omises dans le circuit. Si aucune élision n'est effectuée, ce sera un pointeur nul et le circuit d'entrée restera inchangé. Il incombe à l'appelant de libérer la mise en page renvoyée en appelant qk_transpile_layout_free.

qk_transpiler_pass_standalone_check_gate_direction

bool qk_transpiler_pass_standalone_check_gate_direction(const QkCircuit *circuit, const QkTarget *target)

Faire fonctionner la passe CheckGateDirection sur un circuit.

Pour plus d'informations sur le pass, consultez la qk_transpiler_pass_check_gate_direction fonction.

Sécurité

Le comportement est indéfini si circuit ou target ne sont pas des pointeurs valides et non nuls vers les objets QkCircuit et QkTarget , respectivement.

Paramètres

  • circuit – Un pointeur vers le circuit sur lequel exécuter le passage.
  • target - Un pointeur sur la cible utilisée pour vérifier les directions de la porte.

Retours

Vrai si et seulement si toutes les orientations des portes à deux qubits respectent les contraintes cibles.

qk_transpiler_pass_standalone_gate_direction

void qk_transpiler_pass_standalone_gate_direction(QkCircuit *circuit, const QkTarget *target)

Faire fonctionner la passe GateDirection sur un circuit.

Pour plus d'informations sur le pass, consultez la qk_transpiler_pass_gate_direction fonction.

Sécurité

Le comportement est indéfini si circuit ou target ne sont pas des pointeurs valides et non nuls vers les objets QkCircuit et QkTarget , respectivement.

Paramètres

  • circuit – Un pointeur vers le circuit à modifier in situ.
  • target – Un pointeur vers la cible utilisée pour les directions des portes.

qk_transpiler_pass_standalone_inverse_cancellation

void qk_transpiler_pass_standalone_inverse_cancellation(QkCircuit *circuit)

Faire passer le transpondeur InverseCancellation sur un circuit.

Annule les paires de portes consécutives qui sont inversées l'une par rapport à l'autre. Les portes annulées sont constituées de paires de portes à inversion automatique :

  • QkGate_H
  • QkGate_X
  • QkGate_Y
  • QkGate_Z
  • QkGate_CH
  • QkGate_CX
  • QkGate_CY
  • QkGate_CZ
  • QkGate_ECR
  • QkGate_Swap
  • QkGate_CCX
  • QkGate_CCZ
  • QkGate_CSwap
  • QkGate_RCCX
  • QkGate_C3X

et des paires de portes inverses :

  • (QkGate_T, QkGate_Tdg)
  • (QkGate_S, QkGate_Sdg)
  • (QkGate_SX, QkGate_SXdg)
  • (QkGate_CS, QkGate_CSdg)

Exemple

QkCircuit *qc = qk_circuit_new(2, 2);
uint32_t qargs[1] = {0};
qk_circuit_gate(qc, QkGate_X, qargs, NULL);
qk_circuit_gate(qc, QkGate_H, qargs, NULL);
qk_circuit_gate(qc, QkGate_H, qargs, NULL);
qk_circuit_gate(qc, QkGate_Y, qargs, NULL);
qk_transpiler_pass_standalone_inverse_cancellation(qc);

Sécurité

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

Paramètres

  • circuit - Un pointeur sur le circuit sur lequel InverseCancellation doit fonctionner. Si la passe est en mesure de supprimer des portes, le circuit d'origine sera remplacé par le circuit produit par cette passe.

qk_transpiler_pass_standalone_litinski_transformation

void qk_transpiler_pass_standalone_litinski_transformation(QkCircuit *circuit, bool fix_clifford)

Effectuez le LitinskiTransformation passage sur place sur un circuit.

Cette passe transpose toutes les portes de Clifford vers la fin du circuit, transformant les portes de rotation de Pauli en QkPauliProductRotation portes et les mesures en QkPauliProductMeasurement instructions. Notez que ce passeur ne prend actuellement en charge que les circuits comportant des QkGate_RZ portes QkGate_T, QkGate_Tdg ou non-Clifford; dans le cas contraire, il génère une erreur. La procédure recommandée consiste à effectuer d'abord une transposition en base Clifford+RZ, puis à lancer cette étape.

Sécurité

Le comportement est indéfini si circuit n'est pas valide, pointeurs non nuls vers un QkCircuit.

Paramètres

  • circuit – Un pointeur vers le circuit sur lequel exécuter le passage.
  • fix_clifford – Si true, laisser les portes de Clifford à la fin du circuit. false s'ils sont omis.

qk_transpiler_standalone_optimize_1q_sequences

void qk_transpiler_standalone_optimize_1q_sequences(QkCircuit *circuit, const QkTarget *target)

Exécute la passe Optimize1qGatesDecomposition en mode autonome sur un circuit.

Obsolète depuis la version 2.4.0

Cette fonction est multithread et peut, par défaut, créer un pool de threads dont le nombre correspond à celui des cœurs de processeur. Vous pouvez régler le nombre de threads à l'aide de la RAYON_NUM_THREADS variable d'environnement. Par exemple, définir RAYON_NUM_THREADS=4 cette valeur limiterait le pool de threads à 4 threads.

Sécurité

Le comportement est indéfini si circuit n'est pas un pointeur valide et non nul vers QkCircuit et si target n'est pas un pointeur valide vers QkTarget.

Paramètres

  • circuit - Un pointeur sur l'objet QkCircuit à transformer.
  • target - Un pointeur sur l'objet QkTarget ou un pointeur nul. Dans le cas où un pointeur nul est fourni et que les erreurs de porte sont inconnues, la passe choisira la séquence avec le moins de portes, et prendra en charge toutes les portes de base sur son ensemble de base d'Euler.

qk_transpiler_pass_standalone_optimize_1q_sequences

void qk_transpiler_pass_standalone_optimize_1q_sequences(QkCircuit *circuit, const QkTarget *target)

Exécute la passe Optimize1qGatesDecomposition en mode autonome sur un circuit.

Pour plus d'informations sur le pass, consultez la qk_transpiler_pass_optimize_1q_sequences fonction.

Cette fonction est multithread et peut, par défaut, créer un pool de threads dont le nombre correspond à celui des cœurs de processeur. Vous pouvez régler le nombre de threads à l'aide de la RAYON_NUM_THREADS variable d'environnement. Par exemple, définir RAYON_NUM_THREADS=4 cette valeur limiterait le pool de threads à 4 threads.

Sécurité

Le comportement est indéfini si circuit n'est pas un pointeur valide et non nul vers QkCircuit et si target n'est pas un pointeur valide vers QkTarget.

Paramètres

  • circuit - Un pointeur sur l'objet QkCircuit à transformer.
  • target - Un pointeur sur l'objet QkTarget ou un pointeur nul. Dans le cas où un pointeur nul est fourni et que les erreurs de porte sont inconnues, la passe choisira la séquence avec le moins de portes, et prendra en charge toutes les portes de base sur son ensemble de base d'Euler.

qk_transpiler_pass_standalone_remove_diagonal_gates_before_measure

void qk_transpiler_pass_standalone_remove_diagonal_gates_before_measure(QkCircuit *circuit)

Faire fonctionner la passe RemoveDiagonalGatesBeforeMeasure sur un circuit.

Pour plus d'informations sur le pass, consultez la qk_transpiler_pass_remove_diagonal_gates_before_measure fonction.

Sécurité

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

Paramètres

  • circuit – Un pointeur vers le circuit sur lequel exécuter cette passe.

qk_transpiler_pass_standalone_remove_identity_equivalent

void qk_transpiler_pass_standalone_remove_identity_equivalent(QkCircuit *circuit, const QkTarget *target, double approximation_degree)

Faire passer le transpondeur RemoveIdentityEquivalent sur un circuit.

Pour plus d'informations sur le pass, consultez la qk_transpiler_pass_remove_identity_equivalent fonction.

Cette fonction est multithread et peut, par défaut, créer un pool de threads dont le nombre correspond à celui des cœurs de processeur. Vous pouvez régler le nombre de threads à l'aide de la variable d'environnement RAYON_NUM_THREADS. Par exemple, en définissant RAYON\_NUM\_THREADS=4, on limiterait le pool de threads à 4 threads.

Sécurité

Le comportement est indéfini si circuit ou target n'est pas un pointeur valide et non nul vers QkCircuit et QkTarget.

Paramètres

  • circuit - Un pointeur sur le circuit sur lequel RemoveIdentityEquivalent doit fonctionner. Le circuit pointé sera mis à jour avec le circuit modifié si le laissez-passer est en mesure de supprimer des portes.
  • target - La cible de la passe RemoveIdentityEquivalent. Si approximation_degree est réglé sur NAN , la tolérance pour déterminer si une opération est équivalente à l'identité sera réglée sur le taux d'erreur signalé dans la cible. Dans le cas contraire, le site target n'est pas utilisé car la tolérance est indépendante de la cible.
  • approximation_degree - Le degré à approximer pour la vérification de l'équivalence. Il peut s'agir d'une valeur à virgule flottante comprise entre 0 et 1, ou de NAN. Si la valeur est 1, l'approximation n'est pas supérieure à la précision de la virgule flottante. Pour une valeur < 1, elle est utilisée comme facteur d'échelle pour la fidélité de coupure. Si la valeur est NAN , cela correspond approximativement à la fidélité de la porte spécifiée dans target.

qk_transpiler_pass_standalone_sabre_layout

QkTranspileLayout *qk_transpiler_pass_standalone_sabre_layout(QkCircuit *circuit, const QkTarget *target, const QkSabreLayoutOptions *options)

Faire passer le transpondeur SabreLayout sur un circuit.

La passe SabreLayout choisit une disposition par un routage bidirectionnel itératif du circuit d'entrée.

En partant d'une disposition initiale aléatoire, l'algorithme effectue un routage complet du circuit pour aboutir à une disposition finale. Ce schéma final est ensuite utilisé comme schéma initial pour le routage du circuit inverse. L'algorithme itère un certain nombre de fois jusqu'à ce qu'il trouve une configuration initiale qui réduise le coût total de l'acheminement.

Cette méthode exploite la réversibilité des circuits quantiques et tente d'inclure des informations globales sur les circuits dans le choix de la configuration initiale.

Cette passe exécutera à la fois la disposition et le routage et transformera le circuit de sorte que la disposition soit appliquée à l'entrée (ce qui signifie que le circuit de sortie aura des qubits ancillaires alloués pour les qubits inutilisés sur la carte de couplage et que les qubits seront réorganisés pour correspondre aux qubits physiques cartographiés) et que le routage soit ensuite appliqué. En effet, le programme passera par des essais de semences parallèles avec différentes semences aléatoires pour sélectionner la disposition initiale aléatoire, puis la sortie acheminée qui permet d'obtenir le plus petit nombre de portes de permutation nécessaires. Ce calcul de l'échange final revient à effectuer un routage final, il est donc plus efficace de l'appliquer après l'avoir calculé.

Cette fonction est multithread et lance par défaut un pool de threads dont le nombre est égal au nombre de CPU. Vous pouvez régler le nombre de threads à l'aide de la variable d'environnement RAYON_NUM_THREADS . Par exemple, le paramètre RAYON_NUM_THREADS=4 limiterait le pool de threads à 4 threads.

Références

[1] Henry Zou et Matthew Treinish et Kevin Hartman et Alexander Ivrii et Jake Lishman. “LightSABRE: Un algorithme SABRE léger et amélioré" arXiv:2409.08368

[2] Li, Gushu, Yufei Ding et Yuan Xie. "S'attaquer au problème du mappage des qubits

pour les dispositifs quantiques de l'ère NISQ" ASPLOS 2019.

arXiv:1809.02573

Sécurité

Le comportement est indéfini si circuit ou target n'est pas un pointeur valide et non nul vers QkCircuit et QkTarget.

Paramètres

  • circuit - Un pointeur sur le circuit sur lequel SabreLayout doit fonctionner. Le circuit est modifié sur place et les allocations du circuit d'origine sont libérées par cette fonction.
  • target - Un pointeur sur la cible sur laquelle SabreLayout doit être exécuté
  • options - Un pointeur vers les options pour SabreLayout

Retours

Le schéma de transposition qui décrit la permutation du schéma et de la sortie causée par la passe

qk_transpiler_pass_standalone_split_2q_unitaries

QkTranspileLayout *qk_transpiler_pass_standalone_split_2q_unitaries(QkCircuit *circuit, double requested_fidelity, bool split_swaps)

Exécutez le passage de transcompilation « Split2QUnitaries » sur un circuit.

Pour plus d'informations sur le pass, consultez la qk_transpiler_pass_split_2q_unitaries fonction.

Sécurité

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

Paramètres

  • circuit – Un pointeur modifiable vers le circuit sur lequel exécuter la fonction Split2QUnitaries.
  • requested_fidelity - Tolérance autorisée pour le fractionnement des unités de deux qubits et des décompositions de portes.
  • split_swaps - Indique s'il faut tenter de diviser les portes d'échange, ce qui entraîne une permutation des qubits.

Retours

Si des unités équivalentes à l'échange sont divisées, cette fonction renvoie un pointeur vers un site TranspileLayout qui contient la permutation induite par cette optimisation du circuit. Si aucune unité équivalente à l'échange n'est divisée, il s'agira d'un pointeur nul.

qk_transpiler_pass_standalone_2q_peephole_optimization

void qk_transpiler_pass_standalone_2q_peephole_optimization(QkCircuit *circuit, const QkTarget *target, double approximation_degree)

Lancez la passe de compilation du transpileur « TwoQubitPeepholeOptimization ».

Pour plus de détails sur cette qk_transpiler_pass_2q_peephole_optimization() fonction, consultez la documentation correspondante.

Cette fonction est multithread; elle effectuera l'analyse en parallèle et utilisera tous les cœurs disponibles sur votre système local. Vous pouvez consulter le guide de configuration pour obtenir plus de détails sur la manière de contrôler le comportement du multithreading de Qiskit de manière plus générale, ce qui permettra également de contrôler cette étape

Exemple

QkTarget *target = qk_target_new(2);
uint32_t current_num_qubits = qk_target_num_qubits(target);
QkTargetEntry *cx_entry = qk_target_entry_new(QkGate_CX);
for (uint32_t i = 0; i < current_num_qubits - 1; i++) {
    uint32_t qargs[2] = {i, i + 1};
    double inst_error = 0.0090393 * (current_num_qubits - i);
    double inst_duration = 0.020039;
    qk_target_entry_add_property(cx_entry, qargs, 2, inst_duration, inst_error);
}
QkExitCode result_cx = qk_target_add_instruction(target, cx_entry);
QkCircuit *qc = qk_circuit_new(2, 0);
uint32_t forward[2] = {0, 1};
uint32_t reverse[2] = {1, 0};
for (int i = 0; i < 10; i++) {
    if (i % 2) {
        qk_circuit_gate(qc, QkGate_CX, forward, NULL);
    } else {
        qk_circuit_gate(qc, QkGate_CX, reverse, NULL);
    }
}
qk_transpiler_pass_standalone_2q_peephole_optimization(qc, target, 1.0);
qk_circuit_free(qc);
qk_target_free(target);

Sécurité

Le comportement est indéfini si circuit ou target n'est pas un pointeur valide et non nul vers QkCircuit et QkTarget.

Il n'est pas recommandé d'appeler cette fonction dans un contexte où le circuit contient des objets appartenant à Python. Comme cette fonction est multithread en interne, s'il existe dans le circuit des portes gérées par « Python », les threads de travail pourraient devoir acquérir le GIL pour accéder aux attributs de ces portes, ce qui entraînerait un blocage. Vous devez utiliser la classe d'espace TwoQubitPeepholeOptimization « Python » pour exécuter cette passe si certains éléments du circuit sont gérés par « Python ».

Paramètres

  • circuit – Un pointeur vers le circuit sur lequel exécuter la fonction « TwoQubitPeepholeOptimization »
  • target – Un pointeur vers la cible sur laquelle exécuter « TwoQubitPeepholeOptimization »
  • degree_of_approximation – cadran heuristique utilisé pour l'approximation de circuits (approximation de 1.0=no, approximation de 0.0=maximal ). L'approximation permet de réduire la taille du circuit synthétisé, au prix d'un écart par rapport à l'opérateur unitaire d'origine. Si NAN, l'approximation de la cible repose sur les fidélités des portes dans le target.

qk_transpiler_pass_standalone_unitary_synthesis

void qk_transpiler_pass_standalone_unitary_synthesis(QkCircuit *circuit, const QkTarget *target, size_t min_qubits, double approximation_degree)

Exécutez la passe de transpilation UnitarySynthesis.

La passe de transposition UnitarySynthesis synthétisera toute UnitaryGates dans le circuit en portes disponibles dans la cible.

Cette passe est multithread et lancera potentiellement, par défaut, un pool de threads dont le nombre correspondra à celui des cœurs de processeur. Vous pouvez régler le nombre de threads à l'aide de la RAYON_NUM_THREADS variable d'environnement. Par exemple, définir RAYON_NUM_THREADS=4 cette valeur limiterait le pool de threads à 4 threads.

Exemple

QkTarget *target = qk_target_new(2);
uint32_t current_num_qubits = qk_target_num_qubits(target);
QkTargetEntry *cx_entry = qk_target_entry_new(QkGate_CX);
for (uint32_t i = 0; i < current_num_qubits - 1; i++) {
    uint32_t qargs[2] = {i, i + 1};
    double inst_error = 0.0090393 * (current_num_qubits - i);
    double inst_duration = 0.020039;
    qk_target_entry_add_property(cx_entry, qargs, 2, inst_duration, inst_error);
}
QkExitCode result_cx = qk_target_add_instruction(target, cx_entry);
QkCircuit *qc = qk_circuit_new(2, 0);
QkComplex64 c0 = {0., 0.};
QkComplex64 c1 = {1., 0.};
QkComplex64 unitary[16] = {c1, c0, c0, c0,  // row 0
                           c0, c1, c0, c0,  // row 1
                           c0, c0, c1, c0,  // row 2
                           c0, c0, c0, c1}; // row 3
uint32_t qargs[2] = {0, 1};
qk_circuit_unitary(qc, unitary, qargs, 2, false);
qk_transpiler_pass_standalone_unitary_synthesis(qc, target, 0, 1.0);

Sécurité

Le comportement est indéfini si circuit ou target n'est pas un pointeur valide et non nul vers QkCircuit et QkTarget.

Paramètres

  • circuit - Un pointeur sur le circuit sur lequel UnitarySynthesis doit être exécuté
  • target - Un pointeur sur la cible sur laquelle UnitarySynthesis doit être exécuté
  • min_qubits - Le nombre minimum de qubits dans l'unité à synthétiser. Si l'unité est inférieure au nombre de qubits spécifié, elle ne sera pas synthétisée.
  • approximation_degree - cadran heuristique utilisé pour l'approximation du circuit ( 1.0=no approximation, 0.0=maximal approximation). L'approximation peut rendre le circuit synthétisé moins cher au prix d'un éloignement de l'unité originale. Si NAN, l'approximation de la cible est basée sur les fidélités de la porte dans target.

qk_transpiler_pass_standalone_vf2_layout_average

QkVF2LayoutResult *qk_transpiler_pass_standalone_vf2_layout_average(const QkCircuit *circuit, const QkTarget *target, const QkVF2LayoutConfiguration *config, bool strict_direction)

Utilisez l'algorithme VF2 pour choisir une configuration (si possible) pour le circuit d'entrée, en utilisant un système de notation heuristique tenant compte du bruit et basé uniquement sur les taux d'erreur matériels, et non sur les portes spécifiques du circuit.

Cette fonction correspond au passage de VF2Layout l'espace d' Python.

Cette fonction convient aux circuits qui n'ont pas encore été entièrement transposés en matériel. Si votre circuit a déjà été entièrement transposé en matériel et que vous cherchez à améliorer la disposition pour obtenir un graphe d'interaction exact, utilisez qk_transpile_pass_standalone_vf2_layout_exact plutôt.

Si ce passage permet de trouver une solution, cela signifie qu'il existe une "disposition parfaite" et qu'il n'est pas nécessaire de procéder à d'autres échanges de cartes ou à d'autres routages. Cependant, il n'y a pas toujours de solution possible, ou une solution peut exister mais elle n'est pas trouvée dans les limites spécifiées lors de l'appel de la passe.

Exemple

QkTarget *target = qk_target_new(5);
uint32_t current_num_qubits = qk_target_num_qubits(target);
QkTargetEntry *cx_entry = qk_target_entry_new(QkGate_CX);
for (uint32_t i = 0; i < current_num_qubits - 1; i++) {
    uint32_t qargs[2] = {i, i + 1};
    double inst_error = 0.0090393 * (current_num_qubits - i);
    double inst_duration = 0.020039;
    qk_target_entry_add_property(cx_entry, qargs, 2, inst_duration, inst_error);
}
QkExitCode result_cx = qk_target_add_instruction(target, cx_entry);
QkCircuit *qc = qk_circuit_new(4, 0);
for (uint32_t i = 0; i < qk_circuit_num_qubits(qc) - 1; i++) {
    uint32_t qargs[2] = {i, i + 1};
    for (uint32_t j = 0; j<i+1; j++) {
        qk_circuit_gate(qc, QkGate_CX, qargs, NULL);
    }
}
QkVF2LayoutConfiguration *config = qk_vf2_layout_configuration_new();
qk_vf2_layout_configuration_set_call_limit(config, 10000, 10000);
QkVF2LayoutResult *layout_result = qk_transpiler_pass_standalone_vf2_layout_average(qc, target, config, false);
qk_vf2_layout_result_free(layout_result);
qk_vf2_layout_configuration_free(config);

Sécurité

Le comportement est indéfini si circuit ou target n'est pas un pointeur valide et non nul vers un QkCircuit et QkTarget. Le comportement est indéfini si config est un pointeur non nul qui ne pointe pas vers un objet QkVF2LayoutConfiguration valide (mais un pointeur nul est acceptable).

Paramètres

  • circuit - Un pointeur sur le circuit sur lequel VF2Layout doit être exécuté
  • target - Un pointeur vers la cible sur laquelle la passe VF2Layout doit être exécutée
  • config – Pointeur vers la structure QkVF2LayoutConfiguration de configuration. Si ce pointeur est nul, les valeurs par défaut du passage sont utilisées.
  • strict_direction – Si cette trueoption est activée, le passage tiendra compte de la direction des arêtes dans la connectivité décrite dans le fichier target. En général, il est préférable de régler ce false paramètre sur, car l'heuristique d'erreur est déjà très approximative, et les portes à deux qubits peuvent presque toujours être synthétisées de manière à « inverser » la direction en utilisant uniquement des portes locales à un qubit et la porte à deux qubits dans le sens natif.

Retours

Pointeur vers un objet résultat contenant les résultats du passage. Cet objet est alloué dans le tas et devra être libéré à l'aide de la qk_vf2_layout_result_free fonction.

qk_transpiler_pass_standalone_vf2_layout_exact

QkVF2LayoutResult *qk_transpiler_pass_standalone_vf2_layout_exact(const QkCircuit *circuit, const QkTarget *target, const QkVF2LayoutConfiguration *config)

Utilisez l'algorithme VF2 pour choisir une configuration (si possible) pour le circuit d'entrée, en utilisant un système de notation heuristique sensible au bruit qui exige que le résultat soit déjà entièrement compatible avec le matériel.

Cette fonction correspond à l'espace VF2PostLayout de passage de l' Python avec strict_direction=True.

Cette fonction convient aux circuits qui ont déjà été entièrement transposés en matériel et pour lesquels vous cherchez maintenant à déterminer si une permutation de qubits peut permettre d'obtenir de meilleurs taux d'erreur estimés. Si votre circuit est toujours en termes d'opérations non prises en charge par le matériel, utilisez qk_transpile_pass_standalone_vf2_layout_average à la place.

En général, vous appelez cette passe après la disposition, le routage, la traduction vers un ensemble de base natif et l'optimisation, de sorte que le circuit d'entrée soit déjà exécutable sur le matériel avec les indices de qubits faisant référence aux qubits physiques. Le pass renverra un résultat indiquant l'un des éléments suivants :

  • il existe un meilleur choix de mappage initial entre les qubits virtuels et physiques que celui actuellement utilisé par le circuit.
  • Le choix actuel de qubits physiques est le meilleur possible dans les limites de son appel.
  • il n'existe aucun choix valide de mappage virtuel-physique permettant d'obtenir un circuit exécutable (ou, du moins, le passage n'a pas réussi à en trouver un dans les limites spécifiées).

Dans les deux premiers cas, qk_vf2_layout_has_match renverra true. Dans le premier cas uniquement, qk_vf2_layout_has_improvement renverra true.

Exemple

QkTarget *target = qk_target_new(5)
QkTargetEntry *cx_entry = qk_target_entry_new(QkGate_CX);
for (uint32_t i = 0; i < current_num_qubits - 1; i++) {
    uint32_t qargs[2] = {i, i + 1};
    double inst_error = 0.0090393 * (current_num_qubits - i);
    double inst_duration = 0.020039;
    qk_target_entry_add_property(cx_entry, qargs, 2, inst_duration, inst_error);
}
QkExitCode result_cx = qk_target_add_instruction(target, cx_entry);
QkCircuit *qc = qk_circuit_new(4, 0);
for (uint32_t i = 0; i < qk_circuit_num_qubits(qc) - 1; i++) {
    uint32_t qargs[2] = {i, i + 1};
    for (uint32_t j = 0; j<i+1; j++) {
        qk_circuit_gate(qc, QkGate_CX, qargs, NULL);
    }
}
QkVF2LayoutConfiguration *config = qk_vf2_layout_configuration_new();
qk_vf2_layout_configuration_call_limit(config, 10000, 10000);
QkVF2LayoutResult *layout_result = qk_transpiler_pass_standalone_vf2_layout_exact(qc, target, config);
qk_vf2_layout_result_free(layout_result);
qk_vf2_layout_configuration_free(config);

Sécurité

Le comportement est indéfini si circuit ou target n'est pas un pointeur valide et non nul vers un QkCircuit et QkTarget. Le comportement est indéfini si config est un pointeur non nul qui ne pointe pas vers un objet QkVF2LayoutConfiguration valide (mais un pointeur nul est acceptable).

Paramètres

  • circuit – Pointeur vers le circuit sur lequel effectuer la recherche de disposition.
  • cible – Pointeur vers la cible représentant le QPU.
  • config – Pointeur vers la structure QkVF2LayoutConfiguration de configuration. Si ce pointeur est nul, les valeurs par défaut du passage sont utilisées.

Retours

Pointeur vers un objet résultat contenant les résultats du passage. Cet objet est alloué dans le tas et devra être libéré à l'aide de la qk_vf2_layout_result_free fonction.

qk_transpiler_pass_standalone_vf2_layout

QkVF2LayoutResult *qk_transpiler_pass_standalone_vf2_layout(const QkCircuit *circuit, const QkTarget *target, bool strict_direction, int64_t call_limit, double time_limit, int64_t max_trials)

Version obsolète de qk_transpiler_pass_standalone_vf2_layout_average.

Cette interface héritée n'utilise pas QkVf2LayoutConfiguration, et son nom ne précise pas clairement comment elle gère l'heuristique d'erreur (elle calcule la moyenne sur toutes les portes dans le QkTarget pour un qubit ou une liaison donné(e)).

Obsolète depuis la version 2.3.0

Sécurité

Les exigences de sécurité de qk_transpiler_pass_standalone_vf2_layout_average doivent être respectées pour circuit et target.

Paramètres

  • circuit – Comme dans qk_transpiler_pass_standalone_vf2_layout_average.
  • cible – Comme dans qk_transpiler_pass_standalone_vf2_layout_average.
  • strict_direction – Comme dans qk_transpiler_pass_standalone_vf2_layout_average.
  • call_limit – Comme dans qk_vf2_layout_configuration_set_call_limit, mais la même valeur est utilisée pour et before after.
  • time_limit – Comme dans qk_vf2_layout_configuration_set_time_limit.
  • max_trials – Comme dans qk_vf2_layout_configuration_set_max_trials.

Retours

Comme dans qk_transpiler_pass_standalone_vf2_layout_average.

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