Skip to main content
IBM Quantum Platform

Qiskit SDK 1.1 notes de mise à jour


1.1.2

Prélude

Qiskit 1.1.2 est une version mineure de correction de bugs pour la série 1.1.

Corrections des erreurs

  • Correction d'un bug dans BitArray.from_counts() et BitArray.from_samples(). Jusqu'à présent, ces fonctions soulevaient une erreur si les données fournies ne contenaient que des zéros et aucune valeur pour l'argument facultatif num_bits. Aujourd'hui, ils produisent un BitArray avec la valeur BitArray.num_bits dont la valeur est fixée à 1.

  • Correction d'un décorateur manquant dans C3SXGate qui le faisait échouer si Gate.to_matrix() était appelé. La matrice de la porte est maintenant retournée comme prévu.

  • Ajout des portes de Clifford manquantes à la passe de CollectCliffords transpiler pass. En particulier, nous avons ajouté les portes ECRGate, DCXGate, iSWAPGate, SXGate et SXdgGate à cette passe de transpileur.

  • L'attribut QuantumCircuit.parameters sera désormais correctement vide lors de l'utilisation de QuantumCircuit.copy_empty_like() sur un circuit paramétrique. Auparavant, un cache interne était copié sans être invalidé. Correction #12617.

  • Correction de la passe de SolovayKitaev lors du chargement des approximations de base à partir d'un fichier .npy existant. Auparavant, le chargement d'une approximation stockée qui permettait des réductions supplémentaires (par exemple, en raison d'annulations de portes) pouvait entraîner un échec de l'exécution. En outre, la différence de phase globale du produit de porte U(2) et de la représentation SO(3) a été perdue au cours d'une procédure de sauvegarde et de rechargement. Corrections Qiskit/qiskit#12576.

  • Correction d'un problème avec dag_drawer() et DAGCircuit.draw() lors de la visualisation d'une instance DAGCircuit contenant des Var fils. Le visualiseur soulevait une exception en essayant de le faire, ce qui a été corrigé afin que la visualisation attendue soit générée.

  • Le constructeur GenericBackendV2 permettait auparavant de construire des backends malformés parce qu'il acceptait des portes de base qui ne pouvaient pas être allouées compte tenu de la taille du backend. Par exemple, un backend avec un seul qubit pouvait auparavant accepter une base avec des portes à deux qubits.

  • L'analyseur OpenQASM 2 (qiskit.qasm2) peut maintenant gérer les conditionnelles avec des entiers qui ne tiennent pas dans un entier de 64 bits. Correction #12773.

  • Précédemment, DAGCircuit.replace_block_with_op() permettait de placer une opération n-qubit sur un bloc de m qubits, laissant le DAG dans un état invalide. Ce comportement a été corrigé, et toute tentative de faire cela lèvera désormais un DAGCircuitError comme prévu.


1.1.1

Prélude

Qiskit 1.1.1 est une version mineure de correction de bugs pour la série 1.1.

Corrections des erreurs

  • Correction d'un bogue dans Isometry dû à une assertion inutile, qui conduisait à une erreur dans UnitaryGate.control() lorsque UnitaryGate avait plus de deux qubits.

  • QuantumCircuit.depth() traitera désormais correctement les opérations qui n'ont pas d'opérandes, telles que GlobalPhaseGate.

  • QuantumCircuit.depth() comptera désormais les variables et les clbits utilisés dans les expressions en temps réel dans le cadre du calcul de la profondeur.

  • Correction d'un bogue dans qiskit.visualization.pulse_v2.interface.draw() qui ne dessinait pas les horaires de pouls lorsque la fonction de dessin était appelée avec un argument BackendV2 en argument. Comme le backend V2 ne signale pas les fréquences des canaux matériels, le dessin généré indiquera "no freq" (pas de fréquence) sous l'étiquette de chaque canal.

  • La passe VF2Layout lèverait une exception si on lui fournissait une instance Target sans contraintes de connectivité. Ce serait le cas pour les cibles d'Aer 0.13. Le problème est maintenant corrigé.

  • ParameterExpression a été mis à jour de manière à ce que les instances entièrement liées qui se comparent à des instances des types numériques intégrés de Python (comme float et int) aient également des valeurs de hachage qui correspondent à celles des autres instances. Cette modification garantit que ces types peuvent être utilisés de manière interchangeable comme clés de dictionnaire. Voir #12488.

  • Les portes personnalisées (celles qui découlent d'une déclaration gate ) dans les programmes importés de OpenQASM 2 auront désormais une Gate.to_matrix() mise en œuvre. Auparavant, ils n'avaient pas de définition matricielle, ce qui signifie que les allers-retours sur le site OpenQASM 2 pouvaient perdre inutilement la possibilité de dériver la matrice de la porte. Notez cependant que la matrice est calculée en trouvant récursivement les matrices des définitions des portes internes, comme le fait Operator ce qui peut être moins performant qu'avant l'aller-retour.

  • Target.has_calibration() a été mis à jour afin qu'il ne soulève pas d'exception pour une instruction qui a été ajoutée à la cible avec None pour ses propriétés d'instruction. Corrige #12525.


1.1.0

Prélude

La version de Qiskit 1.1.0 est une version mineure qui inclut une myriade de nouvelles fonctionnalités et de corrections de bugs. Les points forts de cette version sont les suivants :

  • La prise en charge des variables classiques typées a été ajoutée à l'interface de Qiskit QuantumCircuit. Ces variables classiques peuvent être spécifiées en tant qu'entrées ou variables de portée dans un système d'information QuantumCircuit où elles stockent, par exemple, la sortie des mesures de qubits ou des opérations de flux de contrôle ciblées. La prise en charge, par exemple, de la définition des paramètres de la porte ou des variables de sortie sera ajoutée à l'avenir.

  • Les méthodes de synthèse de deux qubits par défaut qui sont utilisées en interne par le transpileur dans la passe UnitarySynthesis ont été réimplémentées en Rust. Cela permet d'accélérer considérablement le temps d'exécution lors de la décomposition de matrices unitaires à deux qubits. Par conséquent, la durée d'exécution de la transpilation avec le niveau d'optimisation 3 a été considérablement améliorée lorsque l'exécution UnitarySynthesis entraînait historiquement un surcoût d'exécution important. Cette version commence également à fonctionner UnitarySynthesis dans le cadre de l'étape d'optimisation au niveau d'optimisation 2 en raison de ces améliorations des performances d'exécution.

    En outre, les méthodes numériques utilisées en Isometry ont été transférées à Rust, ce qui a permis d'accélérer considérablement le temps d'exécution, en particulier pour la synthèse de portes unitaires contrôlées. La décomposition pour le contrôle multiple XGate et PhaseGate a été améliorée, ce qui a permis de réduire le nombre de portes utilisées dans la synthèse de plus de deux ordres de grandeur.

  • Un certain nombre de nouvelles passes de transpilation ont été introduites dans Qiskit et permettent d'accélérer considérablement l'exécution tout en réduisant la taille des circuits quantiques transposés dans de nombreux cas. En particulier, ElidePermutations et StarPreRouting ont démontré qu'elles avaient un impact significatif sur la qualité des résultats du routage et sur la durée d'exécution RemoveFinalReset peuvent améliorer les circuits quantiques qui incluent des réinitialisations.

  • Les gestionnaires de passes par défaut ont été améliorés en les étendant aux passes de transpilation nouvellement introduites. En particulier, le gestionnaire de passes prédéfini de niveau d'optimisation 2 provenant de generate_preset_pass_manager et utilisé en interne par transpile() a été remanié pour obtenir un meilleur compromis entre la durée d'exécution et l'effort d'optimisation afin de servir de gestionnaire de passe par défaut dans les prochaines versions. Bien que cette version ne modifie pas l'utilisation par défaut du niveau 2, il s'agit généralement d'un meilleur choix que l'utilisation du niveau 1 ou 3.

  • De nouvelles implémentations de la primitive générique V2 ont été ajoutées, BackendEstimatorV2 et BackendSamplerV2pour compléter les implémentations existantes basées sur le vecteur d'état complet.

  • Changements dans la prise en charge des plateformes : Python 3.8 est obsolète à partir de Qiskit 1.1.0 et ne sera plus pris en charge dans 1.3.0, et arm64 macOS a été promu à la prise en charge de niveau 1.

Caractéristiques des circuits

  • Les méthodes QuantumCircuit.power(), Gate.power()ainsi que les méthodes similaires sur les sous-classes de sous-classes de Gate (telles que de SGate) ont toutes un nouvel argument supplémentaire annotated qui est utilisé pour renvoyer un objet AnnotatedOperation lors de l'application d'une puissance à une porte ou à un circuit. La valeur par défaut de False correspond au comportement existant. En outre, pour les portes standard dont la méthode power est explicitement définie, l'argument annotated n'a aucun effet. Par exemple, SGate().power(1.5, annotated=False) et SGate().power(1.5, annotated=True) renvoient tous deux un PhaseGate. Une différence dans la valeur de annotated se manifeste pour les portes qui n'ont pas de méthode de puissance explicitement définie. La valeur de False renvoie un UnitaryGatecomme précédemment, tandis que la valeur de True renvoie un AnnotatedOperation qui représente l'instruction modifiée avec le "power modifier".

  • Ajout d'un nouvel argument ctrl_state à QuantumCircuit.mcp() et MCPhaseGate.

    La méthode QuantumCircuit.mcp() et la classe MCPhaseGate ont été mises à jour pour inclure un paramètre ctrl_state . Cette amélioration permet aux utilisateurs de spécifier l'état de contrôle de la porte de phase multicontrôlée. Le paramètre peut accepter une valeur entière ou une chaîne de bits et contrôle par défaut l'état "1" s'il n'est pas fourni.

    from qiskit import QuantumCircuit
    
    qc = QuantumCircuit(4)
    qc.mcp(0.2,[0,1,2],3,ctrl_state=2)
  • Ajout d'un nouvel argument ctrl_state à QuantumCircuit.mcx().

    La méthode QuantumCircuit.mcx() de la bibliothèque de circuits quantiques a été améliorée pour inclure un paramètre ctrl_state, permettant aux utilisateurs de spécifier l'état de contrôle de la porte X multicontrôlée. Ce paramètre peut accepter une valeur décimale ou une chaîne de bits et contrôle par défaut l'état "1" s'il n'est pas fourni.

    from qiskit import QuantumCircuit
    
    qc = QuantumCircuit(3, 3)
    qc.mcx([0, 1], 2, ctrl_state="00")
  • A QuantumCircuit peut désormais contenir des variables classiques typées :

    from qiskit.circuit import QuantumCircuit, ClassicalRegister, QuantumRegister
    from qiskit.circuit.classical import expr, types
    
    qr = QuantumRegister(2, "q")
    cr = ClassicalRegister(2, "c")
    qc = QuantumCircuit(qr, cr)
    # Add two input variables to the circuit with different types.
    a = qc.add_input("a", types.Bool())
    mask = qc.add_input("mask", types.Uint(2))
    
    # Test whether the input variable was true at runtime.
    with qc.if_test(a) as else_:
        qc.x(0)
    with else_:
        qc.h(0)
    
    qc.cx(0, 1)
    qc.measure(qr, cr)
    
    # Add a typed variable manually, initialized to the same value as the classical register.
    b = qc.add_var("b", expr.lift(cr))
    
    qc.reset([0, 1])
    qc.h(0)
    qc.cx(0, 1)
    qc.measure(qr, cr)
    
    # Store some calculated value into the `b` variable.
    qc.store(b, expr.bit_and(b, cr))
    # Test whether we had equality, up to a mask.
    with qc.if_test(expr.equal(expr.bit_and(b, mask), mask)):
        qc.x(0)

    Ces variables peuvent être spécifiées soit en tant qu' entrées dans le circuit, soit en tant que variables cadrées. L'objet circuit ne prend pas encore en charge la représentation des sorties de variables classiques typées, mais cela sera ajouté ultérieurement lorsque le matériel et les interfaces de résultats seront mieux en mesure de le prendre en charge. Les circuits qui représentent un bloc d'une portée intérieure peuvent également capturer des variables de portées extérieures.

    Une variable est un Var qui peut désormais contenir un type arbitraire et représente un emplacement de mémoire unique dans sa plage de vie lorsqu'il est ajouté à un circuit. Ceux-ci peuvent être construits dans un circuit utilisant QuantumCircuit.add_var() et QuantumCircuit.add_input()ou à un niveau inférieur en utilisant Var.new().

    Les variables peuvent être stockées manuellement dans, en utilisant l'instruction Store et la méthode de circuit correspondante QuantumCircuit.store(). Il s'agit notamment d'écrire à Clbit et ClassicalRegister enveloppées dans des nœuds Var nœuds.

    Les variables peuvent être utilisées partout où les expressions classiques (voir qiskit.circuit.classical.expr) sont valables. Actuellement, il s'agit des expressions cibles des opérations de flux de contrôle, mais nous prévoyons de les étendre aux paramètres des portes à l'avenir, à mesure que le système de types et d'expressions sera développé.

    Voir Calcul classique en temps réel pour plus de détails sur ces variables et le modèle de données associé.

    Ceux-ci sont pris en charge par l'ensemble du transpileur, par le biais de la sérialisation QPY (qiskit.qpy), OpenQASM 3 export (qiskit.qasm3), et sont initialement supportés par les visualisateurs de circuits (voir QuantumCircuit.draw()).

    Remarque

    Il faudra un certain temps pour que les nouvelles variables classiques et le stockage soient pris en charge par le matériel et les backends des simulateurs. Elles ne sont pas prises en charge par les interfaces de primitives (qiskit.primitives), mais elles seront probablement intégrées à ces interfaces au fur et à mesure de leur évolution.

  • Le module classique d'expressions en temps réel qiskit.circuit.classical peut maintenant représenter l'indexation et le décalage de bits d'entiers non signés et de bits similaires (par ex. ClassicalRegister). Par exemple, il est désormais possible de comparer un registre avec le décalage de bits d'un autre registre :

    from qiskit.circuit import QuantumCircuit, ClassicalRegister
    from qiskit.circuit.classical import expr
    
    cr1 = ClassicalRegister(4, "cr1")
    cr2 = ClassicalRegister(4, "cr2")
    qc = QuantumCircuit(cr1, cr2)
    with qc.if_test(expr.equal(cr1, expr.shift_left(cr2, 2))):
        pass

    Qiskit peut également représenter une condition qui indexe dynamiquement un registre :

    with qc.if_test(expr.index(cr1, cr2)):
        pass
  • Les performances de construction de NLocal et de ses sous-classes de bibliothèques de circuits dérivées (par ex. EfficientSU2 et RealAmplitudes) s'est considérablement améliorée lorsque les sous-blocs de rotation et/ou d'enchevêtrement sont de simples applications d'une seule porte de la bibliothèque standard Qiskit. Étant donné que ces circuits sont construits paresseusement, il se peut que l'amélioration ne soit pas visible immédiatement lors de l'instanciation de la classe, mais plutôt lors du premier accès à sa structure interne. Les améliorations de performance sont de l'ordre de dix fois plus rapides.

  • QuantumCircuit.append() dispose désormais d'un mot-clé copy , dont la valeur par défaut est True. Lorsqu'une instruction avec des paramètres d'exécution (ParameterExpression) est ajoutée à un circuit, par défaut, le circuit a toujours créé une copie de l'instruction, de sorte que si l'on tente de muter l'instruction en place, cela n'affecte pas les autres références à la même instruction QuantumCircuit.assign_parameters() tente de muter l'instruction en place, cela n'affecte pas les autres références à la même instruction. L'option copy=False vous permet d'outrepasser cette règle, de sorte que vous pouvez éviter la pénalité de copie si vous savez que vos instructions ne seront pas utilisées dans d'autres lieux.

  • QuantumCircuit.compose() dispose désormais d'un mot-clé copy , dont la valeur par défaut est True. Par défaut, compose() copie toutes les instructions, de sorte que les mutations d'un circuit n'affectent pas les autres. Si copy=False, les instructions de l'autre circuit seront directement détenues par le nouveau circuit, ce qui peut impliquer leur mutation sur place. Dans ce cas, l'autre circuit ne doit pas être utilisé par la suite.

  • Le temps de construction des QuantumVolume a été considérablement amélioré, de l'ordre de 10x ou un peu plus. Les portes internes de SU4 utiliseront désormais davantage de bits d'aléa lors de leur génération, ce qui permettra d'obtenir des circuits en volume plus représentatifs, en particulier pour les grandes largeurs et profondeurs.

  • QuantumVolume dispose désormais d'un argument de mot-clé flatten . La valeur par défaut est False, où le circuit construit contient une seule instruction qui, à son tour, contient la structure réelle du volume. S'il est réglé sur True, le circuit aura directement les matrices volumétriques SU4.

  • UnitaryGate accepte désormais un argument facultatif num_qubits . Le seul effet est de sauter la déduction du nombre de qubits, ce qui peut être utile pour les performances lorsque de nombreuses portes sont construites.

  • QuantumCircuit dispose de plusieurs nouvelles méthodes pour travailler et inspecter les variables manuelles Var manuelles.

    Voir Travailler avec des données classiques typées en temps réel pour une discussion plus approfondie sur tous ces points.

    Les nouvelles méthodes sont les suivantes

    En outre, plusieurs nouveaux attributs dynamiques entourent ces variables QuantumCircuit entourant ces variables :

  • ControlFlowOp et ses sous-classes ont désormais une méthode iter_captured_vars() qui renvoie un itérateur sur les variables uniques capturées dans n'importe lequel de ses blocs immédiats.

  • DAGCircuit dispose de plusieurs nouvelles méthodes pour travailler et inspecter les variables manuelles Var manuelles. Ils sont en grande partie équivalents à leurs QuantumCircuit sauf que les DAGCircuit sont optimisées pour un accès programmatique avec des objets déjà définis, tandis que les méthodes QuantumCircuit sont plus axées sur une utilisation humaine interactive.

    Les nouvelles méthodes sont les suivantes

    Il existe également de nouveaux attributs publics :

  • DAGCircuit.wires contiendra désormais également toutes les variables manuelles du circuit, puisqu'il s'agit également d'un flux de données classique Var les variables manuelles du circuit, puisqu'il s'agit également d'un flux de données classique.

  • Une nouvelle méthode, Var.new()est ajoutée pour construire manuellement une variable classique en temps réel qui possède sa propre mémoire.

  • QuantumCircuit.compose() a deux arguments de mots-clés nécessaires, var_remap et inline_captures , pour mieux prendre en charge les variables classiques en temps réel.

    var_remap peut être utilisé pour réécrire les nœuds Var dans l'argument du circuit au fur et à mesure que ses instructions sont intégrées au circuit de base. Cela permet d'éviter les conflits de noms.

    inline_captures peut être fixé à True (valeur par défaut : False) pour lier tous les nœuds Var nœuds suivis comme "captures" dans le circuit argument avec les mêmes nœuds dans le circuit de base, sans tenter de redéclarer les variables Var dans le circuit de base, sans essayer de redéclarer les variables. Ceci peut être utilisé, en combinaison avec la gestion de QuantumCircuit.copy_empty_like()vars_mode="captures" , pour construire un circuit couche par couche, contenant des variables.

  • DAGCircuit.compose() dispose d'un nouveau mot-clé, inline_captures, qui peut être défini à True pour intégrer les nœuds "capturés" du circuit argument dans le circuit de base sans les redéclarer Var capturés sur le circuit de l'argument sur le circuit de base sans les redéclarer. En conjonction avec l'option vars_mode="captures" de plusieurs méthodes DAGCircuit cette option peut être utilisée pour combiner des DAGs qui opèrent sur les mêmes variables.

  • QuantumCircuit.copy_empty_like() et DAGCircuit.copy_empty_like() ont un nouveau mot-clé, vars_mode , qui contrôle la façon dont les nœuds possédant de la mémoire sont suivis dans la sortie Var sont suivis dans la sortie. Par défaut ("alike"), les variables sont déclarées dans le même mode input/captured/local que la source. Cette valeur peut être fixée à "captures" pour convertir toutes les variables en captures (utile avec compose()) ou "drop" pour les supprimer.

  • Un nouvel argument vars_mode a été ajouté au mot-clé DAGCircuit méthodes :

    qui a la même signification que pour copy_empty_like().

  • Toutes les "portes standard" de la bibliothèque de circuits (qiskit.circuit.library) peuvent maintenant être spécifiées par un nom de chaîne de caractères pour les opérations d'enchevêtrement dans les circuits TwoLocal tels que RealAmplitudes et EfficientSU2.

Fonctionnalités primitives

  • La mise en œuvre BackendEstimatorV2 de BaseEstimatorV2 a été ajoutée. Cet estimateur prend en charge BackendV1 et BackendV2.

    import numpy as np
    from qiskit import transpile
    from qiskit.circuit.library import IQP
    from qiskit.primitives import BackendEstimatorV2
    from qiskit.providers.fake_provider import Fake7QPulseV1
    from qiskit.quantum_info import SparsePauliOp, random_hermitian
    
    backend = Fake7QPulseV1()
    estimator = BackendEstimatorV2(backend=backend)
    n_qubits = 5
    mat = np.real(random_hermitian(n_qubits, seed=1234))
    circuit = IQP(mat)
    observable = SparsePauliOp("Z" * n_qubits)
    isa_circuit = transpile(circuit, backend=backend, optimization_level=1)
    isa_observable = observable.apply_layout(isa_circuit.layout)
    job = estimator.run([(isa_circuit, isa_observable)], precision=0.01)
    result = job.result()
    print(f"> Expectation value: {result[0].data.evs}")
    print(f"> Standard error: {result[0].data.stds}")
    print(f"> Metadata: {result[0].metadata}")
  • La mise en œuvre BackendSamplerV2 de BaseSamplerV2 a été ajoutée. Cet échantillonneur prend en charge BackendV1 et BackendV2 qui permettent à l'option memory de calculer des chaînes de bits.

    import numpy as np
    from qiskit import transpile
    from qiskit.circuit.library import IQP
    from qiskit.primitives import BackendSamplerV2
    from qiskit.providers.fake_provider import Fake7QPulseV1
    from qiskit.quantum_info import random_hermitian
    
    backend = Fake7QPulseV1()
    sampler = BackendSamplerV2(backend=backend)
    n_qubits = 5
    mat = np.real(random_hermitian(n_qubits, seed=1234))
    circuit = IQP(mat)
    circuit.measure_all()
    isa_circuit = transpile(circuit, backend=backend, optimization_level=1)
    job = sampler.run([isa_circuit], shots=100)
    result = job.result()
    print(f"> bitstrings: {result[0].data.meas.get_bitstrings()}")
    print(f"> counts: {result[0].data.meas.get_counts()}")
    print(f"> Metadata: {result[0].metadata}")
  • Ajout de méthodes pour joindre plusieurs objets BitArray objets le long de différents axes.

    ba = BitArray.from_samples(['00', '11'])
    print(ba)
    # BitArray(<shape=(), num_shots=2, num_bits=2>)
    
    # reshape the bit array because `concatenate` requires an axis.
    ba_ = ba.reshape(1, 2)
    print(ba_)
    # BitArray(<shape=(1,), num_shots=2, num_bits=2>)
    
    ba2 = BitArray.concatenate([ba_, ba_])
    print(ba2.get_bitstrings())
    # ['00', '11', '00', '11']
    
    # `concatenate_bits` and `concatenates_shots` do not require any axis.
    
    ba3 = BitArray.concatenate_bits([ba, ba])
    print(ba3.get_bitstrings())
    # ['0000', '1111']
    
    ba4 = BitArray.concatenate_shots([ba, ba])
    print(ba4.get_bitstrings())
    # ['00', '11', '00', '11']
  • Ajout de méthodes pour générer un sous-ensemble de l'objet BitArray en le découpant selon différents axes.

    • __getitem__(): découpe le tableau le long d'un axe existant du tableau.
    • slice_bits(): coupe le tableau le long de l'axe des bits.
    • slice_shots(): coupe le tableau le long de l'axe de prise de vue.
    ba = BitArray.from_samples(['0000', '0001', '0010', '0011'], 4)
    print(ba)
    # BitArray(<shape=(), num_shots=4, num_bits=4>)
    print(ba.get_bitstrings())
    # ['0000', '0001', '0010', '0011']
    
    ba2 = ba.reshape(2, 2)
    print(ba2)
    # BitArray(<shape=(2,), num_shots=2, num_bits=2>)
    print(ba2[0].get_bitstrings())
    # ['0000', '0001']
    print(ba2[1].get_bitstrings())
    # ['0010', '0011']
    
    ba3 = ba.slice_bits([0, 2])
    print(ba3.get_bitstrings())
    # ['00', '01', '00', '01']
    
    ba4 = ba.slice_shots([0, 2])
    print(ba3.get_bitstrings())
    # ['0000', '0010']
  • Ajout d'une méthode transpose() pour transposer un BitArray.

    ba = BitArray.from_samples(['00', '11']).reshape(2, 1, 1)
    print(ba)
    # BitArray(<shape=(2, 1), num_shots=1, num_bits=2>)
    print(ba.transpose())
    # BitArray(<shape=(1, 2), num_shots=1, num_bits=2>)
  • Ajout d'une méthode expectation_values() pour calculer les valeurs d'espérance des opérateurs diagonaux.

    ba = BitArray.from_samples(['01', '11'])
    print(ba.expectation_values(["IZ", "ZI", "01"]))
    # [-1.   0.   0.5]
  • DataBin satisfait désormais au Shaped protocole. Cela signifie que chaque DataBin possède désormais les attributs supplémentaires suivants

    • shape (tupleint[,...])la forme initiale de chaque entrée de l'instance
    • ndim (int) : la longueur de shape
    • size (int) : le produit des entrées de shape

    La forme peut être transmise au constructeur.

  • Ajout de fonctionnalités similaires à celles de la cartographie à DataBinc'est-à-dire __getitem__, __contains__, __iter__, keys(), values(), et items().

    from qiskit import QuantumCircuit
    from qiskit.primitives import StatevectorSampler
    
    circuit = QuantumCircuit(1)
    circuit.h(0)
    circuit.measure_all()
    
    sampler = StatevectorSampler()
    result = sampler.run([circuit]).result()
    databin = result[0].data
    for creg, arr in databin.items():
        print(creg, arr)
    for creg in databin:
        print(creg, databin[creg])
  • La sous-classe SamplerPubResult de PubResult a été ajoutée, que les implémentations de BaseSamplerV2 peuvent renvoyer. La principale caractéristique ajoutée à cette nouvelle sous-classe est la suivante join_data()qui rassemble (un sous-ensemble) le contenu de data en un seul objet. Cela permet d'obtenir les modèles suivants :

    job_result =  sampler.run([pub1, pub2, pub3], shots=123).result()
    
    # assuming all returned data entries are BitArrays
    counts1 = job_result[0].join_data().get_counts()
    bistrings2 = job_result[1].join_data().get_bitstrings()
    array3 = job_result[2].join_data().array

Fonctionnalités des fournisseurs

Fonctionnalités Pulse

  • Il est désormais possible d'attribuer des paramètres aux impulsions Schedule et ScheduleBlock en spécifiant le nom du paramètre sous la forme d'une chaîne de caractères. Le nom du paramètre peut être utilisé pour attribuer des valeurs à tous les paramètres à l'intérieur de la zone Schedule ou ScheduleBlock qui portent le même nom. De plus, le nom de paramètre d'un ParameterVector peut être utilisé pour assigner toutes les valeurs du vecteur simultanément (la liste des valeurs doit donc correspondre à la longueur du vecteur).

  • Les méthodes assign_parameters de Schedule et ScheduleBlock prennent désormais en charge l'affectation simultanée d'un ParameterVector à une liste de valeurs de paramètres simultanément, en plus de l'affectation d'instances individuelles de Parameter à des valeurs individuelles.

OpenQASM Caractéristiques

  • L'exportateur OpenQASM 3 prend en charge les nœuds de stockage manuel sur les circuits Var sur les circuits.

Caractéristiques du QPY

  • LA VERSION 12 DU FORMAT QPY (qiskit.qpy), la version 12 a été ajoutée, ce qui inclut la prise en charge des variables à mémoire Var possédant de la mémoire. Voir la version 12 pour plus de détails sur les changements de format.

Caractéristiques de l'information quantique

  • Ajout d'une nouvelle méthode apply_layout() qui est équivalente à apply_layout(). Cette méthode est utilisée pour appliquer une TranspileLayout du transpileur à un observable qui a été construit pour un circuit d'entrée Pauli observable qui a été construit pour un circuit d'entrée. Cela permet de travailler avec BaseEstimator / BaseEstimatorV2 et la transpilation locale lorsque l'entrée est de type Pauli. Par exemple :

    from qiskit.circuit.library import RealAmplitudes
    from qiskit.primitives import BackendEstimatorV2
    from qiskit.providers.fake_provider import GenericBackendV2
    from qiskit.quantum_info import Pauli
    from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
    
    psi = RealAmplitudes(num_qubits=2, reps=2)
    H1 = Pauli("XI")
    backend = GenericBackendV2(num_qubits=7)
    estimator = BackendEstimatorV2(backend=backend)
    thetas = [0, 1, 1, 2, 3, 5]
    pm = generate_preset_pass_manager(optimization_level=3, backend=backend)
    transpiled_psi = pm.run(psi)
    permuted_op = H1.apply_layout(transpiled_psi.layout)
    res = estimator.run([(transpiled_psi, permuted_op, thetas)]).result()

    où un circuit d'entrée est transposé localement avant d'être transmis à run(). La transpilation fait passer le circuit original de 2 à 7 qubits (la taille de backend) et permute sa disposition, qui est ensuite appliquée à H1 à l'aide de apply_layout() pour refléter les transformations effectuées par pm.run().

  • Ajoute les PauliList.noncommutation_graph() et SparsePauliOp.noncommutation_graph() en exposant la construction de graphes de non-commutation, en refondant le problème de regroupement des opérateurs de mesure en un problème de coloration de graphes. Cela permet aux utilisateurs de travailler directement avec ces graphes, par exemple pour explorer des algorithmes de coloration autres que celui utilisé par SparsePauliOp.group_commuting().

  • Les performances de SparsePauliOp.to_matrix() a été grandement améliorée, tant pour les formes denses que pour les formes éparses. Par défaut, les deux prendront désormais avantage du parallélisme threadé disponible sur votre système, sous réserve de la variable d'environnement RAYON_NUM_THREADS . Vous pouvez temporairement forcer l'exécution en série en utilisant le nouvel argument booléen force_serial de la commande to_matrix().

Caractéristiques de la synthèse

  • Le KMSSynthesisLinearFunction pour synthétiser des objets LinearFunction accepte désormais deux options supplémentaires : use_inverted et use_transposed. Ces options modifient la matrice sur laquelle tourne l'algorithme de synthèse sous-jacent, éventuellement en l'inversant et/ou en la transposant, et ajustent ensuite de manière appropriée le circuit synthétisé. En faisant varier ces options, nous obtenons généralement des circuits synthétisés différents, et dans certains cas, nous pouvons obtenir de meilleurs résultats qu'avec leurs valeurs par défaut.

  • Le PMHSynthesisLinearFunction pour synthétiser des objets LinearFunction accepte désormais plusieurs options supplémentaires. L'option section_size est transmise à la méthode de synthèse sous-jacente. Les options use_inverted et use_transposed modifient la matrice sur laquelle tourne l'algorithme de synthèse sous-jacent en l'inversant et/ou en la transposant éventuellement, puis ajustent de manière appropriée le circuit synthétisé. En faisant varier ces options, nous obtenons généralement des circuits synthétisés différents, et dans certains cas, nous pouvons obtenir de meilleurs résultats qu'avec leurs valeurs par défaut.

  • Ajout d'un nouvel argument, use_dag, à la méthode TwoQubitBasisDecomposer.__call__() et XXDecomposer.__call__() méthodes. Cet argument est utilisé pour contrôler si un DAGCircuit est retourné lors de l'appel d'un TwoQubitBasisDecomposer ou XXDecomposer au lieu de l'instance par défaut QuantumCircuit. Par exemple :

    from qiskit.circuit.library import CXGate
    from qiskit.quantum_info import random_unitary
    from qiskit.synthesis import TwoQubitBasisDecomposer
    
    decomposer = TwoQubitBasisDecomposer(CXGate(), euler_basis="PSX")
    decomposer(random_unitary(4), use_dag=True)

    renverra un DAGCircuit lors de l'appel de l'instance TwoQubitBasisDecomposer instance decomposer.

  • LieTrotter.synthesize() utilise désormais QuantumCircuit.repeat() pour générer des répétitions supplémentaires d'un pas de Trotter après le premier pas de Trotter. Cela permet de réduire le nombre d'appels QuantumCircuit.compose() par un facteur de reps et réduit considérablement la durée d'exécution pour les opérateurs les plus importants.

  • Ajouter une nouvelle méthode de synthèse synth_permutation_reverse_lnn_kms() de permutations inversées pour les architectures linéaires à plus proche voisin en utilisant la méthode Kutin, Moulton, Smithline. Cet algorithme synthétise la permutation inverse sur nn qubits sur une architecture linéaire à plus proche voisin utilisant des portes CX de profondeur 2n+22 * n + 2.

  • La classe TwoQubitBasisDecomposer a été réécrite en rouille, ce qui améliore considérablement les performances d'exécution.

  • La classe TwoQubitWeylDecomposition a été réécrite en Rust pour de meilleures performances.

Fonctionnalités du transpilateur

  • Extension de l'analyse de commutation effectuée par CommutationChecker pour qu'elle fonctionne également avec des circuits abstraits, c'est-à-dire que chaque opération dans le circuit quantique d'entrée est maintenant vérifiée pour sa représentation matricielle avant de procéder à l'étape d'analyse. Auparavant, l'analyse de commutation n'était effectuée que sur des circuits physiques. En outre, il est désormais vérifié que chaque opération peut être mise en cache dans la bibliothèque de commutation de la session. Par exemple, cela permet maintenant de calculer si AnnotatedOperation commute. Cela permet aux passes de transpilation qui s'appuient sur CommutationChecker en interne, telles que CommutativeCancellationde s'exécuter au cours des premières étapes d'un pipeline de transpilation par défaut (avant la traduction de la base).

  • La passe de transpilation ElidePermutations s'exécute par défaut dans l'étape init pour les niveaux d'optimisation 2 et 3. Intuitivement, en supprimant SwapGateet PermutationGatedans un circuit virtuel est presque toujours bénéfique, car elle rend le circuit plus court et plus facile à acheminer. Comme OptimizeSwapBeforeMeasure est un cas particulier de ElidePermutationsil a été remplacé par la passe ElidePermuations dans le cadre de l'étape init des gestionnaires de passes d'optimisation de niveau 3.

  • Ajout d'une nouvelle passe de transposition d'optimisation, ElidePermutationsqui est conçue pour être exécutée avant l' étape de mise en page et qui optimisera tous les SwapGateet PermutationGatedans un circuit en permutant les qubits virtuels. Par exemple, en prenant un circuit avec SwapGates :

    _images/release_notes-1.png

    supprimera les échanges lors de l'exécution de la passe :

    from qiskit.transpiler.passes import ElidePermutations
    from qiskit.circuit import QuantumCircuit
    
    qc = QuantumCircuit(3)
    qc.h(0)
    qc.swap(0, 1)
    qc.swap(2, 0)
    qc.cx(1, 0)
    qc.measure_all()
    
    ElidePermutations()(qc).draw("mpl")
    _images/release_notes-2.png

    La passe définit également l'ensemble de propriétés virtual_permutation_layout , qui stocke la permutation des qubits virtuels à la fin du circuit qui a été optimisé.

  • L'option HLSConfig dispose désormais de deux arguments facultatifs supplémentaires. L'argument plugin_selection peut être défini comme "sequential" ou "all". Si la valeur est "séquentielle" (par défaut), pour chaque objet de niveau supérieur, la passe HighLevelSynthesis considérera les méthodes spécifiées séquentiellement, dans l'ordre où elles apparaissent dans la liste, en s'arrêtant à la première méthode capable de synthétiser l'objet. Si elle est réglée sur "toutes", toutes les méthodes spécifiées seront prises en compte et le meilleur circuit synthétisé, selon plugin_evaluation_fn , sera choisi. L'argument plugin_evaluation_fn est un appel facultatif qui évalue la qualité du circuit quantique synthétisé; une valeur plus petite signifie un meilleur circuit. Lorsqu'il est fixé à None, la qualité du circuit est sa taille (c'est-à-dire le nombre de portes qu'il contient).

    L'exemple suivant illustre la nouvelle fonctionnalité :

    from qiskit import QuantumCircuit
    from qiskit.circuit.library import LinearFunction
    from qiskit.synthesis.linear import random_invertible_binary_matrix
    from qiskit.transpiler.passes import HighLevelSynthesis, HLSConfig
    
    # Create a circuit with a linear function
    mat = random_invertible_binary_matrix(7, seed=37)
    qc = QuantumCircuit(7)
    qc.append(LinearFunction(mat), [0, 1, 2, 3, 4, 5, 6])
    
    # Run different methods with different parameters,
    # choosing the best result in terms of depth.
    hls_config = HLSConfig(
        linear_function=[
            ("pmh", {}),
            ("pmh", {"use_inverted": True}),
            ("pmh", {"use_transposed": True}),
            ("pmh", {"use_inverted": True, "use_transposed": True}),
            ("pmh", {"section_size": 1}),
            ("pmh", {"section_size": 3}),
            ("kms", {}),
            ("kms", {"use_inverted": True}),
        ],
        plugin_selection="all",
        plugin_evaluation_fn=lambda circuit: circuit.depth(),
    )
    
    # synthesize
    qct = HighLevelSynthesis(hls_config=hls_config)(qc)

    Dans l'exemple, nous utilisons plusieurs méthodes de synthèse avec différents paramètres, en choisissant le meilleur circuit en termes de profondeur. Notez qu'en optimisant circuit.size() , vous choisirez un circuit différent.

  • Ajout du CommutativeCancellation à l'étape init des gestionnaires de passe prédéfinis pour les niveaux d'optimisation 2 et 3. Cela permet aux gestionnaires de passes prédéfinies d'annuler des opérations logiques supplémentaires au début du pipeline de compilation.

  • Les passes d'analyse suivantes acceptent désormais les contraintes encodées dans une balise Target grâce à un nouvel argument d'entrée target :

    Les contraintes cibles auront la priorité sur les contraintes fournies par l'utilisateur, par souci de cohérence avec le reste du pipeline du transpilateur.

  • Ajout d'une nouvelle méthode Layout.inverse() qui est utilisée pour prendre l'inverse d'un Layout objet. Ajout d'une nouvelle méthode Layout.compose() utilisée pour composer deux objets Layout ensemble. Ajout d'une nouvelle méthode Layout.to_permutation() qui permet de créer une permutation correspondant à un objet Layout objet.

  • Ajout d'une nouvelle réduction à la passe de OptimizeAnnotated transpiler. Cette réduction recherche des opérations annotées (objets de type AnnotatedOperation constitués d'une opération de base BB et d'une liste MM de modificateurs de contrôle, d'inverse et de puissance) ayant les propriétés suivantes :

    • l'opération de base BB doit être synthétisée (c'est-à-dire qu'elle n'est pas déjà supportée par la cible ou qu'elle appartient à la bibliothèque d'équivalence)
    • le circuit de définition de BB peut être exprimé comme suit : PP - QQ - RR avec R=P1R = P^{-1}

    Dans ce cas, les modificateurs peuvent être déplacés vers la partie QQ uniquement. À titre d'exemple, les additionneurs contrôlés basés sur la QFT ont la forme control - [QFT -- U -- IQFT], qui peut être simplifiée en QFT -- control-[U] -- IQFT. En supprimant les contrôles sur les parties QFT et IQFT du circuit, on obtient beaucoup moins de portes dans le circuit transposé.

  • Ajout de deux nouvelles méthodes à la DAGCircuit deux nouvelles méthodes : qiskit.dagcircuit.DAGCircuit.op_successors() retourne un itérateur vers les DAGOpNode successeurs d'un noeud, et qiskit.dagcircuit.DAGCircuit.op_successors() renvoie un itérateur vers les DAGOpNode prédécesseurs d'un noeud.

  • Ajout d'une nouvelle passe de transpilation, RemoveFinalResetqui supprimera toute opération Reset qui est la dernière instruction sur un fil de qubit. Par exemple, en prenant un circuit avec final Resets :

    _images/release_notes-3.png

    supprimera les réinitialisations finales lors de l'exécution de la passe :

    from qiskit.transpiler.passes import RemoveFinalReset
    from qiskit.circuit import QuantumCircuit
    
    qc = QuantumCircuit(3, 1)
    qc.reset(0)
    qc.h(range(3))
    qc.cx(1, 0)
    qc.measure(0, 0)
    qc.reset(range(3))
    RemoveFinalReset()(qc).draw("mpl")
    _images/release_notes-4.png
  • Ajout d'une nouvelle passe de transpilation StarPreRouting qui est conçue pour identifier les sous-circuits de connectivité en étoile et les remplacer par un routage linéaire optimal. Ceci est utile pour certains circuits qui sont composés de cette connectivité de circuit comme Bernstein-Vazirani et QFT. Par exemple :

    _images/release_notes-5.png
    from qiskit.circuit import QuantumCircuit
    from qiskit.transpiler.passes import StarPreRouting
    
    qc = QuantumCircuit(5)
    qc.h(0)
    qc.cx(0, range(1, 5))
    StarPreRouting()(qc).draw("mpl")
    _images/release_notes-6.png

    Il est également possible d'étendre un gestionnaire de laissez-passer préréglé existant :

    from qiskit import QuantumCircuit
    from qiskit.transpiler import CouplingMap
    from qiskit.transpiler.passes import StarPreRouting
    from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
    
    cm = CouplingMap.from_line(5)
    qc = QuantumCircuit(5)
    qc.h(0)
    qc.cx(0, range(1, 5))
    pm = generate_preset_pass_manager(2, coupling_map=cm)
    pm.init += StarPreRouting()
    result = pm.run(qc)
    result.draw("mpl")
    _images/release_notes-7.png

Fonctionnalités de visualisation

  • Les tiroirs de texte et de Matplotlib tiroirs de circuits (QuantumCircuit.draw()) offrent un support minimal pour l'affichage d'expressions impliquant des variables manuelles en temps réel. L'opération Store et les initialisations de variables ne sont pas encore prises en charge; pour les circuits dynamiques à grande échelle, nous recommandons d'utiliser les capacités d'exportation de OpenQASM 3 (qasm3.dumps()) pour obtenir une représentation textuelle d'un circuit.

Divers. Fonctions

  • Cette version de Qiskit finalise la prise en charge de NumPy 2.0. Qiskit continuera à soutenir les sites NumPy 1.x et 2.x dans un avenir proche.

Mise à niveau

  • Supprime le codage en dur des options de style pour les fichiers plot_histogram(). Cela permet d'appliquer fidèlement les fichiers de style Matplotlib aux figures. Les utilisateurs qui souhaitent aller au-delà des valeurs par défaut définies par Matplotlib peuvent créer leurs propres fichiers de style ou transmettre un objet Matplotlib Axes à plot_histogram et appliquer a posteriori toute personnalisation.

  • La fonction transpile() a été mise à jour pour convertir en interne les entrées backend de type BackendV1 en BackendV2ce qui permet au pipeline de transpilation d'accéder aux contraintes de l'arrière-plan par le biais d'un élément de type Target. Cette modification ne nécessite aucune action de la part de l'utilisateur.

Notes sur la mise à niveau des circuits

  • L'utilisation des nombres aléatoires de QuantumVolume a changé, vous obtiendrez donc un circuit différent pour une graine fixe entre les anciennes versions de Qiskit et cette version. La génération aléatoire-unitaire utilise maintenant plus de bits d'entropie, de sorte que les grands circuits seront moins biaisés.

  • Les instances UnitaryGate dans la définition d'un QuantumVolume n'auront plus de champ label ne sera plus défini. Auparavant, il s'agissait de la chaîne su4_<seed> , où <seed> était un nombre à trois chiffres indiquant la graine d'une instance interne de Numpy pRNG pour cette porte. Cela posait un sérieux problème de performance, et la graine n'aurait pas dû être utile; si vous avez besoin de récupérer la matrice à partir de la porte, utilisez simplement la méthode Gate.to_matrix() méthode.

Notes de mise à niveau des primitives

  • La fonction make_data_bin() ne crée plus et ne renvoie plus de DataBin sous-classe. En revanche, il renvoie toujours la DataBin classe. Cependant, il continue d'exister pour des raisons de rétrocompatibilité, mais il sera à terme obsolète. Tous les utilisateurs devraient migrer pour construire directement des instances DataBin directement, au lieu d'instancier des sous-classes comme le fait make_data_bin().

Notes de mise à niveau des fournisseurs

  • La mise en œuvre de BackendV2 (et BackendV1) peuvent souhaiter mettre à jour leurs méthodes run() pour rejeter avec empressement les entrées contenant des variables classiques typées (voir qiskit.circuit.classical) et l'instruction Store si elles ne les prennent pas en charge. La nouvelle instruction Store est traitée par le transpileur comme une "directive" toujours disponible (comme Barrier); si vos backends ne la supportent pas, elle ne sera pas prise en compte par la directive transpiler.

    Voir Variables en temps réel pour plus d'informations.

Notes de mise à niveau QPY

Notes de mise à niveau de Synthesis

  • Les TwoQubitWeylDecomposition ne s'auto-spécialise plus dans une sous-classe à la création. Il s'agit d'un détail interne de la classe TwoQubitWeylDecomposition et n'était pas un comportement public documenté car toutes les sous-classes se comportaient de la même manière et n'étaient utilisées que pour l'envoi interne. Cependant, comme ce comportement a été découvert, cette note de mise à jour a pour but de documenter le fait que cela ne se produira plus et que toutes les instances de TwoQubitWeylDecomposition seront du même type. Il n'y a pas de changement de comportement pour les méthodes publiques de la classe.

Notes de mise à niveau du transpilateur

  • Le préréglage StagedPassManager retourné pour le niveau d'optimisation 2 par generate_preset_pass_manager() et level_2_pass_manager() ont été retravaillés pour offrir un meilleur équilibre entre la durée d'exécution et l'optimisation. Cela signifie que les circuits de sortie seront modifiés par rapport aux versions précédentes. Si vous avez besoin d'un gestionnaire de passes exact du niveau 2 dans des versions antérieures, vous pouvez soit le construire manuellement, soit l'utiliser à partir d'une version antérieure et sauvegarder les circuits à l'aide de la commande qpy pour le charger dans une version plus récente.

Divers. Mise à niveau

  • La version minimale de Windows prise en charge est désormais Windows 10. Dans les versions précédentes, nous ne mentionnions pas explicitement une version minimale de Windows et, implicitement, Windows 7, 8 et 8.1 auraient pu fonctionner (mais n'ont jamais été testés). Mais en raison de l'abandon par Rust 1.78 de la prise en charge des anciennes versions de Windows, les binaires publiés par Qiskit sur PyPI ne prendront plus en charge les anciennes versions de Windows à partir de cette version. Si vous utilisez une ancienne version de Windows, vous pouvez probablement encore compiler Qiskit à partir des sources en utilisant un compilateur Rust plus ancien (la version Rust minimale supportée par Qiskit pour la compilation à partir des sources est actuellement 1.70 ), mais les anciennes versions de Windows ne sont pas une plateforme supportée et ne sont pas testées.

Remarques concernant la dépréciation

  • La prise en charge de l'exécution de Qiskit avec Python 3.8 est obsolète et sera supprimée dans la version de Qiskit 1.3.0. Le site 1.3.0 est la première version après que le site Python 3.8 a atteint sa fin de vie et n'est plus pris en charge. [1] Cela signifie qu'à partir de la version 1.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/

Avertissements aux fournisseurs

  • Les classes de base abstraites Provider et ProviderV1 sont désormais obsolètes et seront supprimées dans Qiskit 2.0.0. L'abstraction offerte par ces définitions d'interface n'apportait pas de valeur substantielle; elle encapsulait uniquement les attributs name, backends, et a get_backend(). Un fournisseur, en tant que concept, continuera d'exister en tant que collection de backends. Si vous implémentez actuellement un fournisseur, vous pouvez adapter votre code en supprimant simplement ProviderV1 en tant que classe parente de votre implémentation. Dans ce cadre, vous voudrez probablement ajouter une implémentation de get_backend pour assurer la compatibilité ascendante. Par exemple :

    def get_backend(self, name=None, **kwargs):
      backends = self.backends(name, **kwargs)
      if len(backends) > 1:
          raise QiskitBackendNotFoundError("More than one backend matches the criteria")
      if not backends:
          raise QiskitBackendNotFoundError("No backend matches the criteria")
      return backends[0]

Dépréciations de synthèse

  • La méthode TwoQubitWeylDecomposition.specialize() est désormais obsolète et sera supprimée dans la version de Qiskit 2.0.0. Cette méthode n'a jamais eu d'utilité publique et n'était pas sûre pour un utilisateur final, car elle aurait modifié la décomposition calculée dans l'objet et produit des champs non valides dans l'objet. Il n'a été utilisé qu'en interne pour construire un nouvel objet TwoQubitWeylDecomposition objet. Malgré cela, il s'agissait toujours d'une partie documentée de l'API publique de la classe et il est maintenant déprécié sans aucun remplacement potentiel. Cette version lèvera toujours NotImplementedError lorsqu'elle sera appelée car le sous-classement de la spécialisation a été supprimé dans le cadre de la réécriture Rust de la classe.

Dépréciations du transcompilateur

  • Le pass qiskit.transpiler.passes.CXCancellation a été déprécié en faveur de InverseCancellationqui est plus générique. CXCancellation est pleinement équivalent sémantiquement à InverseCancellation([CXGate()]).

  • La passe de transpilation qiskit.transpiler.passes.ALAPSchedule est désormais obsolète. Il était en attente de dépréciation depuis Qiskit 0.37 (avec Terra 0.21 ), publié en juin 2022. La passe est remplacée par ALAPScheduleAnalysisqui est une passe d'analyse.

  • La passe de transpilation qiskit.transpiler.passes.ASAPSchedule est désormais obsolète. Il était en attente de dépréciation depuis Qiskit 0.37 (avec Terra 0.21 ), publié en juin 2022. Il a été remplacé par ASAPScheduleAnalysis et le nouveau flux de travail de programmation.

  • La passe de transpilation qiskit.transpiler.passes.DynamicalDecoupling est désormais obsolète. Il était en attente de dépréciation depuis Qiskit 0.37 (avec Terra 0.21 ), publié en juin 2022. Au lieu de cela, utilisez PadDynamicalDecouplingqui remplit la même fonction, mais nécessite l'exécution préalable de passes d'analyse de l'ordonnancement et de l'alignement.

  • La passe de transpilation qiskit.transpiler.passes.AlignMeasures est désormais obsolète. Il était en attente de dépréciation depuis Qiskit 0.37 (avec Terra 0.21 ), publié en juin 2022. Au lieu de cela, utilisez ConstrainedReschedulequi remplit la même fonction et permet également de s'aligner sur des contraintes de temps supplémentaires.

Dépréciations de la visualisation

  • Les paramètres show_idle et show_barrier des tiroirs chronologiques ont été remplacés par idle_wires et plot_barriers respectivement pour correspondre aux paramètres des tiroirs de circuits. Leurs noms précédents sont désormais obsolètes et seront supprimés dans la prochaine version majeure. Les nouveaux paramètres sont parfaitement équivalents.

Corrections des erreurs

  • Correction d'un problème avec la fonction qpy.dump() où, lorsque l'indicateur use_symengine était défini sur un objet véridique évalué à True mais qui n'était pas en fait le booléen True, la charge utile QPY générée était corrompue. Par exemple, si vous attribuez à use_symengine la valeur HAS_SYMENGINEcet objet est évalué à True lorsqu'il est converti en bool, mais n'est pas réellement True.

  • Correction d'un problème avec la fonction circuit_drawer() fonction et QuantumCircuit.draw() lors du chargement d'un style matplotlib via le fichier de configuration utilisateur.

  • Correction d'un problème où la passe de ConstrainedReschedule transpiler pass provoquait auparavant une erreur si le circuit contenait une Reset instruction. Cela a été corrigé de sorte que la passe ne provoque plus d'erreurs, mais le matériel réel peut se comporter différemment de ce que suppose l'ordonnanceur Qiskit, en particulier pour les mesures en milieu de circuit et les réinitialisations. Le planificateur Qiskit lève RuntimeWarning s'il rencontre un circuit contenant l'un ou l'autre de ces éléments. Corrigé #10354

  • Correction d'un problème avec la classe CommutationChecker qui provoquait une erreur si l'attribut name d'une porte était encodé en UTF8. Auparavant, seuls les noms de porte codés en ascii fonctionnaient. Corrigé #12501

  • Correction d'un problème avec les SparsePauliOp.apply_layout() et Pauli.apply_layout() lorsqu'un tableau invalide avec des indices dupliqués ou négatifs était transmis pour l'argument layout . Auparavant, cela n'entraînait pas d'erreur et la transformation effectuée n'était pas valide. Ces méthodes lèveront désormais un QiskitError si des indices en double ou des indices négatifs sont fournis dans le cadre d'une mise en page.

  • Correction d'un problème de performance dans les BackendSamplerV2 et BackendEstimatorV2. Corrigé #12290

  • Correction d'un problème avec l'attribut convert_to_target() où le convertisseur ignorait à tort les instructions de flux de contrôle si elles étaient spécifiées dans l'attribut BackendConfiguration.supported_instructions , qui est l'emplacement typique où les instructions de flux de contrôle sont spécifiées dans un objet BackendConfiguration objet. Correction #11872.

  • Correction d'un problème avec la fonction circuit_drawer() ou QuantumCircuit.draw() lors de l'utilisation de l'option de sortie mpl . Le programme se bloquait si le circuit dessiné contenait une opération ControlFlow et que l'option fold était réglée sur -1 (ce qui signifie pas de pli). Correction #12012.

  • Correction d'un bogue dans la conversion des instructions d'impulsion personnalisées au format legacy qiskit.qobj ancien. Le bogue a été introduit dans Qiskit 1.0.0 et provoquait une erreur lors de la conversion d'instructions avec des formes d'impulsion personnalisées. Après la correction, la conversion s'effectue correctement et l'impulsion personnalisée est convertie en Waveform comme il se doit. Correction #11828.

  • Un bogue dans transpile() a été corrigé : les contraintes personnalisées instruction_durations, dt et backend_properties étaient ignorées lorsqu'elles étaient fournies en même temps qu'un backend de type BackendV2. Le comportement après la correction est maintenant indépendant du fait que le backend fourni soit de type BackendV1 ou de type BackendV2. De même, les entrées personnalisées timing_constraints sont désormais remplacées par les entrées target , mais ont la priorité sur les entrées BackendV1 et BackendV2 les entrées.

  • L'appel à EquivalenceLibrary.set_entry() mettra désormais correctement à jour l'objet graphique interne de la bibliothèque. Auparavant, les métadonnées étaient mises à jour, mais la structure du graphe restait inchangée, ce qui signifiait que des utilisateurs tels que BasisTranslator continueraient à utiliser les anciennes règles. Correction #11958.

  • La fonction EvolvedOperatorAnsatz gère désormais correctement le cas où l'argument des opérateurs est une liste vide. Auparavant, cela entraînait une erreur.

  • A partir de maintenant, EvolvedOperatorAnsatz n'aura pas de qregs quand il y a zéro qubit, au lieu d'avoir une instance avec zéro qubit QuantumRegister avec zéro qubit. Ce comportement est plus cohérent avec celui de la superclasse QuantumCircuit.

  • La méthode Instruction.repeat() déplace maintenant un ensemble condition vers l'extérieur retourné Instruction et laisse les portes intérieures de sa définition inconditionnelles. Auparavant, la méthode laissait les instances ClassicalRegister dans la définition interne, ce qui était un état invalide et se manifestait par des bogues apparemment sans rapport par la suite, par exemple lors de la transpilation ou de l'exportation. Correction #11935.

  • Correction d'un problème dans la passe InverseCancellation qui, dans certains cas, annulait incorrectement une porte paramétrée auto-inverse même si la valeur du paramètre ne correspondait pas. Corrigé #11815

  • Améliorer la décomposition des portes MCXGate et MCPhaseGate sans utiliser de qubits ancillaires, de sorte que le nombre de CXGate croîtra quadratiquement en fonction du nombre de qubits et non pas exponentiellement.

  • Un bogue qui faisait planter la fonction convert_to_target() lorsque les propriétés du qubit (soit T1, T2 ou la fréquence) sont manquantes a été corrigé. Les valeurs de propriété manquantes dans QubitProperties sont remplies par None.

  • BasePassManager.run() ne laissera plus échapper l'ancien PropertySet dans les nouveaux flux de travail lorsqu'elle est appelée plusieurs fois. Auparavant, les mêmes PropertySet que précédemment était utilisée pour initialiser les exécutions suivantes, ce qui pouvait signifier que des informations non valides sur les propriétés étaient communiquées aux tâches. Le comportement correspond désormais à celui de Qiskit 0.44. Correction #11784.

  • Pauli.evolve() gère désormais correctement les circuits quantiques contenant des portes ECR. Auparavant, ils n'étaient pas reconnus comme des portes Clifford, et une erreur a été soulevée.

  • Correction d'un bug dans Pauli.evolve() où l'évolution par un circuit dont le nom correspondait à certaines portes de Clifford ('cx', 'cz', etc) faisait évoluer le Pauli en fonction du nom du circuit, et non en fonction du contenu du circuit. Ce bogue ne s'est produit qu'avec l'option par défaut frame='s'.

  • Correction d'un problème de performance dans la fonction qpy.load() lors de la désérialisation de charges utiles QPY avec un grand nombre de qubits ou de clbits dans un circuit.

  • Correction d'un bug dans la gestion de l'argument default_alignment de la commande build(). Les entrées de type AlignmentKind sont désormais correctement traitées comme des alignements par défaut.

  • Correction d'un bogue dans la fonction qiskit.pulse.utils.format_parameter_value() qui convertissait involontairement des nombres entiers suffisamment grands en valeurs flottantes ou provoquait des arrondis inattendus. Voir #11971 pour plus de détails.

  • Correction d'un problème dans la classe QDrift où les coefficients de l'hamiltonien étaient auparavant forcés d'être positifs en prenant la valeur absolue de chaque coefficient. Cette erreur a été corrigée de manière à ce que les signes des coefficients négatifs soient rajoutés.

  • Un bogue a été corrigé dans convert_durations_to_dt() où la fonction appliquait aveuglément une conversion de secondes à dt sur les durées de circuit, indépendamment des unités originales de l'attribut. Cela pourrait conduire à des ordres de grandeur erronés dans les durées de circuit rapportées.

  • Corrigé SparsePauliOp.apply_layout() pour qu'il fonctionne correctement avec les opérateurs zéro-qubit. Par exemple, si vous avez créé un qubit 0 et que vous avez appliqué une disposition du type :

    op = SparsePauliOp("")
    op.apply_layout(None, 3)

    ce qui aurait auparavant provoqué une erreur. Cela renverra correctement un opérateur de la forme : SparsePauliOp(['III'], coeffs=[1.+0.j])

  • Correction d'un oubli dans la passe Commuting2qGateRouter où les permutations qreg n'étaient pas ajoutées à l'ensemble des propriétés de la passe, de sorte qu'elles devaient être suivies manuellement par l'utilisateur. Il est désormais possible d'accéder à la permutation par le biais de la propriété layout du circuit de sortie et d'insérer la passe dans n'importe quel pipeline de transpilation sans perte d'informations.

  • Correction d'une imprécision en virgule flottante lors de la mise à l'échelle de certaines unités d'impulsion entre les secondes et les nanosecondes. Si l'impulsion était définie symboliquement, une erreur inutile en virgule flottante pourrait être introduite par la mise à l'échelle pour certaines constructions de symengine, ce qui pourrait se traduire par des résultats inattendus une fois que les symboles sont entièrement liés. Correction #12392.

  • Les gestionnaires de passage prédéfinis de transpile() n'échoueront plus sur les circuits avec flux de contrôle, si aucune cible matérielle ou aucun ensemble de portes de base n'est spécifié. Ils traiteront désormais ces cibles abstraites comme autorisant toutes les opérations de flux de contrôle. Correction #11906.

  • La méthode qiskit.instruction.Instruction.soft_compare() a pour but de comparer si deux portes correspondent dans leur nom, leur nombre de qubits, leur nombre de clbits et leur nombre de paramètres. Cependant, il y avait une faute de frappe qui empêchait de vérifier le nombre de qubits et le nombre de clbits pour une correspondance. Cela résout l'apparente coquille.

  • Le plugin par défaut init ne soulevait pas correctement une erreur de type TranspilerError lorsqu'il était appelé avec un niveau d'optimisation invalide.

  • Correction d'un problème avec la méthode Operator.from_circuit() qui interprétait de manière incorrecte la permutation finale de la disposition, ce qui entraînait la construction d'un fichier Operator invalide. Auparavant, la disposition finale était traitée sans tenir compte de la disposition initiale, c'est-à-dire que l'initialisation était incorrecte pour tous les circuits quantiques dont la disposition initiale n'était pas triviale.

  • Correction d'un problème de performance dans PassManager.run() lorsqu'il fonctionne sur plusieurs circuits en parallèle. Il ne passera plus de temps à sérialiser le PassManager (ce qui est une condition de l'exécution parallèle) lorsqu'il reçoit des entrées multiples s'il ne va traiter les entrées que de manière sérielle.

  • Parameter a été mis à jour de manière à ce que les instances qui se comparent entre elles aient toujours le même hachage. Auparavant, seul le Parameter.uuid était comparée, de sorte que les instances Parameter avec des noms différents pouvaient être comparées entre elles si elles avaient été construites en utilisant une valeur commune pour le paramètre uuid (qui n'est généralement pas transmis explicitement).

  • Correction d'un bug dans plot_coupling_map() qui provoquait une coloration incorrecte des bords de la carte de couplage. Correction #12369.

  • L'analyseur OpenQASM 2.0 (qasm2.load() et qasm2.loads()) peut maintenant évaluer les expressions gate-angle comprenant des opérandes entiers qui déborderaient de l'entier de taille système. Ceux-ci seront évalués dans un contexte de virgule flottante en double précision, comme le reste de l'expression l'a toujours été. Toutefois, un nombre entier arbitrairement grand ne sera pas nécessairement représentable avec exactitude en virgule flottante double précision, de sorte qu'il est possible que, quelle que soit la manière dont le circuit a été généré, il ait déjà perdu toute précision numérique modulo 2π2\pi.

  • Parameter les instances utilisées comme substituts des variables input dans les programmes OpenQASM 3 verront désormais leur nom échappé afin d'éviter les collisions avec les portes intégrées lors de l'exportation vers OpenQASM 3. Auparavant, il pouvait y avoir un conflit d'appellation et l'exportateur générait une version invalide de OpenQASM 3.

  • Correction d'un bogue dans QuantumCircuit.draw() qui entraînait la modification des dictionnaires de styles personnalisés pour le tiroir Matplotlib lors de l'exécution.

  • QuantumCircuit.append() avec copy=True (sa valeur par défaut) copiera désormais correctement les instructions paramétrées par des ParameterExpression et non plus seulement par des instances Parameter instances.

  • Le traitement interne des étalonnages de circuits personnalisés et des InstructionDurations a été déchargé de la fonction transpile() aux différentes passes du transpondeur : DynamicalDecoupling, DynamicalDecoupling. Auparavant, les durées d'instruction des calibrages de circuits n'étaient pas prises en compte à moins qu'elles ne soient incorporées manuellement dans l'argument d'entrée instruction_durations, mais les passes qui en ont besoin analysent désormais le circuit et choisissent la valeur de durée la plus pertinente selon l'ordre de priorité suivant : cible > entrée personnalisée > calibrages de circuits.

  • Correction d'un bogue dans transpile() où l'argument num_processes n'était utilisé que si dt ou instruction_durations était fourni.

Autres remarques


1.0.0rc1

Notes de mise à niveau des fournisseurs

  • Le module qiskit.providers.fake_provider a été migré vers le paquet qiskit-ibm-runtime Python. Pour cette raison, les éléments suivants de la section qiskit.providers.fake_provider ont été supprimés à la suite de leur dépréciation dans Qiskit 0.46:

    • qiskit.providers.fake_provider.FakeProvider
    • qiskit.providers.fake_provider.FakeProviderForBackendV2
    • qiskit.providers.fake_provider.FakeProviderFactory
    • qiskit.providers.fake_provider.fake_backends.FakeBackendV2
    • tout faux backend contenu dans qiskit.providers.fake_provider.backends (accessible via le fournisseur)
    • qiskit.providers.fake_provider.FakeQasmSimulator
    • qiskit.providers.fake_provider.FakeJob
    • qiskit.providers.fake_provider.FakeQobj

    Pour utiliser le nouveau module "fake provider", vous pouvez lancer pip install qiskit-ibm-runtime et remplacer le chemin d'importation de qiskit (qiskit.providers.fake_provider) par le nouveau chemin d'importation (qiskit_ibm_runtime.fake_provider). Exemple de migration :

    # Legacy path
    from qiskit.providers.fake_provider import FakeProvider, FakeSherbrooke
    backend1 = FakeProvider().get_backend("fake_ourense")
    backend2 = FakeSherbrooke()
    
    # New path
    # run "pip install qiskit-ibm-runtime"
    from qiskit_ibm_runtime.fake_provider import FakeProvider, FakeSherbrooke
    backend1 = FakeProvider().get_backend("fake_ourense")
    backend2 = FakeSherbrooke()

    En outre, les faux backends suivants, conçus à des fins de test spéciales, ont été remplacés par la nouvelle classe GenericBackendV2 et sont également supprimés suite à leur dépréciation dans Qiskit 0.46:

    • qiskit.providers.fake_provider.fake_backend_v2.FakeBackendV2
    • `qiskit.providers.fake_provider.fake_backend_v2.FakeBackendV2LegacyQubitProps
    • qiskit.providers.fake_provider.fake_backend_v2.FakeBackend5QV2
    • qiskit.providers.fake_provider.fake_backend_v2.FakeBackendSimple

    Exemple de migration vers la nouvelle GenericBackendV2 classe :

    # Legacy path
    from qiskit.providers.fake_provider import FakeBackend5QV2
    backend = FakeBackend5QV2()
    
    # New path
    from qiskit.providers.fake_provider import GenericBackendV2
    backend = GenericBackendV2(num_qubits=5)
    # note that this class will generate 5q backend with generic
    # properties that serves the same purpose as FakeBackend5QV2
    # but will generate different results
Cette page a-t-elle été utile ?
Signaler un bogue, une coquille ou proposer du contenu sur GitHub.