Qiskit SDK 2.2 notes de mise à jour
2.2.3
Prélude
Qiskit 2.2.3 corrige un bug introduit par Qiskit 2.2.2 lors de l'utilisation de la run() méthode sur un PassManager pour plus d'un circuit.
Mise à niveau
ConsolidateBlockslit désormais unePropertySetcléConsolidateBlocks_qubit_mapà l'entrée. Cette clé et sa valeur ne sont pas publiques et ne doivent pas être lues ou écrites par d'autres passes.
Corrections des erreurs
- Réutilisation fixe de la même
ConsolidateBlocksinstance sur plusieurs circuits, y compris les appels verstranspile()plusieurs circuits et sans parallélisation basée sur les processus. Un bug introduit dans l' 2.2.2 e de Qiskit provoquait une panique ou produisait une sortie invalide si la même instance était réutilisée sur des circuits différents.
2.2.2
Prélude
Qiskit 2.2.2 est une version de correction de bogues pour la série de versions mineures v2.2.
Corrections des erreurs
-
Correction de l'implémentation de
__deepcopy__()dansQuantumCircuitqui ne copiait pas en profondeur les paramètres du circuit. Par conséquent, la mutation d'unBoxOpdans un circuit copié n'affecte plus le circuit d'origine. -
Correction d'un problème dans le
Optimize1qGatesDecompositionpass lorsque celui-ci est initialisé avec unTargetcontenant des portes à 1 qubit avec des paramètres d'angle fixes. Auparavant, le passeur pouvait potentiellement générer des portes non incluses dans la cible, car il ne vérifiait pas si les portes de la cible prenaient en charge des valeurs de paramètres arbitraires. Correction du bug n° 14743. -
Correction d'un comportement incorrect dans le
BasisTranslatorpassage où une porte multi-qubit dans unControlFlowOpbloc effectuait un suivi à l'aide de ses indices de qubit locaux au lieu d'utiliser les indices absolus du circuit source. -
Le passage du
ConsolidateBlockstranspilateur évaluera désormais correctement si une porte donnée est prise en charge par le matériel lors de la récursivité dans les opérations de flux de contrôle. -
qpy.dump()peut désormais gérer l'écriture dans.gzdes fichiers ouverts à l'aide du modulegzipstandard-library avec les versions 16 ou supérieures de QPY. Voir le n° 15157 pour plus de détails. -
Correction de la méthode
MCPhaseGate.inverse()pour préserver les états de contrôle des portes à commande ouverte lors du calcul de leurs inverses. -
ConsolidateBlocksrenverra désormais une exception d'espace Python au lieu de paniquer lorsqu'il détecte une analyse invalide ou obsolète dans les clésblock_listPropertySethéritéesrun_listou. Correction du bug n° 14646. -
Optimize1qGatesDecompositionva désormais générer une exceptionTranspilerErrorau lieu d'une panique Rust-space lors d'une tentative d'exécution sur un circuit trop grand pour leTarget. Correction du bug n° 15116. -
Les passes de planification et
ALAPScheduleAnalysisgéreront désormais correctement les circuitsASAPScheduleAnalysisne contenant aucune opération. Auparavant, ils avaient soulevé uneTranspilerErrorfausse allégation selon laquelle « aucune durée n'était fournie ». Correction du bug n° 15145. -
Correction d'une erreur dans le dessinateur de texte de circuit, qui pouvait se produire lorsque des blocs de circuit à l'intérieur d'opérations de flux de contrôle étaient définis sur des registres différents de ceux du circuit externe. Cette situation peut par exemple se produire lors de l'ajout direct
ControlFlowOpd'opérations, ou pour les circuits après transcompilation.
2.2.1
Prélude
Qiskit 2.2.1 est un petit patch qui corrige plusieurs bugs identifiés dans la version 2.2.0.
Notes de mise à niveau du transpilateur
- Les limites maximales d'appel et d'essai pour l'exécution à correspondance exacte de
VF2PostLayoutàoptimization_level=3ont été réduites afin d'éviter des durées d'exécution excessives pour les circuits d'essai hautement symétriques mappés sur de grandes cartes de couplage.
Corrections des erreurs
-
DAGCircuit.apply_operation_back(),apply_operation_back()etcircuit_to_dag()va maintenant ajouter de nouvelles arêtes dans un ordre déterministe. Le comportement précédent pouvait entraîner certaines passes du transcompilateur (telles queSabreSwap) à parcourir le DAG dans un ordre non déterministe. -
DAGCircuit.apply_operation_front()ne peut plus insérer de boucles auto-référencées invalides lors du traitement de nœuds incluant des conditions classiques. -
Correction d'un problème avec
picklela prise en charge deSabreSwapoù uneSabreSwapinstance renvoyait une erreur lors de la mise en conserve après l'exécution deSabreSwap.run()la méthode. Correction du bug n° 15071. -
Correction d'un problème où ne
is_unitary()respectait pas correctement les valeurs de tolérance d'entrée lors de la vérification de l'unitarité d'un opérateur. La méthode utilise désormais correctement les paramètresrtoletatolfournis lors de la simplification de l'opérateur et de la vérification de son égalité avec l'identité. Cela corrige le problème n° 14107.
2.2.0
Prélude
Le Qiskit v2.2 apporte plusieurs améliorations à l'API C et au transpileur, ainsi que de nombreuses autres améliorations et corrections de bogues. Les principales caractéristiques de cette nouvelle version sont les suivantes
- Fonction de transpilation de l'API C : l'API C comprend désormais une fonction permettant de transpilier un circuit quantique :
qk_transpile(). Cette fonction est équivalente à la fonctiontranspile()Python pour un contexte C autonome.- Passage de transformation Litinski : nouveau passage de transformation
LitinskiTransformationqui implémente la transformation décrite arXiv:1808.02892. Ce passe est généralement utilisé dans la compilation pour les architectures tolérantes aux pannes.- Prise en charge des limites d'angle pour les cibles : la
Targetclasse prend désormais en charge la spécification de limites pour les valeurs autorisées pour les opérations paramétrées ajoutées à la cible. Lorsqu'une instruction est ajoutée au,Targetvous pouvez ajouter l'argument facultatif angle_bounds pour spécifier les limites supérieure et inférieure des portes de rotation paramétrées. Un nouveau passage deWrapAnglestranspiler a été ajouté pour appliquer les contraintes d'angle dans le cadre d'un pipeline de transpilation.
La série de versions v2.2 est la dernière série de versions mineures avec le support Python 3.9. La version minimale de Rust utilisée pour construire Qiskit à partir des sources est maintenant Rust v1.85, augmentée de 1.79 dans 2.1.0. Pour plus d'informations sur les changements ci-dessus et les autres modifications apportées, veuillez consulter les notes de mise à jour ci-dessous et la documentation mise à jour.
Fonctionnalités de l'API C
-
Ajout de nouvelles fonctions autonomes de passage du transpondeur à l'API C. Ces fonctions prennent en compte une adresse
QkCircuitpour exécuter la passe et sont équivalentes à l'appel d'une passe instanciée. -
Le
QkTargettype peut désormais représenter des cibles qui prennent en charge les typesQkGateparamétrés acceptant n'importe quelle valeur de paramètre. Auparavant, ces portes ne pouvaient être ajoutées à la cible qu'avec une valeur d'angle fixe prise en charge à l'aide deqk_target_entry_new_fixed()pour créer leQkTargetEntry. Désormais, laqk_target_entry_new()fonction peut être utilisée avec des portes paramétrées. Lorsqu'elle est utilisée avec des portes paramétrées, cette fonction indique que la porte dans la cible prend en charge n'importe quelle valeur pour tous les paramètres de la porte. Par exemple :#include <qiskit.h> QkTarget *target = qk_target_new(5); QkTargetEntry *rz_entry = qk_target_entry_new(QkGate_RZ); for (uint32_t i = 0; i < 5; i++) { uint32_t qargs[1] = {i}; qk_target_entry_add_property(rz_entry, qargs, 1, 1.2e-6, 1.3e-9); } qk_target_add_instruction(target, rz_entry); // Clean up after using target qk_target_free(target);Cela crée une cible de 5 qubits qui acceptera une porte RZ sur n'importe quel qubit avec n'importe quelle valeur de paramètre prise en charge par cette porte.
-
Ajouté
qk_obs_apply_layout()pour appliquer de nouvelles dispositions de qubits à unQkObsobservable. Cette fonction prend en paramètre l'observable, les nouveaux indices de qubits et un nombre de qubits en sortie. Il est important de noter que cette fonction permet d'appliquer des mises en page de transpilation, généralement fournies parQkTranspileLayoutun passage de transpilateur, à un observable. Par exemple :// get the number of output qubits -- transpile_layout is a QkTranspileLayout* uint32_t num_output_qubits = qk_transpile_layout_num_output_qubits(transpile_layout); // get the layout including the ancillas (hence the ``false`` in the function call) uint32_t *layout = malloc(sizeof(uint32_t) * num_output_qubits); qk_transpile_layout_final_layout(transpile_layout, false, layout); // apply the layout -- obs is a QkObs* int exit = qk_obs_apply_layout(obs, layout, num_output_qubits); // free the layout array free(layout); -
Ajout d'une nouvelle fonction
qk_transpile()à l'API C de Qiskit. Cette fonction est utilisée pour transcompiler des circuits quantiques dans un contexte C autonome sans utiliser Python. Il s'agit du dernier composant majeur nécessaire dans l'API C pour les workflows d'exécution matérielle classiques utilisant Qiskit.Cette fonction reflète les gestionnaires de passes prédéfinis qui sont utilisés pour le transpileur Python, à l'exception de certaines passes et fonctionnalités qui sont ignorées si elles ne sont pas pertinentes pour les circuits construits à l'aide de l'API C. Cette fonction ne convient donc qu'aux contextes C autonomes.
-
Ajout d'un nouveau type
QkTranspileLayoutà l'API C. Ce type est utilisé pour raisonner sur les permutations causées par le transpileur.
Caractéristiques des circuits
-
Une nouvelle méthode
QuantumCircuit.ensure_physical()est fournie pour garantir qu'un circuit est défini sur des qubits physiques, les indices de qubits faisant référence à des qubits physiques. Pour plus de détails sur les concepts liés aux métadonnées, consultez la nouvelle discussion sur les représentations abstraites et physiques des circuits dans la documentation. Les concepts de circuits « abstraits » et « physiques » ne sont pas nouveaux pour Qiskit, seule la documentation explicite l'est. -
La classe
Durations'est enrichie d'une nouvelle varianteps, qui peut être utilisée pour représenter une durée en picosecondes. -
Amélioré
PauliEvolutionGate.control(),PauliEvolutionGate.power()etPauliEvolutionGate.inverse()pour renvoyer des représentations plus efficaces en termes de aPauliEvolutionGate. Pour le calcul des versions contrôlées et exponentielles de la porte d'évolution, cette modification conduit à des circuits nettement moins profonds et à un nombre de portes inférieur par rapport aux mécanismes génériques utilisés précédemment. La décomposition inverse ne change pas, mais elle est désormais générée plus efficacement et permet de meilleures optimisations du compilateur. -
Une nouvelle méthode
ParameterExpression.bind_all()rapide a été ajoutée pour prendre en charge le cas d'utilisation consistant à lier de nombreuses instancesParameterExpressiondifférentes à des valeurs numériques à l'aide du même dictionnaire de mappages. Labind()méthode existante entraîne une charge importante et des allocations inutiles, car elle renvoie toujours unParameterExpressionpour assurer la cohérence de la saisie.
OpenQASM Caractéristiques
-
Ajout d'une prise en charge partielle des
defcalsymboles dans l'exportateur OpenQASM3. Cela permet aux paquets en aval d'exporter des instructions personnalisées qui fonctionnent à la fois sur des bits quantiques et classiques à l'aide deqiskit.qasm3.dumps(). Les utilisateurs peuvent désormais définir des instructions personnalisées (par exemple, une instructionCustomMeasurequi agit sur un qubit et renvoie un bit classique) et spécifier leur comportement à l'aide deDefcalInstruction. Ces défis sont transmis à l'exportateur viaimplicit_defcalsl'argument dansqiskit.qasm3.dumps().Par exemple :
from qiskit.circuit import Instruction, QuantumCircuit from qiskit.qasm3 import dumps from qiskit.qasm3.exporter import DefcalInstruction, types custom_measure = Instruction("measure_2", 1, 1, []) qc = QuantumCircuit(1, 1) qc.h(0) qc.append(custom_measure, [0], [0]) qc.measure(0, 0) defcals = { "measure_2": DefcalInstruction("measure_2", 0, 1, types.Bool()), } out_qasm = dumps(qc, implicit_defcals=defcals) print(out_qasm)Le résultat serait la chaîne OpenQASM3 suivante, valide :
OPENQASM 3.0; bit[1] c; qubit[1] q; h q[0]; c[0] = measure_2 q[0]; c[0] = measure q[0];Cette approche suppose que la définition de la grammaire pour le defcal est fournie à l'extérieur (par exemple, dans un fichier d'en-tête), bien qu'un tel fichier ne soit pas strictement nécessaire pour que l'exportateur fonctionne.
-
Les fonctions
qasm3.loads()et disposentqasm3.load()désormais d'un argument supplémentaire appelénum_qubits. Si elles sont fournies, les fonctions renverront des circuits dont les qubits seront égaux ànum_qubits. Si cette information n'est pas fournie, le circuit renvoyé aura un nombre de qubits égal à l'indice maximal observé dans le circuit sérialisé. Pour plus de détails, voir le n ° 14435
Caractéristiques du QPY
-
Ajout d'un paramètre nommé
min_qpy_versiondans le fichier de configuration utilisateur. Une fois défini, il définit la version minimale autorisée de QPY pourqpy.load(). Si la version du format d'un fichier QPY est inférieure au paramètreminimum_qpy_version``minimum_qpy_version, une exception sera levée. -
Introduction de la version 16 du format QPY. Cette nouvelle version introduit une nouvelle table de début de circuit dans l'en-tête du fichier, qui contient les décalages d'octets du début de chaque circuit dans un fichier QPY. Cela permet un chargement potentiellement plus efficace des circuits à partir des fichiers QPY, et une mise en œuvre de Rust potentiellement multithreadée à l'avenir. En outre, la nouvelle version du format prend en charge la nouvelle variante
DURATIONdes picosecondes.
Caractéristiques de l'information quantique
-
Ajout des méthodes
PauliLindbladMap.drop_qubits()PauliLindbladMap.keep_qubits()et pour tracer les sous-systèmes hors des cartes de Pauli Lindblad. -
Ajout des méthodes
QubitSparsePauli.to_pauli()etQubitSparsePauliList.to_pauli_list(), qui convertissent respectivement les objets clairsemés en versions denses correspondantes,PaulietPauliList. -
Ajout des
PhasedQubitSparsePauliclassesPhasedQubitSparsePauliListet. Ces classes représentent respectivement un opérateur de Pauli unique et une liste d'opérateurs de Pauli stockés au format qubit-sparse. Ces classes sont très similaires àQubitSparsePaulietQubitSparsePauliList, sauf qu'elles contiennent en plus des informations de phase. -
Ajout de la méthode
QubitSparsePauliList.to_dense_array(). Cela renvoie la liste sous forme d'un tableau d'entiers contenant les valeurs dePauli.
Caractéristiques de la synthèse
-
Ajout d'un nouvel algorithme de synthèse pour
ModularAdderGatequi ne nécessite aucun qubit auxiliaire et présente un meilleur nombre de CX par rapport àadder_qft_d00(): -
Ajout d'un nouvel algorithme de synthèse,
synth_mcx_noaux_hp24(), pourMCXGatequi ne nécessite aucun qubit auxiliaire. Cette méthode produit un nombre linéaire, plutôt que quadratique, de portes CX, par rapport àsynth_mcx_noaux_v24()l'algorithme existant. En particulier, la nouvelle méthode est plus efficace lorsque le nombre de qubits de contrôle est supérieur à cinq. L'algorithme est basé sur l'article « Compiling Conditional Quantum Gates without Using Helper Qubits » (Compilation de portes quantiques conditionnelles sans utiliser de qubits auxiliaires) de Huang et Palsberg ( https://dl.acm.org/doi/10.1145/3656436 ). -
Amélioration de la
qs_decomposition()fonction qui était initialement basée sur Shende et. al. (https://arxiv.org/abs/quant-ph/0406176). La nouvelle méthode de synthèse est basée sur Krol et Al-Ars ( https://arxiv.org/abs/2403.13692 ) et réduit le nombre total deCXGates d'un unitaire n-qubit général par sCXGated' . Grâce à cette décomposition améliorée, une unité générale à 3 qubits peut être décomposée en 19CXGates (au lieu de 20). -
Ajouté
synth_mcmt_xgate()pour synthétiser la porte multi-contrôle multi-cible lorsque la porte de base estXGate. Il comporte une décomposition en nombre linéaire de portes CX et 0 qubits ancillaires, ainsi qu'un plugin de synthèse deMCMTSynthesisXGatehaut niveau.
Fonctionnalités du transpilateur
-
Ajout d'un nouveau plugin de synthèse de haut niveau pour synthétiser un
ModularAdderGate:ModularAdderSynthesisV17, basé suradder_modular_v17().
Le
ModularAdderSynthesisDefaulta également été mis à jour pour suivre la séquence suivante de synthétiseurs additionneurs modulaires :"ModularAdder.qft_d00"lorsque le nombre de qubits est ,"ModularAdder.modular_v17"dans tous les autres cas. -
Ajout d'un nouveau passage de
LitinskiTransformationtranspiler qui implémente la transformation décrite dans arXiv:1808.02892.L'entrée du passage est un circuit avec des portes Clifford et des portes de rotation RZ à un seul qubit, et la sortie est un circuit avec des rotations de Pauli multi-qubits (implémentées sous forme de
PauliEvolutionGateportes ) suivies de portes Clifford. Le passage lève uneTranspilerErrorexception si le circuit contient des portes non prises en charge.Le laissez-passer prend en charge toutes les portes Clifford figurant dans la liste renvoyée par
get_clifford_gate_names(), à savoir["id", "x", "y", "z", "h", "s", "sdg", "sx", "sxdg", "cx", "cz", "cy", "swap", "iswap", "ecr", "dcx"]. La liste des rotations RZ prises en charge est la suivante["t", "tdg", "rz"](nous convertissons automatiquement les portes T et Tdg en rotations RZ).De plus, le
LitinskiTransformationconstructeur accepte un argumentfix_clifford. LorsqueFalse(non par défaut), le circuit renvoyé ne contient quePauliEvolutionGatedes portes, les portes Clifford finales étant omises. Notez que dans ce cas, les opérateurs des circuits d'origine et synthétisés ne seront généralement pas équivalents.Par exemple :
from qiskit.circuit import QuantumCircuit from qiskit.transpiler.passes import LitinskiTransformation from qiskit.quantum_info import Operator # The following quantum circuit consists of 5 Clifford gates # and two single-qubits RZ-rotation gates (note that Tdg is # an RZ-rotation). qc = QuantumCircuit(2) qc.cx(0, 1) qc.rz(0.1, 0) qc.cz(0, 1) qc.tdg(1) qc.h(1) qc.s(1) qc.cz(1, 0) # The transformed circuit consists of two PauliEvolution gates # and the same Clifford gates as in the original circuit. qct = LitinskiTransformation()(qc) # The circuits before and after the transformation are equivalent assert Operator(qc) == Operator(qct) -
Ajout d'un nouveau plugin de synthèse de
MCXSynthesisNoAuxHP24haut niveau pourMCXGateles objets. De plus, le plugin de synthèseMCXSynthesisDefaultpar défaut pourMCXGateles objets a été mis à jour afin de toujours choisir la meilleure méthode de synthèse en fonction du nombre de qubits auxiliaires disponibles. -
Ajout de la prise en charge d'un
Targetpour spécifier les limites d'angle sur les instructions. Avant cette version, unTargetpouvait spécifier qu'une opération prenant un paramètre accepterait soit n'importe quelle valeur valide, soit une valeur spécifique. Par exemple, siRZGate(Parameter("theta"))était ajouté à la cible, cela indiquerait qu'unRZGateavec n'importe quelle valeur pour thêta était autorisé. SiRZGate(math.pi)était ajouté à la cible, cela indiqueraitRZGateque seule la valeur est autorisée sur la cible. Cette nouvelle fonctionnalité permet de limiter les angles autorisés à n'importe quellefloatvaleur comprise entre deux limites incluses. Par exemple, vous pouvez ajouterRZGate(math.pi)à unTargetet limiter la valeur de l'angle entre les valeurs 0 et .Il existe plusieurs méthodes pour travailler avec les limites d'angle sur la cible. Le premier est
Target.add_instruction()qui dispose d'un nouvel argumentangle_boundsclé utilisé pour ajouter une limite d'angle à une instruction dans leTarget. Pour travailler avec les limites angulaires, vous devrez également enregistrer une fonction de rappel dans le registreWRAP_ANGLE_REGISTRYglobal qui indiquera au transcompilateur etWrapAnglespass comment ajuster les portes pour les limites angulaires. La fonction de rappel prendra une liste de valeursfloatarbitraires représentant les angles de porte du circuit, ainsi que les indices de qubit dans le circuit sur lequel la porte fonctionnait, et renverra unDAGCircuitqui représente un circuit équivalent pour la porte avec cet angle, mais en respectant les limites d'angle et autresTargetcontraintes. Par exemple :import math from qiskit.dagcircuit import DAGCircuit from qiskit.transpiler import Target from qiskit.transpiler.passes.utils.wrap_angles import WRAP_ANGLE_REGISTRY target = Target(num_qubits=1) target.add_instruction(RZGate(Parameter("theta")), angle_bounds=[(-math.pi, math.pi)]) def callback(angles: List[float], qubits: List[int]) -> DAGCircuit: """Callback function to wrap RZ gate angles Args: angles: The list of floating point parameter values for the instance of RZGate in the circuit qubits: The physical qubit indices that this gate is operating on Returns: The DAGCircuit of the equivalent circuit""" angle = angles[0] dag = DAGCircuit() dag.add_qubits([Qubit()]) if angle > 0: divisor = math.pi else: divisor = -math.pi gate_counts = int(angles[0] // divisor) rem = angles[0] % divisor for _ in range(gate_counts): dag.apply_operation_back(RZGate(math.pi), [dag.qubits[0]], check=True) dag.apply_operation_back(rem, [dag.qubits[0]], check=True) WRAP_ANGLE_REGISTRY.add_wrapper("rz", callback)Target.has_angle_bounds()peut être utilisé pour vérifier si des limites d'angle sont définies dans la cible, etTarget.gate_has_angle_bounds().Si vous souhaitez appliquer les limites d'angle d'une cible à n'importe quelle porte d'un circuit, vous devez utiliser le passage
WrapAnglesdu transcompilateur. -
Ajout d'un nouveau kwarg
check_angle_boundsà laTarget.instruction_supported()méthode. Lorsque cette option est définie surTrue(valeur par défaut), la méthode vérifie si la valeur spécifiée estparameterségalement conforme aux limites d'angle pouvant exister pour l'instruction interrogée. -
Ajout d'un nouveau passage de
WrapAnglestranspileur utilisé pour appliquer des contraintes d'angle aux portes dans leTarget. Si unTargeta défini des limites d'angle, cette passe analysera tous les paramètres des portes du circuit et les vérifiera par rapport aux limites spécifiées dans la cible. Par exemple, si une cible contient une porte personnalisée avec des limites d'angle, le passage décomposera cette porte en une porte conforme aux limites :from qiskit.circuit import Gate, Parameter, QuantumCircuit, Qubit from qiskit.dagcircuit import DAGCircuit from qiskit.transpiler import Target, WrapAngleRegistry from qiskit.transpiler.passes import WrapAngles class MyCustomGate(Gate): def __init__(self, angle): super().__init__("my_custom", 1, [angle]) param = Parameter("a") circuit = QuantumCircuit(1) circuit.append(MyCustomGate(6.0), [0]) target = Target(num_qubits=1) target.add_instruction(MyCustomGate(param), angle_bounds=[(0, 0.5)]) def callback(angles, _qubits): angle = angles[0] if angle > 0: number_of_gates = angle / 0.5 else: number_of_gates = (6.28 - angle) / 0.5 dag = DAGCircuit() dag.add_qubits([Qubit()]) for _ in range(int(number_of_gates)): dag.apply_operation_back(MyCustomGate(0.5), [dag.qubits[0]]) return dag registry = WrapAngleRegistry() registry.add_wrapper("my_custom", callback) wrap_pass = WrapAngles(target, registry) res = wrap_pass(circuit) res.draw('mpl')
-
DAGCircuitdispose désormais d'une implémentation manuelle de__deepcopy__(). C'est beaucoup plus rapide que l'implémentation implicite précédente du protocole pickle, en particulier pour les circuits de grande taille. Cela améliore également directement les performances de compilation lors de l'exécutiontranspile()ou de l'exécution des gestionnaires de passes prédéfinis renvoyés pargenerate_preset_pass_manager()àoptimization_level=3car le niveau d'optimisation 3 copie en profondeur en interne leDAGCircuitpour chaque itération de la boucle d'optimisation dans laoptimizationphase. -
Une nouvelle méthode est proposée,
DAGCircuit.make_physical()qui remplace efficacement les qubits dans leDAGCircuitpar le registre canonique de qubits physiques, pouvant inclure une expansion. Une méthode similaire est égalementQuantumCircuit.ensure_physical()disponible. -
Une nouvelle méthode,
DAGCircuit.structurally_equal(), peut être utilisée si deuxDAGCircuitinstances ont été créées et modifiées dans le même ordre. Il s'agit d'un test beaucoup plus rigoureux que la vérification standard de l'équivalence sémantique de la==surcharge, et il peut être utilisé par les auteurs de transpilateurs pour vérifier que leurs ordres de modification sont déterministes. -
Les sous-classes personnalisées de
BasePassManagerpeuvent désormais modifier leurproperty_setattribut lors de leur_passmanager_frontend()méthode afin d'initialiser les propriétés initiales. Cela apporte une symétrie, car auparavant, il n'était possible de lire les propriétés finales que pendant_passmanager_backend(). -
Ajout d'une nouvelle classe
OptimizationMetricqui spécifie le critère d'optimisation dans leHighLevelSynthesispassage. Actuellement, les deux indicateurs pris en charge sont les suivants :COUNT_2Qle nombre de portes à deux qubits est optimisé.COUNT_Tle nombre de portes T est optimisé lors de la transposition dans un ensemble de base Clifford+T.
Le transpilateur sélectionne automatiquement la métrique cible en fonction du jeu de bases, par exemple, il utilisera
COUNT_Tsi un jeu de bases Clifford+T est détecté. Cependant, cette classe ne peut actuellement pas être définie manuellement lors de l'exécutiontranspile()ou de l'exécution d'un gestionnaire de passe prédéfini généré pargenerate_preset_pass_manager(). -
Ajout d'un nouvel argument
optimization_metricau constructeur pour le passageHighLevelSynthesisdu transcompilateur qui prend unOptimizationMetricobjet. Lorsqu'il est réglé surCOUNT_T, le pass choisit les décompositions qui conviennent le mieux à l'ensemble de portes Clifford+T. -
Les plugins de synthèse de haut niveau par défaut pour
ModularAdderGateetMultiplierGateproduisent de meilleurs T-counts lors de la transcompilation dans le jeu de bases Clifford+T. -
Le plugin de synthèse de haut niveau par défaut pour
MCXGateproduit de meilleurs T-counts lors de la transcompilation dans le jeu de bases Clifford+T, à condition qu'au moins 1 qubit ancilla soit disponible. -
Ajout d'un ensemble par défaut de portes inversées pour le passage
InverseCancellationdu transcompilateur. Auparavant, une liste explicite des portes ou des paires de portes à annuler était un argument obligatoire pour le constructeur de l'objet pass. Cette liste est facultative et, si aucune liste n'est fournie, les portes auto-inverses sont les suivantes :et les paires inverses :
sera annulée par le laissez-passer.
-
Ajout d'un nouvel argument au
InverseCancellationconstructeur,run_defaultqui, lorsqu'il est défini surTrue, exécutera la nouvelle liste de portes d'annulation inverse par défaut en plus des portes personnalisées fournies. Ceci est destiné aux cas où vous souhaitez exécuter un ensemble personnalisé d'annulations inverses en plus des portes par défaut. -
TranspileLayoutdispose de deux nouvelles méthodes :from_property_set()etwrite_into_property_set(), qui formalisent la structure ad hoc actuelle des propriétés de transpilation et la manière dont elles sont converties enTranspileLayout. Cela permet aux passes d' un pipeline de transpiler d'accéder à ce que seraTranspileLayoutle, de le modifier sous sa forme entièrement structurée, puis de le réécrire sous sa forme canonique.Il est prévu que dans la future version 3.0 de Qiskit, le
TranspileLayout(ou quelque chose de similaire) soit un attribut direct de la représentationDAGCircuitintermédiaire du transcompilateur, et soit requis par les passes afin d'être synchronisé avec le reste duDAGCircuit. -
Réactivation du passage
VF2PostLayoutdu transpiler dans laoptimizationphase pouroptimization_level=3avec latranspile()fonction et les objets gestionnaires de passage générés renvoyés par lagenerate_preset_pass_manager()fonction. Le passage s'effectuestrict_direction=Trueaprès toutes les optimisations physiques réalisées au cours de cette étape afin d'essayer d'améliorer une dernière fois la disposition avec le circuit de sortie exact. Cette fonctionnalité était auparavant activée dans Qiskit v2.1.0, mais a été désactivée dans 2.1.2 en raison de problèmes liés à la mise en œuvre initiale. Ces problèmes ont été corrigés et la mise en page sera correctement appliquée si une meilleure mise en page est trouvée.
Fonctionnalités de visualisation
-
Une nouvelle option,
measure_arrows, a été ajoutée aux backendsmpl``textet pour les dessineurs de circuitsqiskit.visualization.circuit_drawer()etqiskit.circuit.QuantumCircuit.draw(). Lorsque cette option est activéeTrue, le tiroir dessine une flèche entre lameasurecase et les bits classiques situés en dessous. C'était le comportement précédent dans les tiroirs. Si cette option est activéeFalse, aucune flèche ne sera dessinée et, à la place, le registre classique et le bit utilisé par lemeasureseront indiqués à l'intérieur de lameasureboîte. Cela permetmeasured'empiler les boîtes dans une couche verticale.Si aucune option n'est définie, la valeur par défaut est
True. L'utilisateur peut modifier la valeur par défaut dans le fichier de configuration de l'utilisateur, qui se trouve par défaut dans le répertoire~/.qiskit, dans le fichiersettings.conf. Sous la rubrique[Default], un utilisateur peut saisircircuit_measure_arrows = Falsepour modifier la valeur par défaut.
Mise à niveau
- La version minimale de Rust pour construire Qiskit à partir des sources (y compris la construction de l'API C en mode autonome) a été augmentée de Rust 1.79 à Rust 1.85. Ce changement était nécessaire pour permettre l'utilisation d'une version plus récente de la bibliothèque d'algèbre linéaire Rust faer qui est utilisée dans Qiskit. Des problèmes ont été identifiés lors de l'exécution de Qiskit sur Windows avec la version précédente de faer. Ces problèmes ont été corrigés dans la nouvelle version, mais une version plus récente du compilateur Rust est nécessaire pour construire la nouvelle version de faer.
Notes sur la mise à niveau des circuits
-
La définition du circuit de
ModularAdderGatea été mise à niveau pour utiliseradder_modular_v17(). Pour obtenir l'ancien comportement, utilisez plutôt la définitionadder_qft_d00()de. -
Les méthodes
XGate.control(),CXGate.control(),CCXGate.control(),C3XGate.control()C4XGate.control(), etMCXGate.control()ne renvoient plus uneAnnotatedOperationlorsque l'argumentannotatedest défini surTrue, mais renvoient à la place la même expliciteMCXGateque celle obtenue lorsqueannotatedestFalse. Cela est cohérent avec la manière dont l'argumentannotatedest utilisé dans la bibliothèque de circuits standard, où nous évitons généralement d'introduire unAnnotatedOperationlorsqu'une classe de porte native est déjà disponible. Dans la pratique, cela conduit à des décompositions plus efficaces des portes annotées par contrôle dans la famille MCX.
Notes de mise à niveau de l'API C
-
La plupart des usages de
uintptr_tont été remplacés parsize_t. En particulier, les usages suivants ont été modifiés :QkOpCount.countQkOpCounts.lenQkObsTerm.len- Le type de retour de
qk_circuit_num_instructions(). indexL'argument dansqk_circuit_get_instruction().boundariesL'argument dansqk_obs_new().- Les types de retour de
qk_obs_num_terms(),qk_obs_len(), etqk_obs_boundaries(). - Le type de retour de
qk_target_entry_num_properties(), etqk_target_num_instructions().
Ce changement était nécessaire car l'outil utilisé pour générer les fichiers d'en-tête C à partir du code Rust de Qiskit, cbindgen, utilisait
uintptr_tpar défaut à des endroits oùsize_tcorrespondait mieux à l'utilisation des types en Rust. Cette modification a été apportée pour clarifier la manière dont les valeurs de l'API C sont destinées à être utilisées.
Notes de mise à niveau QPY
- La version par défaut du QPY émis par
qpy.dump()est désormais le format QPY version 16. Si vous avez besoin d'une version de format différente, vous pouvez utiliserversionl'argument pour spécifier une version de format antérieure.
Notes de mise à jour sur les informations quantiques
SparsePauliOp.assign_parameters()va maintenant définir le type de données (dtype) ducoeffstableau de sortie àcomplexsi tous les paramètres sont entièrement liés à des valeurs numériques.
Notes de mise à niveau de Synthesis
- Les valeurs par défaut des arguments
opt_a1etopt_a2deqs_decomposition()sont désormaisopt_a1 = Noneetopt_a2 = None. Les nouveaux paramètres par défaut choisiront la valeur optimale en fonction du fait que l'unité d'entrée pourmatl'argument est contrôlée ou non afin d'obtenir le nombreCXGateminimal par défaut. Si vous souhaitez conserver le comportement précédent, vous pouvez appeleropt_a1 = Trueexplicitement etopt_a2 = Truepour conserver le même comportement que dans les versions précédentes.
Notes de mise à niveau du transpilateur
- Le circuit
PassManagerdéfinit désormais systématiquement les propriétésoriginal_circuit_indicesetnum_input_qubitsavant le début de l'exécution des passes individuelles. Il s'agit des propriétés du circuit d'entrée, qui étaient auparavant définies par chaque passage individuel, souvent comme effet secondaire de leur fonction principale.
Circuits obsolètes
-
Les classes suivantes de la bibliothèque des circuits sont obsolètes depuis Qiskit 2.2 et seront supprimées dans Qiskit 3.0. Ils ont été remplacés par des équivalents modernes.
Corrections des erreurs
-
ApplyLayouttraitera désormais correctement le cas de l'application d'un qubit nulLayout. Auparavant, il affirmait qu'aucune mise en page n'avait été définie, même si le"layout"champ duPropertySetétait égal àLayout(). -
Correction des problèmes de fuite de mémoire lors de la création d'une
QkOpCountsinstance et lors de tout appel àqk_opcounts_clear()lorsqu'une instance vide est transmise. -
Auparavant, on pouvait définir un invalide
PauliEvolutionGateà partir d'une liste d'opérateurs, où les opérateurs n'étaient pas tous définis sur le même nombre de qubits. Ce problème est désormais résolu, et nous générons désormais une erreur lorsque la porte est définie :from qiskit.quantum_info import Pauli, SparsePauliOp from qiskit.circuit.library import PauliEvolutionGate pauli = Pauli("XYZ") # 3 qubits op = SparsePauliOp(["XYIZ"], [1]) # 4 qubits evo = PauliEvolutionGate([pauli, op], time=1) -
Correction d'un problème dans le
VF2Layoutpassage du transcompilateur où, même avec un ensemble de graines fixe, la sortie du passage était potentiellement non déterministe; en particulier si le circuit d'entrée comportait des qubits actifs qui ne contenaient que des opérations à qubit unique. Corrigé #14729 -
Correction d'un bug dans
PassManager.run()où lacallbackfonction n'était pas invoquée lors de l'exécution avec plusieurs circuits. Le rappel est désormais correctement déclenché à chaque passage sur chaque circuit, y compris en cas d'exécution parallèle. -
Correction de plusieurs problèmes dans le
CommutativeInverseCancellationpassage du transcompilateur. Le passe-partout fonctionne désormais correctement sur les circuits contenantClifforddes opérations, des opérations de contrôle de flux et des opérations non inversibles telles queInitialize.En outre, la passe effectue toujours une vérification syntaxique (non basée sur la matrice) en premier lieu, lors de l'identification des paires de portes inversées. Si les portes ne sont pas syntaxiquement égales, que l'argument
matrix_basedest fixé àTrueet que l'opération n'agit pas sur plus demax_qubitsqubits, une vérification basée sur la matrice est également effectuée. Cela améliore légèrement le potentiel de réduction du col. -
Correction de plusieurs problèmes dans le
CommutativeCancellationpassage du transcompilateur (et donc danstranspile()), où la phase globale du circuit n'était pas mise à jour correctement. En particulier, la fusion d'une porte X et d'une porte RX a introduit un déphasage, tandis que la suppression d'une porte de rotation de Pauli avec un angle de la forme , a produit de manière incorrecte un déphasage de . -
Correction d'un problème dans
CommutationChecker, où les portes contrôlées standard n'étaient pas gérées correctement si elles étaient contrôlées sur un état autre que l'état « tout à 1 ». Corrigé #14974 -
Correction d'un problème de non-déterminisme dans
CommutativeCancellation. Cela n'a pas affecté l'ordre renvoyé parDAGCircuit.topological_nodes()outopological_op_nodes(), qui devraient généralement être utilisés lorsque le déterminisme de l'ordre des nœuds est important, en raison de leur fonction de tri canonique intégrée. Cependant, si l'on inspecte les nœuds dans un ordre arbitraire (DAGCircuit.op_nodes()) ou la structure des arêtes (DAGCircuit.edges()), l'ordre d'itération serait non déterministe après un appel àCommutativeCancellation. -
Correction d'un bug dans
MCXGate.control(), où l'ajout de commandes supplémentaires à un contrôlé ouvertMCXGatene tenait pas compte ductrl_statede la porte MCX contrôlée, ce qui entraînait un incorrectctrl_statede la porte MCX étendue. Notez que les classes MCXCXGateexplicites,CCXGate,C3XGateetC4XGateétaient déjà gérées correctement. -
Correction de l'avertissement de dépréciation pour Python 3.9 afin qu'il soit correctement identifié comme étant causé par du code utilisateur lors de l'importation de Qiskit. Auparavant, il n'était pas identifié comme étant causé par le code de l'utilisateur, ce qui signifiait que les filtres d'avertissement par défaut de Python n'affichaient pas l'avertissement à l'intention de l'utilisateur.
-
Correction d'un bug dans
PhaseOracle,PhaseOracleGateetBitFlipOracleGateoù la tentative de chargement à partir d'un fichier dimacs provoquait une erreurTypeError. -
Correction d'un bug dans le
ElidePermutationspassage du transcompilateur, où le mappage des qubits n'était pas mis à jour correctement en présence dePermutationGates, ce qui entraînait des circuits incorrects et des mises à jour incorrectes de l'ensemble de propriétés du gestionnaire de passages. -
Le transpilateur intégré qui définit la
final_layoutpropriété gère désormais correctement la mise à jour de ce champ s'il était déjà défini. Cela peut être observé dans la méthode quiTranspileLayout.routing_permutationrenvoie désormais une permutation correcte après avoir effectué plusieurs passages qui définissentfinal_layout.Cela n'a pas affecté les appels normaux à
transpile()ougenerate_preset_pass_manager()utilisant les plugins intégrés de Qiskit; aucun pipeline construit sous cette forme ne tenterait de définirfinal_layoutplus d'une fois. -
Correction d'un bug dans le
HighLevelSynthesispass où, si le circuit contenait des objets de haut niveau avec des registres classiques, ceux-ci étaient mappés à l'index relatif dans l'objet au lieu de l'index correspondant dans le circuit externe. Les registres classiques sont désormais correctement mappés à l'index du circuit externe. -
Correction d'un bug dans
Target.instruction_supported()où la vérification de l'ordre des qubits de l'instruction était ignorée lorsque la méthode était appelée avecoperation_nameetparametersdes arguments qui correspondaient à une instruction existante. -
Correction du comportement de
max_trialsl'argumentVF2Layoutlorsqu'il est défini surNoneou sur un nombre négatif. Le passe-partout a été documenté comme limitant la recherche à la taille du circuit ou de la cible si l'option était définie surNoneet comme acceptant des valeurs négatives pour spécifier une recherche illimitée. Cependant, dans l' 2.1.0, ce comportement a été modifié de manière incorrecte, de sorte queNoneeffectuait une recherche illimitée et que l'utilisation d'un nombre négatif provoquait une erreur. Ces oublis ont été corrigés afin que le passe-partout fonctionne comme prévu et soit conforme aux versions précédentes. -
Correction d'un problème dans les plugins de synthèse de
MCXSynthesis1DirtyKG24haut niveau etMCXSynthesis2DirtyKG24pourMCXGate, où les plugins ne considéraient pas les qubits auxiliaires propres disponibles comme des qubits auxiliaires sales disponibles. En particulier, le pluginMCXSynthesis2DirtyKG24ne s'appliquait pas lorsqu'un qubit auxiliaire propre et un qubit auxiliaire sale étaient disponibles. -
La
PauliEvolutionGate.to_matrix()méthode renvoie désormais l'exponentielle matricielle exacte , où est leoperatoret est letimetransmis à la porte. Cela corrige un comportement inattendu, car lePauliEvolutionGateest documenté pour représenter l'évolution temporelle exacte, mais auparavant, la matrice dépendait de la manière dont le compilateur approximait l'évolution temporelle. Lato_matrixméthode est désormais conforme à la documentation. -
Correction d'une régression des performances lors de la compilation incrémentielle
ParameterExpressionà partir de la combinaison d'un grand nombre de sous-expressions. Corrigé #14653 -
Correction d'un problème de correction lors de l'exportation de circuits avec des instructions de retard utilisant les unités 'ps' vers QASM3.
-
Correction d'un cas particulier dans l'affichage du
QFTcircuit. Auparavant, lorsqueQFT.inverse()était appelé et que les attributs du circuit QFT étaient modifiés, le QFT s'affichait sous la forme"IQFT_dg". Ceci était incorrect, et maintenant cela s'affiche correctement"IQFT". Correction du bug n° 14758. -
Correction d'un bug dans le
PauliEvolutionSynthesisRustiqplugin qui produisait des circuits incorrects dans le cas où l'opérateur d'unPauliEvolutionGatecontenait des objets de typeSparseObservable.Par exemple :
from qiskit.circuit.library import PauliEvolutionGate from qiskit.quantum_info import SparseObservable, Operator from qiskit.transpiler.passes.synthesis.hls_plugins import PauliEvolutionSynthesisRustiq obs = SparseObservable.from_sparse_list([("1+XY", (0, 1, 2, 3), 1.5)], num_qubits=4) evo = PauliEvolutionGate(obs, 1) qct = PauliEvolutionSynthesisRustiq().run(evo) assert Operator(qct) == Operator(evo) -
Correction d'un problème avec la
generate_preset_pass_manager()fonction qui ignorait de manière incorrecte les données de contraintes de synchronisation contenues dans unTargetobjet fourni lorsquebackendl'argument n'était pas défini. Corrigé #14329 -
Correction d'un bogue dans
ObservablesArray.coerce_observable()où une exception indiquant qu'une observable n'était pas hermitienne était surdéclenchée. Les observables égaux àzerone sont pas autorisés et invoquent désormais un échec gracieux. -
qiskit.circuit.library.quantum_volume()a été mis à jour pour traiter unnumpy.random.Generatorcomme entrée pour sonseedargument. Auparavant, un tel argument générateur aurait donné lieu à unTypeError. -
QuantumCircuit.compose()remapper correctement les variables et les segments utilisés dansDelayles instructions lorsquevar_remapl'argument est spécifié. -
SabreLayoututilise une disposition « sous-ensemble dense » comme l'un de ses essais, en suivant le même algorithme queDenseLayout. Auparavant, cependant, la version utilisée par Sabre attribuait tous les qubits virtuels, y compris les ancillas factices, à un qubit physique, ce qui compromettait l'efficacité de l'algorithme, mais pas son exactitude. Sabre n'utilisera désormais que les qubits virtuels définis par l'utilisateur pour cet essai initial, ce qui pourrait entraîner de légères améliorations dans la sélection de la disposition lorsqu'on calcule la moyenne sur de grandes classes de circuits. -
Correction d'un bug dans
SparsePauliOp.simplify()où la méthode supprimait les termes de Pauli en fonction de l'amplitude de leurs coefficients avant de combiner les doublons. Cela a entraîné un comportement incorrect dans deux cas limites importants :- Lorsque plusieurs termes de Pauli identiques avaient de petits coefficients qui étaient individuellement inférieurs au seuil de simplification mais dont la somme dépassait le seuil, ces termes ont été supprimés à tort.
- Lorsque plusieurs termes de Pauli identiques avaient des coefficients supérieurs au seuil mais dont la somme était proche de zéro, ils étaient incorrectement conservés.
Voir #14194 pour plus de détails.
-
TranspileLayout.initial_index_layout()gérera désormais correctementfilter_ancillas=Truel'argument si les qubits virtuels dans leinitial_layoutn'ont pas été spécifiés par le constructeur dans l'ordre d'indexation. -
VF2LayoutetVF2PostLayoutinclura désormais correctement les affectations de disposition (arbitraires) pour les qubits complètement inactifs. Auparavant, cela pouvait être observé par des appels àTranspileLayout.initial_index_layout()échouant après une compilation. -
Correction d'un problème dans le
VF2PostLayoutpassage du transcompilateur. Dans certaines situations, lorsque le passage est exécuté avec l'argument, un problème potentiel de mise àstrict_direction=Truel'échelle du temps d'exécution pouvait survenir lorsque le graphe d'interaction du circuit contenait des qubits qui n'avaient que des opérations à 1 qubit. Ces problèmes de mappage entraînent une complexité combinatoire pour le calcul des scores qui conduirait presque toujours à dépasser le temps imparti pour le calcul des scores et, en général, à ne pas améliorer la disposition. Enstrict_direction=Falsemode, il existe une implémentation de recherche optimisée pour ces problèmes, mais les contraintes supplémentaires pourstrict_direction=Truerendent cette approche irréalisable. Dans ces cas-là, la rechercheVF2PostLayoutsera désormais ignorée, car le problème de disposition n'est pas viable pour le passage.
Autres remarques
- La mise en œuvre du routage Sabre utilisé par
SabreLayoutetSabreSwapcompresse désormais les séries de nœuds qui deviendront automatiquement éligibles au routage en même temps dans sa représentation interne d'interaction virtuelle. Cela améliore l'efficacité du routage, réduit l'utilisation de la mémoire intermédiaire et évite les séries de portes d' 2q qui biaisent leslookaheadcomposants heuristiques.
2.1.0rc1
Remarques concernant la dépréciation
-
La prise en charge de l'exécution de Qiskit avec Python 3.9 est obsolète et sera supprimée dans la version de Qiskit 2.3.0. Le site 2.3.0 est la première version après que le site Python 3.9 a atteint sa fin de vie et n'est plus pris en charge. [1] Cela signifie qu'à partir de la version 2.3.0, vous devrez mettre à jour la version Python que vous utilisez vers Python 3.9 ou une version supérieure.