Skip to main content
IBM Quantum Platform

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

  • ConsolidateBlocks lit désormais une PropertySet clé 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 ConsolidateBlocks instance sur plusieurs circuits, y compris les appels vers transpile() 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__() dans QuantumCircuit qui ne copiait pas en profondeur les paramètres du circuit. Par conséquent, la mutation d'un BoxOp dans un circuit copié n'affecte plus le circuit d'origine.

  • Correction d'un problème dans le Optimize1qGatesDecomposition pass lorsque celui-ci est initialisé avec un Target contenant 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 BasisTranslator passage où une porte multi-qubit dans un ControlFlowOp bloc effectuait un suivi à l'aide de ses indices de qubit locaux au lieu d'utiliser les indices absolus du circuit source.

  • Le passage du ConsolidateBlocks transpilateur é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 .gz des fichiers ouverts à l'aide du module gzip standard-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.

  • ConsolidateBlocks renverra désormais une exception d'espace Python au lieu de paniquer lorsqu'il détecte une analyse invalide ou obsolète dans les clés block_listPropertySet héritées run_list ou. Correction du bug n° 14646.

  • Optimize1qGatesDecomposition va désormais générer une exception TranspilerError au lieu d'une panique Rust-space lors d'une tentative d'exécution sur un circuit trop grand pour le Target. Correction du bug n° 15116.

  • Les passes de planification et ALAPScheduleAnalysis géreront désormais correctement les circuits ASAPScheduleAnalysis ne contenant aucune opération. Auparavant, ils avaient soulevé une TranspilerError fausse 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 ControlFlowOp d'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=3 ont é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() et circuit_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 que SabreSwap) à 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 pickle la prise en charge de SabreSwap où une SabreSwap instance renvoyait une erreur lors de la mise en conserve après l'exécution de SabreSwap.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ètres rtol et atol fournis 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 fonction transpile()Python pour un contexte C autonome.
  • Passage de transformation Litinski : nouveau passage de transformation LitinskiTransformation qui 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 Target classe 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, Target vous 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 de WrapAngles transpiler 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

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 Duration s'est enrichie d'une nouvelle variante ps , qui peut être utilisée pour représenter une durée en picosecondes.

  • Amélioré PauliEvolutionGate.control(), PauliEvolutionGate.power() et PauliEvolutionGate.inverse() pour renvoyer des représentations plus efficaces en termes de a PauliEvolutionGate. 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 instances ParameterExpression différentes à des valeurs numériques à l'aide du même dictionnaire de mappages. La bind() méthode existante entraîne une charge importante et des allocations inutiles, car elle renvoie toujours un ParameterExpression pour assurer la cohérence de la saisie.

OpenQASM Caractéristiques

  • Ajout d'une prise en charge partielle des defcal symboles 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 de qiskit.qasm3.dumps(). Les utilisateurs peuvent désormais définir des instructions personnalisées (par exemple, une instruction CustomMeasure qui agit sur un qubit et renvoie un bit classique) et spécifier leur comportement à l'aide de DefcalInstruction. Ces défis sont transmis à l'exportateur via implicit_defcals l'argument dans qiskit.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 disposent qasm3.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_version dans le fichier de configuration utilisateur. Une fois défini, il définit la version minimale autorisée de QPY pour qpy.load(). Si la version du format d'un fichier QPY est inférieure au paramètre minimum_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 DURATION des picosecondes.

Caractéristiques de l'information quantique

Caractéristiques de la synthèse

  • Ajout d'un nouvel algorithme de synthèse pour ModularAdderGate qui 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(), pour MCXGate qui 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 de CXGates d'un unitaire n-qubit général par s CXGated' 4n213\frac{4^{n − 2} − 1}{3}. Grâce à cette décomposition améliorée, une unité générale à 3 qubits peut être décomposée en 19 CXGates (au lieu de 20).

  • Ajouté synth_mcmt_xgate() pour synthétiser la porte multi-contrôle multi-cible lorsque la porte de base est XGate. Il comporte une décomposition en nombre linéaire de portes CX et 0 qubits ancillaires, ainsi qu'un plugin de synthèse de MCMTSynthesisXGate haut niveau.

Fonctionnalités du transpilateur

  • Ajout d'un nouveau plugin de synthèse de haut niveau pour synthétiser un ModularAdderGate:

    Le ModularAdderSynthesisDefault a également été mis à jour pour suivre la séquence suivante de synthétiseurs additionneurs modulaires : "ModularAdder.qft_d00" lorsque le nombre de qubits est 4\leq 4, "ModularAdder.modular_v17" dans tous les autres cas.

  • Ajout d'un nouveau passage de LitinskiTransformation transpiler 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 PauliEvolutionGate portes ) suivies de portes Clifford. Le passage lève une TranspilerError exception 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 LitinskiTransformation constructeur accepte un argument fix_clifford. Lorsque False (non par défaut), le circuit renvoyé ne contient que PauliEvolutionGate des 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 MCXSynthesisNoAuxHP24 haut niveau pour MCXGate les objets. De plus, le plugin de synthèse MCXSynthesisDefault par défaut pour MCXGate les 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 Target pour spécifier les limites d'angle sur les instructions. Avant cette version, un Target pouvait spécifier qu'une opération prenant un paramètre accepterait soit n'importe quelle valeur valide, soit une valeur spécifique. Par exemple, si RZGate(Parameter("theta")) était ajouté à la cible, cela indiquerait qu'un RZGate avec n'importe quelle valeur pour thêta était autorisé. Si RZGate(math.pi) était ajouté à la cible, cela indiquerait RZGate que seule la valeur π\pi est autorisée sur la cible. Cette nouvelle fonctionnalité permet de limiter les angles autorisés à n'importe quelle float valeur comprise entre deux limites incluses. Par exemple, vous pouvez ajouter RZGate(math.pi) à un Target et limiter la valeur de l'angle entre les valeurs 0 et 2π2\pi.

    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 argument angle_bounds clé utilisé pour ajouter une limite d'angle à une instruction dans le Target. Pour travailler avec les limites angulaires, vous devrez également enregistrer une fonction de rappel dans le registre WRAP_ANGLE_REGISTRY global qui indiquera au transcompilateur et WrapAngles pass comment ajuster les portes pour les limites angulaires. La fonction de rappel prendra une liste de valeurs float arbitraires représentant les angles de porte du circuit, ainsi que les indices de qubit dans le circuit sur lequel la porte fonctionnait, et renverra un DAGCircuit qui représente un circuit équivalent pour la porte avec cet angle, mais en respectant les limites d'angle et autres Target contraintes. 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, et Target.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 WrapAngles du transcompilateur.

  • Ajout d'un nouveau kwarg check_angle_bounds à la Target.instruction_supported() méthode. Lorsque cette option est définie sur True (valeur par défaut), la méthode vérifie si la valeur spécifiée est parameters également conforme aux limites d'angle pouvant exister pour l'instruction interrogée.

  • Ajout d'un nouveau passage de WrapAngles transpileur utilisé pour appliquer des contraintes d'angle aux portes dans le Target. Si un Target a 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')
    _images/release_notes-1.png
  • DAGCircuit dispose 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écution transpile() ou de l'exécution des gestionnaires de passes prédéfinis renvoyés par generate_preset_pass_manager() à optimization_level=3 car le niveau d'optimisation 3 copie en profondeur en interne le DAGCircuit pour chaque itération de la boucle d'optimisation dans la optimization phase.

  • Une nouvelle méthode est proposée, DAGCircuit.make_physical() qui remplace efficacement les qubits dans le DAGCircuit par le registre canonique de qubits physiques, pouvant inclure une expansion. Une méthode similaire est également QuantumCircuit.ensure_physical() disponible.

  • Une nouvelle méthode, DAGCircuit.structurally_equal(), peut être utilisée si deux DAGCircuit instances 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 BasePassManager peuvent désormais modifier leur property_set attribut 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 OptimizationMetric qui spécifie le critère d'optimisation dans le HighLevelSynthesis passage. 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_T si un jeu de bases Clifford+T est détecté. Cependant, cette classe ne peut actuellement pas être définie manuellement lors de l'exécution transpile() ou de l'exécution d'un gestionnaire de passe prédéfini généré par generate_preset_pass_manager().

  • Ajout d'un nouvel argument optimization_metric au constructeur pour le passage HighLevelSynthesis du transcompilateur qui prend un OptimizationMetric objet. Lorsqu'il est réglé sur COUNT_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 ModularAdderGate et MultiplierGate produisent 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 MCXGate produit 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 InverseCancellation du 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 InverseCancellation constructeur, run_default qui, lorsqu'il est défini sur True , 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.

  • TranspileLayout dispose de deux nouvelles méthodes : from_property_set() et write_into_property_set(), qui formalisent la structure ad hoc actuelle des propriétés de transpilation et la manière dont elles sont converties en TranspileLayout. Cela permet aux passes d' un pipeline de transpiler d'accéder à ce que sera TranspileLayout le, 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ésentation DAGCircuit intermédiaire du transcompilateur, et soit requis par les passes afin d'être synchronisé avec le reste du DAGCircuit.

  • Réactivation du passage VF2PostLayout du transpiler dans la optimization phase pour optimization_level=3 avec la transpile() fonction et les objets gestionnaires de passage générés renvoyés par la generate_preset_pass_manager() fonction. Le passage s'effectue strict_direction=True aprè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 backends mpl``text et pour les dessineurs de circuits qiskit.visualization.circuit_drawer() et qiskit.circuit.QuantumCircuit.draw(). Lorsque cette option est activée True, le tiroir dessine une flèche entre la measure case et les bits classiques situés en dessous. C'était le comportement précédent dans les tiroirs. Si cette option est activée False, aucune flèche ne sera dessinée et, à la place, le registre classique et le bit utilisé par le measure seront indiqués à l'intérieur de la measure boîte. Cela permet measure d'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 fichier settings.conf. Sous la rubrique [Default] , un utilisateur peut saisir circuit_measure_arrows = False pour 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

Notes de mise à niveau de l'API C

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 utiliser version l'argument pour spécifier une version de format antérieure.

Notes de mise à jour sur les informations quantiques

Notes de mise à niveau de Synthesis

  • Les valeurs par défaut des arguments opt_a1 et opt_a2 de qs_decomposition() sont désormais opt_a1 = None et opt_a2 = None. Les nouveaux paramètres par défaut choisiront la valeur optimale en fonction du fait que l'unité d'entrée pour mat l'argument est contrôlée ou non afin d'obtenir le nombre CXGate minimal par défaut. Si vous souhaitez conserver le comportement précédent, vous pouvez appeler opt_a1 = True explicitement et opt_a2 = True pour conserver le même comportement que dans les versions précédentes.

Notes de mise à niveau du transpilateur

  • Le circuit PassManager définit désormais systématiquement les propriétés original_circuit_indices et num_input_qubits avant 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

Corrections des erreurs

  • ApplyLayout traitera désormais correctement le cas de l'application d'un qubit nul Layout. Auparavant, il affirmait qu'aucune mise en page n'avait été définie, même si le "layout" champ du PropertySet était égal à Layout().

  • Correction des problèmes de fuite de mémoire lors de la création d'une QkOpCounts instance 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 VF2Layout passage 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ù la callback fonction 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 CommutativeInverseCancellation passage du transcompilateur. Le passe-partout fonctionne désormais correctement sur les circuits contenant Clifford des opérations, des opérations de contrôle de flux et des opérations non inversibles telles que Initialize.

    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_based est fixé à True et que l'opération n'agit pas sur plus de max_qubits qubits, 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.

    Corrigé #14407, #14635, et #14645.

  • Correction de plusieurs problèmes dans le CommutativeCancellation passage du transcompilateur (et donc dans transpile()), 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 (2+4k)π(2 + 4k)\pi, kZk \in \mathbb Z a produit de manière incorrecte un déphasage de 1-1.

  • 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é par DAGCircuit.topological_nodes() ou topological_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é ouvert MCXGate ne tenait pas compte du ctrl_state de la porte MCX contrôlée, ce qui entraînait un incorrect ctrl_state de la porte MCX étendue. Notez que les classes MCX CXGateexplicites, CCXGate, C3XGate et C4XGate é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, PhaseOracleGate et BitFlipOracleGate où la tentative de chargement à partir d'un fichier dimacs provoquait une erreur TypeError.

  • Correction d'un bug dans le ElidePermutations passage du transcompilateur, où le mappage des qubits n'était pas mis à jour correctement en présence de PermutationGates, 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_layout proprié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 qui TranspileLayout.routing_permutation renvoie désormais une permutation correcte après avoir effectué plusieurs passages qui définissent final_layout.

    Cela n'a pas affecté les appels normaux à transpile() ou generate_preset_pass_manager() utilisant les plugins intégrés de Qiskit; aucun pipeline construit sous cette forme ne tenterait de définir final_layout plus d'une fois.

  • Correction d'un bug dans le HighLevelSynthesis pass 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 avec operation_name et parameters des arguments qui correspondaient à une instruction existante.

  • Correction du comportement de max_trials l'argument VF2Layout lorsqu'il est défini sur None ou 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 sur None et 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 que None effectuait 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 MCXSynthesis1DirtyKG24 haut niveau et MCXSynthesis2DirtyKG24 pour MCXGate, où les plugins ne considéraient pas les qubits auxiliaires propres disponibles comme des qubits auxiliaires sales disponibles. En particulier, le plugin MCXSynthesis2DirtyKG24 ne 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 exp(itH)\exp(-it H), où HH est le operator et tt est le time transmis à la porte. Cela corrige un comportement inattendu, car le PauliEvolutionGate est 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. La to_matrix mé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 QFT circuit. Auparavant, lorsque QFT.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 PauliEvolutionSynthesisRustiq plugin qui produisait des circuits incorrects dans le cas où l'opérateur d'un PauliEvolutionGate contenait des objets de type SparseObservable.

    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 un Target objet fourni lorsque backend l'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 à zero ne sont pas autorisés et invoquent désormais un échec gracieux.

  • qiskit.circuit.library.quantum_volume() a été mis à jour pour traiter un numpy.random.Generator comme entrée pour son seed argument. Auparavant, un tel argument générateur aurait donné lieu à un TypeError.

  • QuantumCircuit.compose() remapper correctement les variables et les segments utilisés dans Delay les instructions lorsque var_remap l'argument est spécifié.

  • SabreLayout utilise une disposition « sous-ensemble dense » comme l'un de ses essais, en suivant le même algorithme que DenseLayout. 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 :

    1. 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.
    2. 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 correctement filter_ancillas=True l'argument si les qubits virtuels dans le initial_layout n'ont pas été spécifiés par le constructeur dans l'ordre d'indexation.

  • VF2Layout et VF2PostLayout inclura 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 VF2PostLayout passage du transcompilateur. Dans certaines situations, lorsque le passage est exécuté avec l'argument, un problème potentiel de mise à strict_direction=True l'é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. En strict_direction=False mode, il existe une implémentation de recherche optimisée pour ces problèmes, mais les contraintes supplémentaires pour strict_direction=True rendent cette approche irréalisable. Dans ces cas-là, la recherche VF2PostLayout sera 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 SabreLayout et SabreSwap compresse 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 les lookahead composants 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.

    [1] https://devguide.python.org/versions/

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