Skip to main content
IBM Quantum Platform

Notes de publication de Qiskit 0.40


0.40.0

Cette version met officiellement fin au projet de fournisseur IBMQ de Qiskit, qui fait partie du métapackage Qiskit. Cela signifie que dans une prochaine version, pip install qiskit n'inclura plus automatiquement qiskit-ibmq-provider. Si vous installez ou listez actuellement qiskit comme une dépendance pour obtenir qiskit-ibmq-provider, vous devez mettre à jour pour inclure explicitement qiskit-ibmq-provider également. Cette démarche s'inscrit dans le cadre de l'évolution du projet Qiskit vers un modèle dans lequel le paquet qiskit ne contient que les fonctionnalités de base communes pour la construction et la compilation de circuits, de programmes et d'applications quantiques. Les paquets qui s'appuient sur ce noyau ou qui lient Qiskit à du matériel ou à des simulateurs seront installables en tant que paquets séparés.

Terra 0.23.0

Prélude

Qiskit Terra 0.23.0 est une version majeure qui inclut une multitude de nouvelles fonctionnalités et de corrections de bugs. Les points forts de cette version sont les suivants :

Cette version met également fin à la prise en charge de l'exécution avec Python 3.7. Un DeprecationWarning sera désormais émis si vous exécutez Qiskit avec Python 3.7. La prise en charge de Python 3.7 sera supprimée dans le cadre de la version 0.25.0 (actuellement prévue pour juillet 2023), et vous aurez alors besoin de Python 3.8 ou d'une version plus récente pour utiliser Qiskit.

Nouvelles fonctions

  • Les impulsions en qiskit.pulse.library

    peut être initialisé avec le nouveau paramètre angle, de sorte que deux paramètres flottants peuvent être fournis : amp et angle. L'initialisation à l'aide de amp complexes est toujours prise en charge.

  • La classe AdaptVQE possède un nouvel attribut, eigenvalue_historyqui est utilisé pour suivre l'énergie la plus basse atteinte par itération de AdaptVQE. Par exemple :

    from qiskit.algorithms.minimum_eigensolvers import VQE
    from qiskit.algorithms.minimum_eigensolvers.adapt_vqe import AdaptVQE
    from qiskit.algorithms.optimizers import SLSQP
    from qiskit.circuit.library import EvolvedOperatorAnsatz
    from qiskit.opflow import PauliSumOp
    from qiskit.primitives import Estimator
    from qiskit.quantum_info import SparsePauliOp
    from qiskit.utils import algorithm_globals
    
    excitation_pool = [
        PauliSumOp(
            SparsePauliOp(["IIIY", "IIZY"], coeffs=[0.5 + 0.0j, -0.5 + 0.0j]), coeff=1.0
        ),
        PauliSumOp(
            SparsePauliOp(["ZYII", "IYZI"], coeffs=[-0.5 + 0.0j, 0.5 + 0.0j]), coeff=1.0
        ),
        PauliSumOp(
            SparsePauliOp(
                ["ZXZY", "IXIY", "IYIX", "ZYZX", "IYZX", "ZYIX", "ZXIY", "IXZY"],
                coeffs=[
                    -0.125 + 0.0j,
                    0.125 + 0.0j,
                    -0.125 + 0.0j,
                    0.125 + 0.0j,
                    0.125 + 0.0j,
                    -0.125 + 0.0j,
                    0.125 + 0.0j,
                    -0.125 + 0.0j,
                ],
            ),
            coeff=1.0,
        ),
    ]
    ansatz = EvolvedOperatorAnsatz(excitation_pool, initial_state=self.initial_state)
    optimizer = SLSQP()
    h2_op = PauliSumOp.from_list(
        [
            ("IIII", -0.8105479805373266),
            ("ZZII", -0.2257534922240251),
            ("IIZI", +0.12091263261776641),
            ("ZIZI", +0.12091263261776641),
            ("IZZI", +0.17218393261915543),
            ("IIIZ", +0.17218393261915546),
            ("IZIZ", +0.1661454325638243),
            ("ZZIZ", +0.1661454325638243),
            ("IIZZ", -0.2257534922240251),
            ("IZZZ", +0.16892753870087926),
            ("ZZZZ", +0.17464343068300464),
            ("IXIX", +0.04523279994605788),
            ("ZXIX", +0.04523279994605788),
            ("IXZX", -0.04523279994605788),
            ("ZXZX", -0.04523279994605788),
        ]
    )
    
    algorithm_globals.random_seed = 42
    calc = AdaptVQE(VQE(Estimator(), ansatz, self.optimizer))
    res = calc.compute_minimum_eigenvalue(operator=h2_op)
    
    print(calc.eigenvalue_history)

    la valeur retournée de calc.history devrait être approximativement [-1.85727503] puisqu'il n'y a qu'une seule itération.

  • La journalisation de l'exécution lors de l'exécution de la fonction AdaptVQE a été améliorée. Lors de l'exécution de la classe, des messages de niveau DEBUG et INFO seront émis lors de l'exécution de la classe.

  • Ajout d'une nouvelle passe de transpilation, CollectAndCollapse, pour collecter et consolider les blocs de nœuds dans un circuit. Cette passe est conçue comme une classe de base générale pour la collecte et la consolidation de blocs combinés. Pour être tout à fait général, le travail de collecte et de regroupement des blocs est effectué par des fonctions fournies lors de l'instanciation de la passe. Par exemple, le CollectLinearFunctions a été mis à jour pour hériter de CollectAndCollapse et rassemble les blocs de CXGate et SwapGate et remplace chaque bloc par un LinearFunction. Le CollectCliffords qui est maintenant également basé sur CollectAndCollapse, rassemble des blocs de portes "Clifford" et remplace chaque bloc par une porte "Clifford" Clifford.

    L'interface prend également en charge l'option do_commutative_analysis, qui permet d'exploiter la commutativité entre les portes afin de collecter des blocs de nœuds plus importants. Par exemple, rassembler des blocs de portes CX dans le circuit suivant :

    qc = QuantumCircuit(2)
    qc.cx(0, 1)
    qc.z(0)
    qc.cx(1, 0)

    l'utilisation de do_commutative_analysis permet de consolider les deux portes CX, la première porte CX et la porte Z faisant la navette.

  • Ajout d'une nouvelle classe BlockCollector qui met en œuvre diverses stratégies de collecte, et d'une nouvelle classe BlockCollapser qui met en œuvre diverses stratégies de regroupement. Actuellement, BlockCollector comprend la stratégie consistant à collecter avec avidité toutes les portes adhérant à une fonction de filtrage donnée (par exemple, collecter toutes les portes de Clifford), et BlockCollapser comprend la stratégie consistant à consolider toutes les portes d'un bloc en un seul objet (par exemple, un bloc de portes de Clifford peut être consolidé en un seul objet Clifford).

  • Ajout d'une nouvelle passe de CollectCliffords qui collecte des blocs de portes de Clifford et les consolide en objets qiskit.quantum_info.Clifford objets. Cette passe hérite de CollectAndCollapse et supporte en particulier l'option do_commutative_analysis. Il prend également en charge deux options supplémentaires : split_blocks et min_block_size. Voir les notes de mise à jour pour CollectAndCollapse et CollectLinearFunctions pour plus de détails.

  • La passe CollectLinearFunctions transpiler pass a plusieurs nouveaux arguments dans son constructeur :

    • do_commutative_analysisl'utilisation de la commutativité entre les portes permet de collecter des blocs de nœuds plus importants.

    • split_blocksil permet de diviser les blocs collectés en sous-blocs sur des sous-ensembles disjoints de qubits. Par exemple, dans le circuit suivant :

      qc = QuantumCircuit(4)
      qc.cx(0, 2)
      qc.cx(1, 3)
      qc.cx(2, 0)
      qc.cx(3, 1)
      qc.cx(1, 3)

      le bloc unique de portes CX sur les qubits {0, 1, 2, 3} peut être divisé en deux sous-blocs disjoints, l'un sur les qubits {0, 2} et l'autre sur les qubits {1, 3}.

    • min_block_sizepermet de spécifier la taille minimale du bloc à consolider; les blocs comportant moins de portes ne seront pas modifiés. Par exemple, dans le circuit suivant :

      qc = QuantumCircuit(4)
      qc.cx(1, 2)
      qc.cx(2, 1)

      les deux portes CX seront consolidées lorsque min_block_size est 1 ou 2, et resteront inchangées lorsque min_block_size est 3 ou plus.

  • Ajout d'un algorithme de synthèse efficace en profondeur synth_cnot_depth_line_kms() pour les circuits linéaires réversibles LinearFunction sur l'architecture linéaire du plus proche voisin, conformément à l'article : https://arxiv.org/abs/quant-ph/0701194.

  • La méthode DAGCircuit.replace_block_with_op() renvoie désormais le nouveau DAGOpNode qui est créé lorsque le bloc est remplacé. Auparavant, l'appel à cette méthode ne renvoyait rien.

  • Ajout d'un algorithme de synthèse efficace en profondeur synth_permutation_depth_lnn_kms() pour Permutation par rapport à l'architecture linéaire du plus proche voisin, conformément à l'article : https://arxiv.org/abs/quant-ph/0701194

  • Ajout d'une nouvelle classe PermutationGate pour représenter la logique de permutation en tant qu'élément de circuit. Contrairement à l'élément de bibliothèque Permutation qui avait une définition statique, cette nouvelle classe évite de synthétiser un circuit de permutation lorsqu'elle est déclarée. Cela retarde la synthèse proprement dite au niveau du transpondeur. Il permet également d'utiliser plusieurs algorithmes différents pour synthétiser les permutations, qui sont disponibles en tant que plugins de permutation de synthèse de haut niveau.

    Une autre caractéristique clé du PermutationGate est qu'il implémente l'interface __array__ pour retourner efficacement une matrice unitaire pour une permutation.

  • Ajout de plusieurs plugins de synthèse de haut niveau pour la synthèse de permutations :

    • BasicSynthesisPermutationil s'applique aux architectures entièrement connectées et est basé sur le tri. Il s'agit de l'algorithme précédemment utilisé pour construire des circuits quantiques pour les permutations.
    • ACGSynthesisPermutationil s'applique aux architectures entièrement connectées mais est basé sur la méthode Alon, Chung, Graham. Il synthétise n'importe quelle permutation en profondeur 2 (mesurée en termes de SWAP).
    • KMSSynthesisPermutationla méthode Kutin, Moulton, Smithline, récemment ajoutée, s'applique aux architectures linéaires à plus proche voisin et correspond à la méthode Kutin, Moulton, Smithline.

    Par exemple :

    from qiskit.circuit import QuantumCircuit
    from qiskit.circuit.library import PermutationGate
    from qiskit.transpiler import PassManager
    from qiskit.transpiler.passes.synthesis.high_level_synthesis import HLSConfig, HighLevelSynthesis
    from qiskit.transpiler.passes.synthesis.plugin import HighLevelSynthesisPluginManager
    
    # Create a permutation and add it to a quantum circuit
    perm = PermutationGate([4, 6, 3, 7, 1, 2, 0, 5])
    qc = QuantumCircuit(8)
    qc.append(perm, range(8))
    
    # Print available plugin names for synthesizing permutations
    # Returns ['acg', 'basic', 'default', 'kms']
    print(HighLevelSynthesisPluginManager().method_names("permutation"))
    
    # Default plugin for permutations
    # Returns a quantum circuit with size 6 and depth 3
    qct = PassManager(HighLevelSynthesis()).run(qc)
    print(f"Default: {qct.size() = }, {qct.depth() = }")
    
    # KMSSynthesisPermutation plugin for permutations
    # Returns a quantum circuit with size 18 and depth 6
    # but adhering to the linear nearest-neighbor architecture.
    qct = PassManager(HighLevelSynthesis(HLSConfig(permutation=[("kms", {})]))).run(qc)
    print(f"kms: {qct.size() = }, {qct.depth() = }")
    
    # BasicSynthesisPermutation plugin for permutations
    # Returns a quantum circuit with size 6 and depth 3
    qct = PassManager(HighLevelSynthesis(HLSConfig(permutation=[("basic", {})]))).run(qc)
    print(f"basic: {qct.size() = }, {qct.depth() = }")
    
    # ACGSynthesisPermutation plugin for permutations
    # Returns a quantum circuit with size 6 and depth 2
    qct = PassManager(HighLevelSynthesis(HLSConfig(permutation=[("acg", {})]))).run(qc)
    print(f"acg: {qct.size() = }, {qct.depth() = }")
  • Ajout de nouvelles classes pour les algorithmes Quantum Fisher Information (QFI) et Quantum Geometric Tensor (QGT) à l'aide de primitives, qiskit.algorithms.gradients.QFI et qiskit.algorithms.gradients.LinCombQGTau module de gradients : qiskit.algorithms.gradients. Par exemple :

    from qiskit.circuit import QuantumCircuit, Parameter
    from qiskit.algorithms.gradients import LinCombQGT, QFI
    
    estimator = Estimator()
    a, b = Parameter("a"), Parameter("b")
    qc = QuantumCircuit(1)
    qc.h(0)
    qc.rz(a, 0)
    qc.rx(b, 0)
    
    parameter_value = [[np.pi / 4, 0]]
    
    qgt = LinCombQGT(estimator)
    qgt_result = qgt.run([qc], parameter_value).result()
    
    qfi = QFI(qgt)
    qfi_result = qfi.run([qc], parameter_value).result()
  • Ajout d'un nouveau mot-clé, derivative_type, dans le constructeur de la classe LinCombEstimatorGradient. Cet argument prend une énumération DerivativeType qui permet de spécifier de calculer uniquement les parties réelles ou imaginaires du gradient.

  • Ajout d'une nouvelle option circuit_reverse_bits au fichier de configuration de l'utilisateur. Cela permet aux utilisateurs de définir un booléen pour le comportement par défaut qu'ils préfèrent pour l'argument reverse_bits des tiroirs de circuits QuantumCircuit.draw() et circuit_drawer(). Par exemple, l'ajout d'une section au fichier de configuration de l'utilisateur dans l'emplacement par défaut ~/.qiskit/settings.conf avec :

    [default]
    circuit_reverse_bits = True

    modifiera la valeur par défaut pour afficher les bits dans l'ordre inverse.

  • Ajout d'une nouvelle classe Z2Symmetries to qiskit.quantum_info qui est utilisée pour identifier les symétries Z2Z_2 à partir d'une entrée SparsePauliOp.

  • Ajout d'une nouvelle directive pulse TimeBlockade. Cette directive a un comportement presque identique à celui de l'instruction delay, mais elle sera supprimée avant l'exécution. Cette directive est destinée à être utilisée en interne par le constructeur d'impulsions et permet de représenter des instructions avec des intervalles de temps absolus ScheduleBlock de représenter des instructions avec des intervalles de temps absolus. Cela permet au constructeur d'impulsions de convertir Schedule en ScheduleBlock, plutôt que de l'envelopper d'instructions Call instructions.

  • Ajout d'algorithmes compatibles avec les primitives pour l'évolution variationnelle du temps quantique qui implémentent l'interface de l'évolution du temps quantique. La classe qiskit.algorithms.VarQRTE est utilisée pour l'évolution du temps quantique réel et la classe qiskit.algorithms.VarQITE est utilisée pour l'évolution du temps quantique imaginaire selon un principe variationnel passé.

    Chaque algorithme accepte un principe variationnel qui met en œuvre l'interface abstraite ImaginaryVariationalPrinciple interface abstraite. Les implémentations suivantes sont incluses :

    Par exemple :

    from qiskit.algorithms import TimeEvolutionProblem, VarQITE
    from qiskit.algorithms.time_evolvers.variational import ImaginaryMcLachlanPrinciple
    from qiskit.circuit.library import EfficientSU2
    from qiskit.quantum_info import SparsePauliOp
    import numpy as np
    
    observable = SparsePauliOp.from_list(
        [
            ("II", 0.2252),
            ("ZZ", 0.5716),
            ("IZ", 0.3435),
            ("ZI", -0.4347),
            ("YY", 0.091),
            ("XX", 0.091),
        ]
    )
    
    ansatz = EfficientSU2(observable.num_qubits, reps=1)
    init_param_values = np.zeros(len(ansatz.parameters))
    for i in range(len(ansatz.parameters)):
        init_param_values[i] = np.pi / 2
    var_principle = ImaginaryMcLachlanPrinciple()
    time = 1
    evolution_problem = TimeEvolutionProblem(observable, time)
    var_qite = VarQITE(ansatz, var_principle, init_param_values)
    evolution_result = var_qite.evolve(evolution_problem)
  • Ajout de règles pour la conversion des XXPlusYYGate et XXMinusYYGate vers d'autres portes du site SessionEquivalenceLibrary. Cela permet d'exécuter transpile() ciblant un backend ou Target qui utilise ces portes.

  • Ajout de deux nouveaux faux backends, FakePrague et FakeSherbrooke au module qiskit.providers.fake_provider module. FakePrague fournit un backend avec un instantané des propriétés du backend IBM Prague Egret R1 et FakeSherbrooke fournit un backend avec un instantané des propriétés du backend IBM Aigle de Sherbrooke R3.

  • Ajout d'un nouveau mot-clé, allow_unknown_parameters, à l'option ParameterExpression.bind() et ParameterExpression.subs() aux méthodes. Lorsqu'il est défini, ce nouvel argument permet de passer un dictionnaire contenant des paramètres inconnus à ces méthodes sans provoquer d'erreur. Auparavant, cela entraînait toujours une erreur sans qu'il soit possible de désactiver ce comportement.

  • L'argument de la méthode BaseEstimator.run() l'argument observables de la méthode accepte désormais un type d'entrée str ou une séquence de str en plus des autres types déjà acceptés. Lorsqu'il est utilisé, le format de la chaîne d'entrée doit correspondre à la représentation de la chaîne de Pauli acceptée par le constructeur des objets Pauli des objets.

  • Ajout d'une nouvelle méthode de construction QuantumCircuit.from_instructions() qui permet de créer un objet QuantumCircuit à partir d'une table itérative d'instructions. Par exemple :

    from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
    from qiskit.circuit.quantumcircuitdata import CircuitInstruction
    from qiskit.circuit import Measure
    from qiskit.circuit.library import HGate, CXGate
    
    
    qr = QuantumRegister(2)
    cr = ClassicalRegister(2)
    instructions = [
        CircuitInstruction(HGate(), [qr[0]], []),
        CircuitInstruction(CXGate(), [qr[0], qr[1]], []),
        CircuitInstruction(Measure(), [qr[0]], [cr[0]]),
        CircuitInstruction(Measure(), [qr[1]], [cr[1]]),
    ]
    circuit = QuantumCircuit.from_instructions(instructions)
    circuit.draw("mpl")
    _images/legacy_release_notes-3.png
  • La classe Clifford prend désormais un argument optionnel copy dans son constructeur. S'il est défini sur False, un StabilizerTable fourni en entrée ne sera pas copié, mais utilisé directement. Cela peut présenter des avantages en termes de performances, si les données du tableau ne sont jamais modifiées par d'autres moyens.

  • Les performances de Clifford.compose() a été grandement améliorée pour tous les nombres de qubits. Pour les opérateurs de 20 qubits, l'accélération est de l'ordre de 100 fois.

  • Ajout d'une nouvelle fonction de synthèse synth_clifford_layers()pour synthétiser un Clifford en couches. L'algorithme est basé sur S. Bravyi, D. Maslov, Les circuits sans Hadamard exposent la structure du groupe de Clifford, arxiv:2003.09412. Cela permet de décomposer le Clifford en 8 couches de portes, dont deux couches de portes CZ et une couche de portes CX. Par exemple, un circuit de Clifford à 5 qubits est décomposé dans les couches suivantes :

         ┌─────┐┌─────┐┌────────┐┌─────┐┌─────┐┌─────┐┌─────┐┌────────┐
    q_0:0    ├┤0    ├┤0       ├┤0    ├┤0    ├┤0    ├┤0    ├┤0
         │     ││     ││        ││     ││     ││     ││     ││        │
    q_1:1    ├┤1    ├┤1       ├┤1    ├┤1    ├┤1    ├┤1    ├┤1
         │     ││     ││        ││     ││     ││     ││     ││        │
    q_2:2 S2 ├┤2 CZ ├┤2 CX_dg ├┤2 H2 ├┤2 S1 ├┤2 CZ ├┤2 H1 ├┤2 Pauli ├
         │     ││     ││        ││     ││     ││     ││     ││        │
    q_3:3    ├┤3    ├┤3       ├┤3    ├┤3    ├┤3    ├┤3    ├┤3
         │     ││     ││        ││     ││     ││     ││     ││        │
    q_4:4    ├┤4    ├┤4       ├┤4    ├┤4    ├┤4    ├┤4    ├┤4
         └─────┘└─────┘└────────┘└─────┘└─────┘└─────┘└─────┘└────────┘

    Cette méthode permettra de décomposer un Clifford en profondeur de 2 qubits 7n+27n+2 pour la connectivité du plus proche voisin linéaire (LNN).

  • Les types de retour des méthodes power() de plusieurs classes de portes de la bibliothèque standard ont été mis à jour pour renvoyer des objets de portes plus spécifiques, ce qui permet d'obtenir un résultat plus efficace et avec moins de pertes. Par exemple, l'exécution de power() renvoie désormais une instance IGate au lieu de UnitaryGate comme c'était le cas auparavant.

    La liste complète des types de sortie qui ont été améliorés est la suivante :

  • Le EquivalenceLibrary est désormais représenté en interne sous la forme d'un PyDiGraph, cet objet graphique sous-jacent est accessible à partir du nouvel attribut graph attribut. Cet attribut est destiné à une utilisation interne dans Qiskit et doit donc toujours être copié avant d'être modifié par l'utilisateur afin d'éviter une éventuelle corruption du graphe d'équivalence interne.

  • La méthode du constructeur Operator.from_circuit() va maintenant inverser la permutation de sortie causée par l'étape de routage/mise en correspondance du transpileur. Par défaut, si des portes Swap ont été insérées dans un circuit transpilé, la matrice de sortie aura cette permutation inversée, de sorte que la matrice renvoyée sera équivalente au circuit original non transpilé. Si vous souhaitez désactiver ce comportement par défaut, l'argument du mot-clé ignore_set_layout peut être défini à True pour le faire (en plus du comportement précédent consistant à ignorer la disposition initiale de la transpilation). Si vous souhaitez définir manuellement une disposition finale, vous pouvez utiliser le nouveau mot-clé final_layout pour transmettre un objet Layout à utiliser pour la permutation de sortie.

  • Ajout d'un support à la passe GateDirection pour gérer la passe de transpilation symétrique RXXGate, RYYGate, et RZZGate symétriques. La passe traitera maintenant correctement ces portes et inversera simplement l'ordre des qargs en place sans aucune autre modification.

  • L'utilisation de l'opérateur d'exponentiation Python, **, avec les objets est désormais prise en charge Gate est désormais pris en charge. Cela équivaut à exécuter la méthode Gate.power() sur l'objet.

    Par exemple :

    from qiskit.circuit.library import XGate
    
    sx = XGate() ** 0.5
  • Ajout d'une nouvelle forme d'impulsion GaussianSquareDrag au module qiskit.pulse.library module. Cette forme d'impulsion est similaire à GaussianSquare mais utilise la forme Drag pendant sa montée et sa descente. La correction de la forme de l'impulsion DRAG peut supprimer une partie du spectre de fréquence de la montée et de la descente de l'impulsion, ce qui permet d'éviter d'exciter les qubits spectateurs lorsque leur fréquence est proche de la fréquence d'entraînement de l'impulsion.

  • Ajout d'un nouveau mot-clé, method, dans les constructeurs pour les FiniteDiffEstimatorGradient et FiniteDiffSamplerGradient . L'argument method accepte une chaîne de caractères indiquant la méthode de calcul à utiliser pour le gradient. Trois méthodes sont disponibles : "central", "forward", et "backward". Les définitions des méthodes sont les suivantes :

    Méthode
    Calcul
    "central"f(x+e)f(xe)2e\frac{f(x+e)-f(x-e)}{2e}
    "forward"f(x+e)f(x)e\frac{f(x+e) - f(x)}{e}
    "backward"f(x)f(xe)e\frac{f(x)-f(x-e)}{e}

    ee est l'epsilon du décalage.

  • Toutes les classes de gradient dans qiskit.algorithms.gradients préservent désormais les opérations non paramétrées au lieu d'essayer de les dérouler. Cela permet d'évaluer les gradients sur des portes personnalisées et opaques que les primitives individuelles peuvent gérer et de conserver un niveau d'abstraction plus élevé pour une synthèse et une compilation optimisées après la construction des circuits de gradient.

  • Ajout d'une TranslateParameterizedGates pour faire correspondre uniquement les portes paramétrées d'un circuit à une base spécifiée, sans toucher aux portes non paramétrées. La passe tente d'abord de dérouler et traduit finalement si une porte paramétrée ne peut pas être déroulée davantage.

  • Le passage du transpondeur CollectCliffords la passe de transposition a été étendue pour collecter et combiner des blocs de "portes de clifford" en objets Clifford où les "portes de clifford" peuvent maintenant aussi inclure des objets de type LinearFunction, Clifford, et PauliGate. Par exemple :

    from qiskit.circuit import QuantumCircuit
    from qiskit.circuit.library import LinearFunction, PauliGate
    from qiskit.quantum_info.operators import Clifford
    from qiskit.transpiler.passes import CollectCliffords
    from qiskit.transpiler import PassManager
    
    # Create a Clifford
    cliff_circuit = QuantumCircuit(2)
    cliff_circuit.cx(0, 1)
    cliff_circuit.h(0)
    cliff = Clifford(cliff_circuit)
    
    # Create a linear function
    lf = LinearFunction([[0, 1], [1, 0]])
    
    # Create a pauli gate
    pauli_gate = PauliGate("XYZ")
    
    # Create a quantum circuit with the above and also simple clifford gates.
    qc = QuantumCircuit(4)
    qc.cz(0, 1)
    qc.append(cliff, [0, 1])
    qc.h(0)
    qc.append(lf, [0, 2])
    qc.append(pauli_gate, [0, 2, 1])
    qc.x(2)
    
    # Run CollectCliffords transpiler pass
    qct = PassManager(CollectCliffords()).run(qc)

    Toutes les portes seront rassemblées et combinées en une seule Clifford. Le circuit final est donc constitué d'un seul objet Clifford objet.

  • CouplingMap est maintenant implicitement itérable, l'itération étant identique à l'itération sur la sortie de CouplingMap.get_edges(). En d'autres termes,

    from qiskit.transpiler import CouplingMap
    coupling = CouplingMap.from_line(3)
    list(coupling) == list(coupling.get_edges())

    fonctionnera désormais comme prévu, de même que les autres itérations. Il s'agit d'une simple commodité syntaxique.

  • Ajout d'une nouvelle fonction synth_cnot_count_full_pmh() qui est utilisée pour synthétiser des circuits linéaires réversibles pour des architectures "all-to-all" en utilisant les méthodes de Patel, Markov et Hayes. Cette fonction est identique à la fonction qiskit.transpiler.synthesis.cnot_synth() disponible, mais elle porte un nom plus descriptif et est placée plus logiquement dans l'arborescence du paquet. Cette nouvelle fonction remplace l'ancienne fonction qui sera probablement supprimée dans une prochaine version.

  • InstructionScheduleMap a été mis à jour pour stocker les données d'étalonnage du backend dans le format PulseQobj JSON et invoque la conversion lorsque les données sont consultées pour la première fois, c'est-à-dire une conversion paresseuse. Cette mise à jour de la logique interne améliore considérablement les performances du chargement du backend, en particulier avec de nombreuses entrées d'étalonnage.

  • Le nouveau module qiskit.pulse.calibration_entries a été ajouté. Il contient plusieurs classes d'enveloppe pour différentes représentations de l'horaire des impulsions.

    • ScheduleDef
    • CallableDef
    • PulseQobjDef

    Ces classes mettent en œuvre les méthodes get_schedule() et get_signature() qui renvoient respectivement le calendrier des impulsions et les noms des paramètres à affecter. Ces classes sont gérées en interne par le système InstructionScheduleMap ou le backend Targetet n'apparaissent donc pas dans un programme utilisateur typique.

  • Introduction d'une nouvelle sous-classe ScalableSymbolicPulse, en tant que sous-classe de SymbolicPulse. La nouvelle sous-classe se comporte de la même manière que SymbolicPulsesauf qu'elle suppose que l'enveloppe de l'impulsion comprend un pré-facteur d'amplitude complexe de la forme ampei×angle\text{amp} * e^{i \times \text{angle}}. Cette forme d'enveloppe correspond à de nombreuses impulsions courantes, y compris toutes les impulsions de la bibliothèque Qiskit Pulse (qui ont également été converties en représentation amp, angle dans cette version).

    La nouvelle sous-classe supprime la nature non unique de la représentation amp, angle et compare correctement les impulsions en fonction de leur amplitude complexe.

  • Ajout d'un nouveau mot-clé, dtype, à la méthode PauliSumOp.from_list() méthode. Lorsqu'il est spécifié, cet argument peut être utilisé pour spécifier l'adresse dtype du tableau numpy alloué pour l'objet de la construction SparsePauliOp utilisé en interne par l'algorithme construit PauliSumOp.

  • La prise en charge de l'importation des programmes OpenQASM 3 dans Qiskit a été ajoutée. On peut y accéder plus facilement en utilisant les fonctions qasm3.loads() et qasm3.load()pour charger un programme directement à partir d'une chaîne de caractères et indirectement à partir d'un nom de fichier, respectivement. Par exemple, on peut maintenant faire :

    from qiskit import qasm3
    
    circuit = qasm3.loads("""
      OPENQASM 3.0;
      include "stdgates.inc";
    
      qubit q;
      qubit[5] qr;
      bit c;
      bit[5] cr;
    
      h q;
      c = measure q;
    
      if (c) {
        h qr[0];
        cx qr[0], qr[1];
        cx qr[0], qr[2];
        cx qr[0], qr[3];
        cx qr[0], qr[4];
      } else {
        h qr[4];
        cx qr[4], qr[3];
        cx qr[4], qr[2];
        cx qr[4], qr[1];
        cx qr[4], qr[0];
      }
      cr = measure qr;
    """)

    Cela chargera le programme dans une instance QuantumCircuit dans la variable circuit.

    Toutes les fonctionnalités de OpenQASM 3 ne sont pas prises en charge dans un premier temps, car Qiskit ne dispose pas encore d'un moyen de représenter le traitement classique avancé des données. Les capacités de l'importateur augmenteront en même temps que celles du reste de Qiskit. L'ensemble initial de caractéristiques de l'importateur est approximativement le même ensemble de caractéristiques que celui qui serait produit par l'exportateur (qasm3.dump() et qasm3.dumps()).

    Notez que la prise en charge de OpenQASM 3 par Qiskit n'a pas pour but de fournir une représentation totalement sans perte de QuantumCircuits. Pour cela, envisagez d'utiliser qiskit.qpy.

  • Les classes de gradient primitives-définies par les classes de gradient basées sur les BaseEstimatorGradient et BaseSamplerGradient ont été mises à jour pour simplifier l'extension de l'interface de base. Il y a trois nouvelles méthodes internes qui peuvent être remplacées, _preprocess(), _postprocess(), et _run_unique(). _preprocess() permet à une sous-classe de personnaliser les circuits et les paramètres du gradient d'entrée, _postprocess permet de personnaliser le résultat de sortie, et _run_unique permet de calculer le gradient d'un circuit avec des paramètres uniques.

  • La passe de SabreLayout est beaucoup plus performant car il a été réécrit en Rust. Dans le cadre de cette réécriture, la passe a été transformée d'une passe d'analyse en une passe de transformation qui exécutera à la fois la mise en page et le routage. Cela a été fait non seulement pour améliorer les performances d'exécution, mais aussi pour améliorer la qualité des résultats. La fonctionnalité précédente de la passe en tant que passe d'analyse peut être conservée en définissant manuellement l'argument routing_pass ou en utilisant le nouvel argument skip_routing .

  • La passe SabreLayout a un nouvel argument de construction layout_trials. Cet argument est utilisé pour contrôler le nombre de graines du générateur de nombres aléatoires que l'on essaiera d'utiliser SabreLayout avec. Lorsque cette option est activée, l'algorithme de mise en page SABRE est exécuté layout_trials un certain nombre de fois et la meilleure qualité de sortie (mesurée par le plus petit nombre de portes de permutation ajoutées) est sélectionnée. Ces essais de semences sont exécutés en parallèle en utilisant le multithreading afin de minimiser les surcharges de performance potentielles liées à l'exécution de la mise en page plusieurs fois. Par défaut, si ce paramètre n'est pas spécifié, le SabreLayout utilisera par défaut le nombre de CPU physiques disponibles sur le système local.

  • Ajout de deux nouvelles classes SciPyRealEvolver et SciPyImaginaryEvolver qui mettent en œuvre des méthodes d'intégration pour l'évolution temporelle d'un état quantique. La valeur et l'écart-type des observables ainsi que les moments auxquels ils sont évalués peuvent être interrogés comme suit TimeEvolutionResult.observables et TimeEvolutionResult.times. Par exemple :

    from qiskit.algorithms.time_evolvers.time_evolution_problem import TimeEvolutionProblem
    from qiskit.quantum_info import SparsePauliOp
    from qiskit.quantum_info.states.statevector import Statevector
    from qiskit.algorithms import SciPyImaginaryEvolver
    
    initial_state = Statevector.from_label("+++++")
    hamiltonian = SparsePauliOp("ZZZZZ")
    evolution_problem = TimeEvolutionProblem(hamiltonian, 100, initial_state, {"Energy":hamiltonian})
    classic_evolver = SciPyImaginaryEvolver(num_timesteps=300)
    result = classic_evolver.evolve(evolution_problem)
    print(result.observables)
  • Ajout de la passe SolovayKitaev pour exécuter l'algorithme Solovay-Kitaev pour l'approximation des unitaires d'un seul qubit en utilisant un ensemble de portes discrètes. En combinaison avec le traducteur de base, cela permet de convertir n'importe quel circuit unitaire en un ensemble de portes discrètes universelles, qui pourrait être mis en œuvre de manière tolérante aux pannes.

    Cette passe peut par exemple être utilisée après la compilation vers les portes U et CX :

    from qiskit import transpile
    from qiskit.circuit.library import QFT
    from qiskit.transpiler.passes.synthesis import SolovayKitaev
    
    qft = QFT(3)
    
    # optimize to general 1-qubit unitaries and CX
    transpiled = transpile(qft, basis_gates=["u", "cx"], optimization_level=1)
    
    skd = SolovayKitaev()  # uses T Tdg and H as default basis
    discretized = skd(transpiled)
    
    print(discretized.count_ops())

    La décomposition peut également être utilisée avec le plugin de synthèse unitaire, comme la méthode "sk" sur la passe de UnitarySynthesis transpiler pass :

    from qiskit import QuantumCircuit
    from qiskit.quantum_info import Operator
    from qiskit.transpiler.passes import UnitarySynthesis
    
    circuit = QuantumCircuit(1)
    circuit.rx(0.8, 0)
    unitary = Operator(circuit).data
    
    unitary_circ = QuantumCircuit(1)
    unitary_circ.unitary(unitary, [0])
    
    synth = UnitarySynthesis(basis_gates=["h", "s"], method="sk")
    out = synth(unitary_circ)
    
    out.draw('mpl')
    _images/legacy_release_notes-4.png
  • La génération de circuits aléatoires avec qiskit.circuit.random.random_circuit() est désormais nettement plus rapide pour les circuits de grande taille.

  • La génération de circuits aléatoires avec qiskit.circuit.random.random_circuit() produira désormais toutes les portes "standard" de la bibliothèque de circuits de Qiskit (qiskit.circuit.library). Cela inclut deux portes à 4 qubits C3SXGate et RC3XGateet les valeurs autorisées de max_operands ont été étendues en conséquence.

  • La passe Optimize1qGatesDecomposition transpiler pass a un nouvel argument de mot-clé, target, dans son constructeur. Cet argument peut être utilisé pour spécifier un objet Target qui représente la cible de la compilation. S'il est utilisé, il supplante l'argument basis pour déterminer si une instruction du circuit est présente sur le backend cible.

  • La passe UnrollCustomDefinitions transpiler pass a un nouvel argument de mot-clé, target, dans son constructeur. Cet argument peut être utilisé pour spécifier un objet Target qui représente la cible de la compilation. S'il est utilisé, il supplante l'argument basis_gates pour déterminer si une instruction du circuit est présente sur le backend cible.

  • Ajout de la classe ReverseEstimatorGradient pour une évaluation classique et rapide des gradients de la valeur d'espérance basée sur la rétropropagation ou les gradients en mode inverse. Cette classe utilise des vecteurs d'état et fournit donc des gradients exacts, mais elle s'étend de manière exponentielle à la taille du système. Il est conçu pour un calcul de référence rapide des systèmes de petite taille. Il peut par exemple être utilisé comme :

    from qiskit.circuit.library import EfficientSU2
    from qiskit.quantum_info import SparsePauliOp
    from qiskit.algorithms.gradients import ReverseEstimatorGradient
    
    observable = SparsePauliOp.from_sparse_list([("ZZ", [0, 1], 1)], num_qubits=10)
    circuit = EfficientSU2(num_qubits=10)
    values = [i / 100 for i in range(circuit.num_parameters)]
    gradient = ReverseEstimatorGradient()
    
    result = gradient.run([circuit], [observable], [values]).result()
  • Ajout d'un nouveau mot-clé argument, use_dag au constructeur de la OneQubitEulerDecomposer classe. Lorsque use_dag est défini sur True , le résultat du décomposeur sera un objet DAGCircuit au lieu de QuantumCircuit objet. Ceci est utile pour les passes de transpilation qui utilisent OneQubitEulerDecomposer (comme Optimize1qGatesDecomposition), car le fait de travailler directement avec un DAGCircuit évite le surcoût de la conversion entre QuantumCircuit et DAGCircuit.

  • Ajout de la possibilité pour les passes d'analyse de définir des pondérations heuristiques personnalisées pour les variables VF2Layout et VF2PostLayout pour les passes de transpilation. Si une passe d'analyse définit la clé vf2_avg_error_map dans l'ensemble de propriétés, sa valeur est utilisée pour les pondérations d'erreur au lieu des taux d'erreur provenant de l'ensemble de propriétés du backend Target (ou BackendProperties pour BackendV1). La valeur doit être une instance ErrorMap , où chaque valeur représente le taux d'erreur moyen pour toutes les opérations à 1 ou 2 qubits sur ces qubits. Si une valeur est NaN, l'arête correspondante est traitée comme une arête idéale (ou un qubit pour les opérations 1q ). Par exemple, une carte des erreurs créée comme suit :

    from qiskit.transpiler.passes.layout.vf2_utils import ErrorMap
    
    error_map = ErrorMap(3)
    error_map.add_error((0, 0), 0.0024)
    error_map.add_error((0, 1), 0.01)
    error_map.add_error((1, 1), 0.0032)

    décrit une cible à 2 qubits, où le taux d'erreur moyen de 1q est de 0.0024 sur le qubit 0 et de 0.0032 sur le qubit 1, le taux d'erreur moyen de 2q pour les portes qui opèrent sur (0, 1) est de 0.01, et (1, 0) n'est pas pris en charge par la cible. Elle sera utilisée pour la notation si elle est définie pour la clé vf2_avg_error_map dans l'ensemble des propriétés lorsque VF2Layout et VF2PostLayout sont exécutés. Par exemple :

    from qiskit.transpiler import AnalysisPass, PassManager, Target
    from qiskit.transpiler.passes import VF2Layout
    from qiskit.transpiler.passes.layout.vf2_utils import ErrorMap
    from qiskit.circuit.library import CZGate, UGate
    from qiskit.circuit import Parameter
    
    class CustomVF2Scoring(AnalysisPass):
      """Set custom score for vf2."""
    
      def run(self, dag):
        error_map = ErrorMap(3)
        error_map.add_error((0, 0), 0.0024)
        error_map.add_error((0, 1), 0.01)
        error_map.add_error((1, 1), 0.0032)
        self.property_set["vf2_avg_error_map"] = error_map
    
    
    target = Target(num_qubits=2)
    target.add_instruction(
        UGate(Parameter('theta'), Parameter('phi'), Parameter('lam')),
        {(0,): None, (1,): None}
    )
    target.add_instruction(
        CZGate(), {(0, 1): None}
    )
    
    vf2_pass = VF2Layout(target=target, seed=1234568942)
    pm = PassManager([CustomVF2Scoring(), vf2_pass])

    Cela fonctionnera VF2Layout avec la notation personnalisée de error_map pour un qubit 2 Target qui ne contient pas de taux d'erreur.

Mise à niveau

  • Lors de l'initialisation de l'une des classes d'impulsions dans qiskit.pulse.library:

    fournir un argument complexe amp avec une angle finie résultera en PulseError maintenant. Par exemple, au lieu d'appeler Gaussian(duration=100,sigma=20,amp=0.5j) , il faut maintenant utiliser Gaussian(duration=100,sigma=20,amp=0.5,angle=np.pi/2) . L'enveloppe d'impulsion qui était définie comme amp * ... est à son tour définie comme amp * exp(1j * angle) * .... Cette modification a été apportée pour mieux prendre en charge les expériences Qiskit dans lesquelles l'amplitude et l'angle des impulsions sont calibrés dans des expériences distinctes.

  • Pour Python 3.7 singledispatchmethod est maintenant une dépendance. Cela a été ajouté pour permettre de tirer parti du mécanisme de répartition des méthodes dans la bibliothèque standard des versions plus récentes de Python. Si vous êtes sur Python >= 3.8, aucune dépendance supplémentaire n'est nécessaire.

  • La passe de transpilation MSBasisDecomposer disponible via le module qiskit.transpiler.passes a été supprimée. Il a été déprécié à l'origine dans le cadre de la version de Qiskit Terra 0.16.0 (10-16-2020). Au lieu de cela, la passe BasisTranslator doit être utilisé pour traduire un circuit en une base appropriée avec un RXXGate

  • EquivalenceLibrary qui sont initialisés avec l'attribut base n'auront plus de référence partagée avec l'objet EquivalenceLibrary passé dans l'attribut. Dans les versions précédentes, si vous modifiez base après qu'il a été utilisé pour créer une nouvelle instance, les deux instances refléteront ce changement EquivalenceLibrary les deux instances reflétaient ce changement. Ce n'est plus le cas et les mises à jour de base ne seront plus reflétées dans le nouveau fichier EquivalenceLibrary. Par exemple, si vous avez créé une bibliothèque d'équivalence avec :

    import math
    
    from qiskit.circuit import QuantumCircuit
    from qiskit.circuit.library import XGate
    from qiskit.circuit.equivalence import EquivalenceLibrary
    
    original_lib = EquivalenceLibrary()
    qc = QuantumCircuit(1)
    qc.rx(math.pi, 0)
    original_lib.add_equivalence(XGate(), qc)
    new_lib = EquivalenceLibrary(base=original_lib)

    si vous avez modifié original_lib avec :

    import from qiskit.circuit.library import SXGate
    
    qc = QuantumCircuit(1)
    qc.rx(math.pi / 2, 0)
    original_lib.add_equivalence(SXGate(), qc)

    dans les versions précédentes, new_lib incluait également la définition de SXGate après qu'elle ait été ajoutée à original_lib, mais ce n'est plus le cas dans cette version. Ce changement a été effectué en raison de la modification de la structure interne des données, qui est devenue un graphique, ce qui a permis d'améliorer les performances de la classe, en particulier lorsqu'il y a plusieurs exécutions EquivalenceLibrary performance de la classe, en particulier lorsqu'il y a plusieurs exécutions de la passe de BasisTranslator transpiler.

  • L'argument initial_state du constructeur de la classe NLocal ainsi que l'assignation directe à l'attribut NLocal.initial_state doit être un QuantumCircuit maintenant. L'utilisation d'autres types pour cet argument et cet attribut n'est plus prise en charge. La prise en charge d'autres types a été supprimée lors de la publication de Qiskit Terra 0.18.0 (juillet 2021).

  • Les tiroirs du tableau LaTeX (par exemple array_to_latex, Statevector.draw('latex')) utilisent désormais la même fonction sympy que le tiroir de la convention ket. Cela signifie que certains chiffres peuvent être rendus différemment par rapport aux versions précédentes, mais que l'expérience sera plus cohérente. Par exemple, il peut identifier de nouveaux facteurs ou rationaliser les dénominateurs là où il ne le faisait pas auparavant. La valeur par défaut de precision a été modifiée de 5 à 10.

  • La version du format QPY émise par dump() est passé à la version 6. Cette nouvelle version du format est incompatible avec les versions précédentes et provoquera une erreur si l'on essaie de la charger avec un désérialiseur qui n'est pas capable de gérer la version 6 de QPY. Cette modification était nécessaire pour prendre en charge l'introduction de ScalableSymbolicPulse , qui a été gérée en ajoutant un attribut class_name_size à l'en-tête des objets vidés SymbolicPulse vidés.

  • La méthode __hash__ pour le SymbolicPulse a été supprimée. Ceci a été fait pour refléter la nature mutable (via l'assignation de paramètres) de cette classe qui pouvait entraîner des erreurs lors de l'utilisation de SymbolicPulse dans des situations où un objet hachable était nécessaire. Cela signifie que la méthode intégrée hash() et l'utilisation de SymbolicPulse comme clés dans les dictionnaires ou les membres d'un ensemble ne fonctionneront plus.

  • Les noms des Register (ce qui inclut les instances de QuantumRegister et ClassicalRegigster) ne sont plus contraints d'être des identifiants OpenQASM 2 valides. Cette mesure est prise car la restriction est trop stricte à mesure que Qiskit se découple de OpenQASM 2, et même la spécification de OpenQASM 3 n'est pas aussi restrictive. Si vous comptiez sur le fait que les registres aient des noms d'identificateurs valides OpenQASM 2, vous devrez commencer à échapper les noms. Une version simpliste de cette méthode pourrait être réalisée, par exemple, par :

    import re
    import string
    
    def escape(name: str) -> str:
      out = re.sub(r"\W", "_", name, flags=re.ASCII)
      if not out or out[0] not in string.ascii_lowercase:
        return "reg_" + out
      return out
  • Les méthodes QuantumCircuitu1 , u2, u3, et leurs variantes contrôlées cu1, cu3 et mcu1 ont été supprimées suite à leur dépréciation dans Qiskit Terra 0.16.0. Il s'agissait de supprimer les noms de portes qui étaient généralement spécifiques à IBM, en faveur de méthodes plus générales p(), u(), cp() et cu(). Les classes de portes U1Gate, U2Gate et U3Gate sont toujours disponibles pour être utilisées avec QuantumCircuit.append()les backends peuvent donc toujours prendre en charge les bases pour lesquelles ces portes sont explicitement indiquées.

  • Les méthodes QuantumCircuit les méthodes combine et extend ont été supprimées suite à leur dépréciation dans Qiskit Terra 0.17.0. Cela s'explique par le fait que ces fonctions sont simplement des versions moins puissantes de QuantumCircuit.compose()qui devraient être utilisées à la place.

    La suppression de extend signifie également que les opérateurs + et += ne sont plus définis pour QuantumCircuit. Au lieu de cela, vous pouvez utiliser les opérateurs & et &= , qui utilisent respectivement QuantumCircuit.compose().

  • Les fonctions précédemment obsolètes : qiskit.circuit.measure.measure() et qiskit.circuit.reset.reset() ont été supprimées. Ces fonctions ont été supprimées dans la version de Qiskit Terra 0.19.0 (décembre 2021). Au lieu de cela, vous devez utiliser les boutons QuantumCircuit.measure() et QuantumCircuit.reset() de l'objet QuantumCircuit que vous souhaitez ajouter un Measure ou Reset à une opération.

  • Les méthodes ParameterView précédemment dépréciées et héritées de set ont été supprimées de ParameterView, le type retourné par QuantumCircuit.parameters. Les méthodes spécifiques qui ont été supprimées sont les suivantes

    • add()
    • difference()
    • difference_update()
    • discard()
    • intersection()
    • intersection_update()
    • issubset()
    • issuperset()
    • symmetric_difference()
    • symmetric_difference_update()
    • union()
    • update()

    ainsi qu'un soutien aux opérateurs Python :

    • ixor: ^=
    • isub: -=
    • ior: |=

    Ils ont été supprimés dans la version de Qiskit Terra 0.17.0 (avril 2021). Le type ParameterView est désormais un type de vue de séquence générale et ne prend plus en charge ces opérations set .

  • Les méthodes de conversion NetworkX précédemment obsolètes pour les méthodes de conversion DAGCircuit et DAGDependency ont été supprimées : DAGCircuit.to_networkx(), DAGCircuit.from_networkx(), et DAGDependency.to_networkx() ont été supprimées. Ces méthodes ont été initialement dépréciées dans le cadre de la version de Qiskit Terra 0.21.0 (juin 2022). Qiskit utilise rustworkx comme bibliothèque de graphes depuis la version qiskit-terra 0.12.0 et depuis lors, la fonction de conversion NetworkX est un processus avec perte. Ils ont été ajoutés à l'origine pour permettre aux utilisateurs d'exploiter la bibliothèque d'algorithmes NetworkX’s afin de tirer parti de fonctionnalités qui ne sont pas présentes dans DAGCircuit et/ou rustworkx. Cependant, depuis lors, tant DAGCircuit et rustworkx ont mûri et offrent davantage de fonctionnalités, et la méthode DAGCircuit est étroitement lié à rustworkx pour son fonctionnement et ces méthodes de conversion n'offraient qu'une fonctionnalité limitée et ont donc été supprimées.

  • tweedledum a été supprimée en tant qu'exigence fondamentale de Qiskit Terra. La fonctionnalité fournie (qiskit.circuit.classicalfunction) est toujours disponible si tweedledum est installé manuellement, par exemple par :

    pip install tweedledum

    Ce changement a été effectué parce que le développement de tweedledum a ralenti au point de ne plus suivre les nouvelles versions de Python et du système d'exploitation, ce qui empêchait certains utilisateurs de Qiskit d'installer Qiskit.

  • Les vérificateurs optionnels paresseux HAS_MATPLOTLIB, HAS_PIL, HAS_PYLATEX et HAS_PDFTOCAIRO ne sont plus exposés à partir de qiskit.visualizationayant été dépréciés dans Qiskit Terra 0.21. L'emplacement canonique de ces vérificateurs (et de nombreux autres vérificateurs paresseux) est le suivant qiskit.utils.optionalset les quatre objets peuvent y être trouvés.

  • L'argument gate du constructeur de la passe de transposition, précédemment déprécié, ainsi que l'attribut correspondant ont été supprimés Decompose ainsi que l'attribut correspondant Decompose.gate ont été supprimés. L'argument et l'attribut ont été dépréciés dans le cadre de la version de Qiskit Terra 0.19.0 (décembre 2021). Au lieu de cela, il convient d'utiliser l'argument gates_to_decompose pour le constructeur ainsi que l'attribut Decompose.gates_to_decompose . L'argument et l'attribut gates_to_decompose devraient fonctionner de la même manière, mais ils portent un nom plus explicite et permettent également de spécifier des listes de portes au lieu de ne prendre en charge qu'une seule porte.

  • L'argument label , précédemment obsolète, pour le constructeur de l'élément MCMT et MCMTVChain a été supprimé. Il a été supprimé à partir de la version de Qiskit Terra 0.19.0 (décembre 2021). L'utilisation de l'argument label sur ces classes était un comportement non défini car elles sont des sous-classes de QuantumCircuit au lieu de Instruction. Dans ce cas, l'étiquette attribuée est généralement ignorée. Si vous devez attribuer une adresse label à une instance de MCMT ou MCMTVChain vous devez les convertir en une instance de Gate avec to_gate() puis attribuer l'étiquette souhaitée à l'attribut label attribut. Par exemple :

    from qiskit.circuit.library import MCMT, XGate
    
    mcmt_circuit = MCMT(XGate(), 3, 2)
    mcmt_gate = mcmt_circuit.to_gate()
    mcmt_gate.label = "Custom MCMT X"
  • La dépendance retworkx pour Qiskit a été supprimée et remplacée par la bibliothèque rustworkx . Il s'agit des mêmes paquets, mais rustworkx est le nouveau nom de retworkx qui a été renommé dans le cadre de la publication combinée de 0.12.0. Si vous utilisiez précédemment retworkx 0.12.0 avec Qiskit, alors vous avez déjà installé rustworkx (retworkx 0.12.0 était juste un shim de redirection pour la compatibilité ascendante). Ce changement a été effectué pour migrer vers le nouveau nom du paquet qui sera le seul paquet pris en charge à l'avenir.

  • Le comportement par défaut de la passe du compilateur SabreLayout a changé. La passe n'est plus un AnalysisPass et, par défaut, calculera la disposition initiale, l'appliquera au circuit, et exécutera également la commande SabreSwap en interne et appliquera le mappage de permutation et définira le jeu de propriétés final_layout avec la permutation causée par les insertions de permutation. Cela signifie que pour les utilisateurs qui utilisent SabreLayout dans le cadre d'un PassManager devront ajuster le gestionnaire de passe pour en tenir compte (à moins qu'ils n'aient défini l'argument routing_pass pour SabreLayout). Ce changement a été effectué dans le but d'améliorer la qualité des résultats, la qualité de l'agencement et du routage étant fortement liée et la qualité de l'agencement et du routage étant fortement liée SabreLayout pour calculer quelle semence fournit les meilleurs résultats, il faut effectuer à la fois l'agencement et le routage. Vous pouvez ajuster l'utilisation de votre gestionnaire de laissez-passer personnalisé de trois manières différentes. La première consiste à éviter d'utiliser l'intégration dans votre gestionnaire de presets. Si vous utilisiez auparavant quelque chose comme :

    from qiskit.transpiler import PassManager
    from qiskit.transpiler.preset_passmanagers import common
    from qiskit.transpiler.passes.SabreLayout
    
    pm = PassManager()
    pm.append(SabreLayout(coupling_map)
    pm += common.generate_embed_passmanager(coupling_map)

    pour calculer la disposition et l'appliquer (ce qui était généralement suivi par le routage), vous pouvez ajuster l'utilisation pour qu'elle soit tout simplement :

    from qiskit.transpiler import PassManager
    from qiskit.transpiler.preset_passmanagers import common
    from qiskit.transpiler.passes.SabreLayout
    
    pm = PassManager()
    pm.append(SabreLayout(coupling_map)

    comme SabreLayout appliquera la mise en page et vous n'aurez plus besoin de l'étape d'intégration. Vous pouvez également spécifier l'argument routing_pass , qui ramènera le système à son comportement précédent SabreLayout à son comportement précédent. Par exemple, si vous voulez exécuter SabreLayout tel qu'il était exécuté dans les versions précédentes, vous pouvez faire quelque chose comme :

    from qiskit.transpiler.passes import SabreSwap, SabreLayout
    routing_pass = SabreSwap(
        coupling_map, "decay", seed=seed, fake_run=True
    )
    layout_pass = SabreLayout(coupling_map, routing_pass=routing_pass, seed=seed)

    qui aura SabreLayout s'exécutera comme une passe d'analyse et définira simplement l'ensemble de propriétés layout . La dernière approche consiste à utiliser l'argument skip_routing sur SabreLayout, lorsque cet argument est défini sur True , il n'est pas nécessaire d'appliquer la disposition trouvée et d'insérer les portes de permutation du routage. Cependant, cela entraîne une pénalité en termes de temps d'exécution, car SabreLayout calcule toujours le routage et n'utilise pas ces données. Les deux premières approches décrites n'entraînent pas de frais généraux supplémentaires.

  • Les tracés calculés par la passe SabreLayout (lorsqu'il est exécuté sans l'argument routing_pass ) avec une valeur de départ fixe peuvent changer par rapport aux versions précédentes. Cela est dû à l'utilisation d'un nouveau générateur de nombres aléatoires dans le cadre de la réécriture de la passe SabreLayout en Rust, ce qui a considérablement amélioré les performances. Si vous avez besoin d'une sortie cohérente, vous pouvez exécuter la passe dans une version antérieure de Qiskit et utiliser l'outil qiskit.qpy pour sauvegarder le circuit et le charger ensuite avec la version actuelle. Vous pouvez également définir explicitement l'argument routing_pass comme une instance de SabreSwap pour refléter le comportement précédent de SabreLayout:

    from qiskit.transpiler.passes import SabreSwap, SabreLayout
    
    
    routing_pass = SabreSwap(
        coupling_map, "decay", seed=seed, fake_run=True
    )
    layout_pass = SabreLayout(coupling_map, routing_pass=routing_pass, seed=seed)

    qui reflètera le comportement de la passe dans la version précédente. Notez que si vous utilisiez l'argument swap_trials sur SabreLayout dans les versions précédentes lors de l'adaptation de l'utilisation à cette forme, vous devrez définir l'argument trials sur le constructeur SabreSwap si vous souhaitez conserver la sortie précédente avec une graine fixe.

  • Le circuit exact renvoyé par qiskit.circuit.random.random_circuit pour une graine donnée a changé. Ceci est dû à l'amélioration de l'efficacité de la génération interne de nombres aléatoires pour la fonction.

  • La version requise pour le paquet de fonctionnalités optionnelles qiskit-toqm, installable via pip install qiskit-terra[toqm], a été mise à jour de la version 0.0.4 à 0.1.0. Pour utiliser la méthode de routage toqm avec transpile() vous devez maintenant utiliser qiskit-toqm version 0.1.0 ou plus récente. Les versions antérieures ne peuvent plus être découvertes par le transpondeur.

  • La sortie QuasiDistribution de la méthode Sampler.run a été mise à jour pour filtrer tous les états dont la probabilité est nulle. Si un état valide est absent de la sortie du dictionnaire, on peut supposer qu'il a une probabilité de 0. Auparavant, tous les résultats possibles pour un nombre donné de bits (par exemple, pour un résultat de 3 bits 000, 001, 010, 011, 100, 101, 110, et 111) même si la probabilité d'un état donné était de 0. Cette modification a été apportée pour réduire la taille de la sortie, car pour un grand nombre de bits, la taille de la sortie pouvait être très importante. En outre, le filtrage des résultats à probabilité nulle rend la sortie cohérente avec d'autres implémentations de BaseSampler.

  • Le comportement du constructeur d'impulsions lorsqu'un Schedule a été amélioré. Les calendriers appelés sont convertis en interne en ScheduleBlock et le mécanisme de référence est toujours appliqué au lieu d'ajouter les programmes enveloppés par l'instruction Call . Il convient de noter que le bloc converti ne récupère pas nécessairement le contexte d'alignement d'origine. Il s'agit simplement d'une séquence d'instructions d'impulsions alignées ASAP avec des intervalles de temps absolus. Il s'agit d'une mise à jour de la représentation interne des programmes d'impulsion appelés, et donc d'aucune modification de l'API. Toutefois, les Call instruction et Schedule ne figurent plus dans le programme d'impulsion du constructeur. Cette modification garantit que les blocs de programmation générés sont toujours compatibles avec le QPY. Si vous filtrez les instructions du calendrier de sortie par Callvous pouvez accéder à l'élément ScheduleBlock.references pour récupérer le programme appelé.

  • RZXCalibrationBuilder et RZXCalibrationBuilderNoEcho ont été mis à jour pour générer des fichiers ScheduleBlock. Cette modification garantit que les circuits transposés sont toujours compatibles avec le QPY. Si vous utilisez directement la méthode rescale_cr_inst()à partir d'un autre programme ou d'une sous-classe de passe pour réévaluer l'impulsion de résonance croisée de l'appareil, cette méthode est maintenant transformée en macro de construction d'impulsion, et vous devez utiliser cette méthode dans le contexte de la construction d'impulsion pour adopter la nouvelle version. L'appel de méthode injecte une instruction de lecture dans le programme d'impulsion contextuel, au lieu de renvoyer une instruction de lecture avec l'impulsion étirée Play avec l'impulsion étirée.

Remarques concernant la dépréciation

  • Le support pour l'exécution de Qiskit avec Python 3.7 a été déprécié et sera supprimé dans la version qiskit-terra 0.25.0. Cela signifie qu'à partir de la version 0.25.0, vous devrez mettre à jour la version Python que vous utilisez vers Python 3.8 ou une version supérieure.

  • La classe LinearFunctionsSynthesis est désormais obsolète et sera supprimée dans une prochaine version. Elle a été remplacée par la classe plus générale HighLevelSynthesis plus générale, qu'il convient d'utiliser à la place. Par exemple, vous pouvez créer une instance de HighLevelSynthesis qui se comportera de la même manière que LinearFunctionSynthesis with :

    from qiskit.transpiler.passes import HighLevelSynthesis
    from qiskit.transpiler.passes.synthesis.high_level_synthesis import HLSConfig
    
    HighLevelSynthesis(
        HLSConfig(
            linear_function=[("default", {})],
            use_default_on_unspecified=False,
        )
    )
  • La prise en charge du passage de listes de valeurs d'arguments à la fonction transpile() est obsolète et sera supprimée dans la version 0.25.0. Cela permet de réduire considérablement les frais généraux liés à l'exécution parallèle pour la transposition de plusieurs circuits à la fois. Si vous utilisez cette fonctionnalité actuellement, vous pouvez appeler transpile() plusieurs fois. Par exemple, si vous faisiez auparavant quelque chose comme.. :

    from qiskit.transpiler import CouplingMap
    from qiskit import QuantumCircuit
    from qiskit import transpile
    
    qc = QuantumCircuit(2)
    qc.h(0)
    qc.cx(0, 1)
    qc.measure_all()
    cmaps = [CouplingMap.from_heavy_hex(d) for d in range(3, 15, 2)]
    results = transpile([qc] * 6, coupling_map=cmaps)

    au lieu de cela, vous devriez exécuter quelque chose comme :

    from itertools import cycle
    from qiskit.transpiler import CouplingMap
    from qiskit import QuantumCircuit
    from qiskit import transpile
    
    qc = QuantumCircuit(2)
    qc.h(0)
    qc.cx(0, 1)
    qc.measure_all()
    cmaps = [CouplingMap.from_heavy_hex(d) for d in range(3, 15, 2)]
    
    results = []
    for qc, cmap in zip(cycle([qc]), cmaps):
        results.append(transpile(qc, coupling_map=cmap))

    Vous pouvez également utiliser parallel_map() ou multiprocessing de la bibliothèque standard Python si vous souhaitez exécuter cette opération en parallèle.

  • L'ancienne version du tiroir à impulsions présente sur le site qiskit.visualization.pulse est obsolète et sera supprimée dans une prochaine version. Il s'agit notamment des classes ScheduleDrawer et :class`WaveformDrawer`. Ce module a été remplacé par le tiroir qiskit.visualization.pulse_v2 et l'API utilisateur typique pulse_drawer() et PulseBlock.draw() ont déjà été mis à jour en interne pour utiliser qiskit.visualization.pulse_v2.

  • La méthode pulse.Instruction.draw() est obsolète et sera supprimée dans une prochaine version. La nécessité de cette méthode a été remplacée par le tiroir qiskit.visualization.pulse_v2 qui n'exige pas que les objets Instrucion aient leur propre méthode de dessin. Si vous avez besoin de dessiner une instruction d'impulsion, vous devriez plutôt utiliser la fonction pulse_drawer() à la place.

  • L'importation qiskit.circuit.qpy_serialization est obsolète, car QPY a été promu au niveau supérieur. Vous devez importer les mêmes objets à partir de qiskit.qpy au lieu de cela. L'ancien chemin sera supprimé dans un futur Qiskit Terra.

  • L'objet qiskit.IBMQ est obsolète. Cet objet alias redirige paresseusement l'accès aux attributs vers qiskit.providers.ibmq.IBMQ. Comme le paquet qiskit-ibmq-provider a été remplacé par le paquet qiskit-ibm-provider qui a son propre espace de noms, le maintien de cet alias n'est plus pertinent avec le nouveau paquet. Si vous utilisiez l'alias qiskit.IBMQ , vous devez mettre à jour votre utilisation pour utiliser directement qiskit.providers.ibmq.IBMQ (et envisager de migrer vers qiskit-ibm-provider, voir le guide de migration pour plus de détails).

  • Plusieurs méthodes publiques des convertisseurs pulse Qobj ont été dépréciées et ne pourront plus être appelées directement dans une prochaine version. La liste des méthodes est la suivante :

    Sur InstructionToQobjConverter,

    • convert_acquire()
    • convert_bundled_acquires()
    • convert_set_frequency()
    • convert_shift_frequency()
    • convert_set_phase()
    • convert_shift_phase()
    • convert_delay()
    • convert_play()
    • convert_snapshot()

    Sur QobjToInstructionConverter,

    • convert_acquire()
    • convert_set_phase()
    • convert_shift_phase()
    • convert_set_frequency()
    • convert_shift_frequency()
    • convert_delay()
    • bind_pulse()
    • convert_parametric()
    • convert_snapshot()

    Au lieu d'appeler directement l'une de ces méthodes, elles seront implicitement sélectionnées lorsqu'une instance de convertisseur est appelée directement. Par exemple :

    converter = QobjToInstructionConverter()
    converter(pulse_qobj)
  • Les fonctions qiskit.visualization.state_visualization.num_to_latex_ket() et qiskit.visualization.state_visualization.num_to_latex_terms() sont obsolètes et seront supprimées dans une prochaine version. Ces fonctions étaient principalement utilisées en interne par la sortie LaTeX de Statevector.draw() et DensityMatrix.draw() qui n'utilise plus ces fonctions et s'appuie sur sympy à la place. Si vous utilisiez ces fonctions, vous devriez plutôt utiliser les fonctions nsimplify() latex() de Sympy.

  • La méthode Register.qasm() est obsolète et sera supprimée dans une prochaine version. Cette méthode se retrouve dans les sous-classes QuantumRegister et ClassicalRegister. La dépréciation est due au fait que la méthode qasm() promeut une vision erronée de la partie responsable de la conversion sûre vers OpenQASM 2; un objet seul n'a pas le contexte nécessaire pour fournir une conversion sûre, par exemple si son nom est incompatible après l'avoir échappé pour produire un identificateur valide.

  • L'expression régulière classe-variable Register.name_format est obsolète et sera supprimée dans une prochaine version. Les noms des registres peuvent désormais être n'importe quelle chaîne valide Python, de sorte que l'expression régulière n'a plus d'utilité.

  • Les fonctions qiskit.quantum_info.synthesis.decompose_clifford() et qiskit.quantum_info.synthesis.decompose_cnot_dihedral() sont obsolètes et seront supprimées dans une prochaine version. Elles sont remplacées par les deux fonctions qiskit.synthesis.synth_clifford_full() et qiskit.synthesis.synth_cnotdihedral_full() respectivement.

Corrections des erreurs

  • Correction d'un problème dans la méthode PauliOp.adjoint() qui renvoyait la bonne valeur pour les Paulis à coefficients complexes, par exemple : PauliOp(Pauli("iX")). Correction #9433.

  • Correction d'un problème avec les algorithmes d'estimation d'amplitude dans le module qiskit.algorithms.amplitude_estimators (voir amplitude_estimators) pour l'utilisation de primitives construites à partir de la primitive abstraite BaseSampler (telles que Sampler et BackendSampler). Auparavant, les résultats des mesures étaient étendus à plus de bits que ceux réellement mesurés, ce qui, pour les oracles comportant plus d'un qubit, entraînait des erreurs potentielles dans la détection des "bons" états quantiques des oracles.

  • Correction d'un problème où les méthodes QuantumCircuit.add_calibrations() et DAGCircuit.add_calibrations() avaient un comportement différent dans la logique de formatage des paramètres. Auparavant, DAGCircuit.add_calibrations() essayait d'intégrer chaque paramètre dans float, QuantumCircuit.add_calibrations() utilisait les paramètres donnés tels quels. Cela pourrait provoquer une erreur lors de l'exécution du programme transpile() sur un QuantumCircuit avec des portes à impulsion, car les paramètres des calibrations pourraient être conservés en tant qu'objets ParameterExpresion .

  • Correction d'un problème de désérialisation dans les fichiers (qiskit.qpy) load() de QPY où les circuits contenant des portes de classe MCXGate, MCXGrayCode, MCXRecursive,, et MCXVChain ne parviendraient pas à se désérialiser. Correction #9390.

  • Correction d'un problème dans TensoredOp.to_matrix() où le coefficient global de l'opérateur était multiplié à la matrice finale plus d'une fois. Désormais, le coefficient global est correctement appliqué, indépendamment du nombre d'opérateurs ou d'états tensoriés. Correction #9398.

  • Le résultat de la méthode run() de la classe BackendSampler définit maintenant les attributs shots et stddev_upper_bound de l'objet retourné QuasiDistribution. Auparavant, ces attributs étaient absents, ce qui empêchait tout post-traitement des résultats. Corrigé #9311

  • La méthode de l'exportateur OpenQASM 2 QuantumCircuit.qasm() émettra désormais par défaut des nombres en virgule flottante de plus haute précision pour les paramètres de la porte. En outre, une limite plus stricte ( 1e121e-12 au lieu de 1e61e-6 ) est utilisée pour vérifier si un paramètre donné est proche d'une fraction/puissance de π\pi. Correction #7166.

  • Correction de la prise en charge dans le module primitives pour l'exécution d'objets QuantumCircuit avec des instructions de flux de contrôle (par ex. IfElseOp). Auparavant, les classes de base BaseSampler et BaseEstimator ne pouvaient pas normaliser correctement de tels circuits. Toutefois, l'exécution de ces circuits dépend de la mise en œuvre particulière des instructions primitives de flux de contrôle. Il s'agit simplement d'un support fixe permettant à une implémentation particulière de BaseSampler ou BaseEstimator d'utiliser des instructions de flux de contrôle.

  • Correction d'un problème avec la méthode PauliOp.matmul() qui renvoyait des résultats incorrects avec iI. Correction #8680.

  • Correction d'un problème avec la classe Approximate Quantum Compiler (AQC) qui lui faisait renvoyer un circuit incorrect lorsque l'unité d'entrée avait un déterminant de -1. Corrigé #9327

  • Correction d'un problème avec la méthode QuantumCircuit.compose() qui rejetait incorrectement les spécificateurs qubit ou clbit valides. Cette erreur a été corrigée de sorte que la méthode accepte désormais le même ensemble de spécificateurs qubit et clbit que d'autres méthodes telles que QuantumCircuit telles que append(). Correction #8691.

  • Correction d'un problème avec la méthode QuantumCircuit.compose() qui faisait correspondre de manière incorrecte les registres dans les conditions du circuit donné avec les registres complets de la base. Auparavant, le mappage était très imprécis; les bits utilisés dans chaque condition n'étaient pas soumis au mappage, et une tentative imprécise était faite pour trouver un registre correspondant. Cela pourrait également entraîner l'extension d'une condition sur un registre plus petit à un registre plus grand, ce qui n'est pas une transformation valide. Désormais, une condition portant sur un seul bit ou un registre sera composée de manière à porter précisément sur les bits définis par l'argument clbits . Un nouveau registre d'aliasing sera ajouté au circuit de base pour faciliter cette opération, si nécessaire. Correction #6583.

  • Correction d'un problème avec la fonction transpile() lorsqu'elle est exécutée avec optimization_level ayant pour valeur 1, 2, ou 3 et qu'aucun argument backend, basis_gates, ou target n'est spécifié. Si le circuit d'entrée comportait des séries de portes à qubit unique pouvant être simplifiées, le circuit de sortie ne serait pas aussi optimisé que possible, car ces séries de portes à qubit unique n'auraient pas été supprimées. Cela aurait pu être corrigé précédemment en spécifiant les arguments backend, basis_gates, ou target lors de l'appel de la fonction transpile() mais maintenant la sortie sera aussi simplifiée qu'elle peut l'être sans connaître les portes cibles autorisées. Corrigé #9217

  • Correction d'un problème avec la fonction transpile() lorsqu'elle est exécutée avec optimization_level=3 et qu'aucun argument backend, basis_gates ou target n'est spécifié. Si le circuit d'entrée contenait des blocs de 2 qubits équivalents à une matrice d'identité, le circuit de sortie ne serait pas aussi optimisé que possible et contiendrait toujours ce bloc d'identité. Cela aurait pu être corrigé précédemment en spécifiant les arguments backend, basis_gates, ou target lors de l'appel de la fonction transpile() mais maintenant la sortie sera aussi simplifiée qu'elle peut l'être sans connaître les portes cibles autorisées. Corrigé #9217

  • Correction d'un problème avec LinCombSamplerGradient qui pouvait soulever une erreur lorsqu'il était exécuté avec la classe Sampler de qiskit-aer.

  • Correction d'un problème avec NumPyEigensolver et par extension NumPyMinimumEigensolver où la résolution des sous-classes de BaseOperator autres que Operator provoquait une erreur.

  • Correction d'un problème dans la sortie des métadonnées de primitives où la liste faisait des copies par référence et où tous les éléments étaient mis à jour avec la même valeur à chaque itération.

  • Correction d'un problème avec QobjToInstructionConverter lorsque plusieurs backends sont appelés et qu'ils ont accidentellement le même nom de pulse dans la bibliothèque de pulse. Il s'agissait d'un cas particulier qui ne pouvait se produire que lorsqu'une instance de convertisseur était réutilisée par plusieurs backends (ce qui n'était pas un schéma d'utilisation typique).

  • Correction d'un problème avec la classe PVQD où la fonction de perte élevait de manière incorrecte la fidélité au carré. Cette erreur a été corrigée afin que la fonction de perte corresponde à la définition de l'algorithme original.

  • Correction d'un bogue dans QPY (qiskit.qpy) où les circuits contenant des registres dont les bits se trouvaient dans le circuit après les bits libres ne parvenaient pas à se désérialiser. Voir #9094.

  • La classe TwoQubitWeylDecomposition est désormais compatible avec le protocole pickle . Auparavant, la désérialisation échouait et soulevait un problème TypeError. Voir #7312.

  • Correction d'un problème avec la méthode LocalReadoutMitigator.quasi_probabilities() où l'argument shots n'était pas utilisé. Il est maintenant utilisé pour définir le nombre de tirs dans l'objet de renvoi.

  • Correction d'une régression dans la construction d'objets Clifford objets à partir de QuantumCircuits qui contiennent d'autres Clifford objets.

  • Correction d'un problème avec la classe TwoQubitWeylDecomposition (et ses sous-classes) pour permettre à la bibliothèque standard Python pickle de sérialiser ces classes. Ceci corrige partiellement #7312

  • QuantumCircuit.qasm() échappe désormais correctement les noms de portes et de registres qui entrent en conflit avec les mots-clés réservés de OpenQASM 2. Corrige #5043.

  • Correction d'un problème dans le RZXCalibrationBuilder où la séquence d'impulsions ECR était mal alignée. Correction #9013.

  • Correction d'un problème avec la fonction pulse_drawer() où, dans certains cas, la visualisation de sortie omettait certains canaux d'une programmation. Correction #8981.

Aer 0.11.2

Pas de modification

IBM 0.19.2 du fournisseur Q

Pas de modification

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