Skip to main content
IBM Quantum Platform

Notes de publication de Qiskit 0.45

Cette page contient les notes de version de Qiskit 0.45, la première version après la suppression complète de l'ancienne structure "elements". Pour toutes les notes de version, y compris celles qui remontent à l'ancienne structure "méta-package" de Qiskit, voir Notes de version. Pour un tableau des versions du méta-paquet, voir les notes de mise à jour de Qiskit 0.44.


0.45.3

Prélude

Qiskit 0.45.3 est une version ponctuelle sans aucun changement de code, si ce n'est qu'il soulève une erreur d'installation si il détecte qu'il a été installé dans un environnement invalide ImportError s'il détecte qu'il a été installé dans un environnement invalide avec Qiskit >= 1.0.

Veuillez lire notre guide de migration sur le nouvel emballage pour obtenir de l'aide sur les erreurs, la préparation de Qiskit 1.0, et des informations plus détaillées.

Remarque

La sortie de Qiskit 1.0 est prévue environ deux semaines après celle de Qiskit 0.45.3, le 15 février 2024, et pourrait ne pas être encore disponible au moment où vous lisez ce message. Ce changement est effectué de manière proactive.

La structure d'emballage de Qiskit est en train de changer dans Qiskit 1.0, et malheureusement les nouvelles exigences ne peuvent pas être entièrement communiquées à pip, surtout si les commandes pip install --upgrade sont exécutées après que l'environnement a été initialement configuré. Toutes les versions de Qiskit antérieures à 1.0 (y compris celle-ci) ont un conflit d'installation avec Qiskit 1.0 que pip ne résoudra pas.

Si import qiskit soulève un ImportError pour vous, votre environnement est dans un état invalide, et les versions de Qiskit 0.45/0.46 et 1.0 sont toutes deux accessibles, ce qui se traduira par un code subtilement cassé. Vous devrez créer un nouvel environnement virtuel et vous assurer qu'une seule des deux versions est installée. En particulier, si vous avez l'intention d'installer Qiskit 1.0, aucun paquet dépendant de qiskit-terra ne doit être installé; ces paquets sont incompatibles avec Qiskit 1.0 et doivent être mis à jour. Si vous avez l'intention d'installer Qiskit 0.45 ou 0.46, vous devez vous assurer que vous n'avez pas essayé d'installer qiskit>=1.0.

Si vous développez une bibliothèque basée sur Qiskit et que vous avez encore une dépendance sur qiskit-terra, vous devez publier d'urgence un nouveau paquetage qui ne dépend que de qiskit. Depuis la version 0.44, le paquet qiskit ne contient que le noyau du compilateur qiskit-terra (le composant qui est maintenant simplement appelé "Qiskit"), donc si votre version minimale est 0.44, vous pouvez en toute sécurité passer d'une dépendance qiskit-terra>=0.44 à qiskit>=0.44 sans changement dans ce qui sera installé. Pour plus de détails et de recommandations sur les tests et la préparation, voir la section du guide de migration destinée aux développeurs.


0.45.2

Prélude

Qiskit 0.45.2 est un petit patch qui corrige plusieurs bugs trouvés dans la série de versions 0.45.

Corrections des erreurs

  • Appel copy() ou copy_empty_like() sur un site BlueprintCircuit propage désormais correctement la mention global_phase à la copie. Auparavant, la phase globale était toujours nulle après la copie.

  • QPY (en utilisant qpy.dump() et qpy.load()) sérialisera et désérialisera désormais correctement les circuits quantiques avec des opérateurs de Clifford (Clifford).

  • Correction d'un problème dans le tiroir du circuit mpl où le texte s'imprimait au-delà de la fin de la case pour un SwitchCaseOp si la case par défaut était vide.

  • La diffusion de l'argument qubit de QuantumCircuit.delay() produit maintenant correctement des instructions individuelles Delay pour chaque qubit, comme prévu. Auparavant, lorsqu'on lui donnait certains itérables (tels que sets), il produisait silencieusement un circuit invalide qui pouvait échouer dans des endroits inhabituels.

  • Correction d'un bogue qui entraînait une erreur lorsqu'un utilisateur essayait de charger les données d'étalonnage d'une porte en Target dans une situation particulière. Cela se produit lorsque le backend ne communique que des données d'étalonnage partielles, par exemple en faisant référence à une impulsion de forme d'onde dans une définition de commande mais sans inclure cette impulsion de forme d'onde dans la bibliothèque d'impulsions. Dans cette situation, l'objet d'impulsion Qiskit ne peut pas être construit, ce qui entraîne l'échec de la construction de l'horaire d'impulsion pour l'étalonnage. Désormais, lorsque les données d'étalonnage sont incomplètes, le Target considère que cela équivaut à ne pas signaler d'étalonnage du tout et ne soulève pas d'exception.

  • Correction d'un problème avec la passe Optimize1qGatesDecomposition où il pouvait potentiellement resynthétiser une seule porte idéale (ce qui signifie que le taux d'erreur est de 0.0), ce qui était présent dans le fichier Target. Ceci est maintenant corrigé de telle sorte que le laissez-passer Optimize1qGatesDecomposition se reportera sur la porte du circuit si le taux d'erreur (qui inclut le nombre de portes) est le même. Corrigé #10568

  • Correction d'un problème avec la passe OptimizeSwapBeforeMeasure qui optimisait incorrectement les circuits impliquant des instructions d'échange et de mesure. Ce commit corrige le bogue en changeant DAGCircuit.successors() en DAGCircuit.descendants(). J'ai également ajouté quelques tests supplémentaires pour m'assurer que le bogue est corrigé. Par exemple :

    from qiskit import QuantumCircuit
    from qiskit.transpiler.passes import OptimizeSwapBeforeMeasure
    pass_ = OptimizeSwapBeforeMeasure()
    qc = QuantumCircuit(2, 1)
    qc.swap(0, 1)
    qc.measure(0, 0)
    qc.measure(0, 0)
    print(qc.draw())
    print(pass_(qc).draw())

    s'imprimerait auparavant :

            ┌─┐┌─┐
    q_0: ─X─┤M├┤M├
          │ └╥┘└╥┘
    q_1: ─X──╫──╫─
             ║  ║
    c: 1/════╩══╩═
             0  0
         ┌─┐
    q_0: ┤M├───
         └╥┘┌─┐
    q_1: ─╫─┤M├
          ║ └╥┘
    c: 1/═╩══╩═
          0  0

    et maintenant le deuxième circuit est correctement optimisé pour :

    q_0: ──────
         ┌─┐┌─┐
    q_1: ┤M├┤M├
         └╥┘└╥┘
    c: 1/═╩══╩═
          0  0
  • Correction d'un bug dans la représentation des StabilizerState dans la représentation des chaînes de caractères.


0.45.1

Prélude

Qiskit Terra 0.45.1 est un petit patch qui corrige plusieurs bugs trouvés dans la série de versions 0.45. Il s'agit également de la première version à prendre officiellement en charge Python 3.12. La version 0.45.1 prend en charge Python 3.8, 3.9, 3.10, 3.11, et 3.12.

Nouvelles fonctions

  • Ajout d'un support pour l'utilisation de Qiskit avec Python 3.12. Depuis cette version, Qiskit fonctionne avec les versions Python, 3.8, 3.9, 3.10, 3.11 et 3.12.

Corrections des erreurs

  • QuantumCircuit.barrier() produira désormais une sortie correcte lorsqu'il recevra un set comme l'une de ses entrées. Auparavant, il ajoutait une opération non valide au circuit, même si, dans la pratique, cela ne posait généralement pas de problèmes observables. Corrigé #11208

  • La propriété Instruction.condition_bits gère désormais correctement les expressions classiques d'exécution (qiskit.circuit.classical).

  • Correction de la hash() des objets Qiskit Pulse Channel (tels que DriveChannel) dans les cas où le canal a été transféré d'un processus Python à un autre qui utilise une graine de hachage différente.

  • Les portes personnalisées conditionnées importées de OpenQASM 2 conservent désormais correctement leurs conditions lorsqu'elles sont décapées et copiées en profondeur. Auparavant, toute porte personnalisée conditionnelle (définie par une instruction gate dans un fichier OpenQASM 2) perdait sa condition lorsqu'elle était copiée ou décapée.

  • Correction de la désérialisation QPY des éléments StatePreparation et Initialize avec des paramètres de type chaîne et entier (par opposition à un vecteur d'état explicite, ce qui fonctionnait déjà). Correction #11158.

  • Correction d'un bug dans SabreLayout qui ne parvenait pas à ajouter les informations relatives au registre à l'objet Layout utilisé pour TranspileLayout.initial_layout. Cette visualisation du circuit affecté avec QuantumCircuit.draw() et circuit_drawer() après transpilation, qui affichait un label de qubit virtuel de la forme Qubit[QuantumRegister(6, 'q', 0)] au lieu du label de qubit virtuel attendu utilisant le nom du registre (par exemple q0). Corrigé #11038

  • Correction d'un problème avec qpy.dump() qui faisait que la fonction pouvait potentiellement ignorer la valeur de use_symengine lors de la sérialisation d'un objet ScheduleBlock objet. Cela entraînerait la génération d'une charge utile QPY invalide, car elle indiquerait qu'elle utilise symengine pour les expressions symboliques, mais contiendrait en réalité des données sérialisées sympy.

  • Correction d'un bogue qui provoquait une erreur de UnitaryOverlap une erreur lors de l'initialisation si un circuit d'entrée contenant une barrière lui était attribué.


0.45.0

Prélude

Qiskit 0.45.0 est la dernière version avant 1.0. Elle prépare le terrain pour les modifications de l'API que nous prévoyons pour notre première version majeure, y compris de nombreuses suppressions de fonctionnalités précédemment dépréciées ainsi qu'une série de nouvelles dépréciations.

Remarque

Si votre projet dépend de Qiskit, il peut s'appuyer sur des fonctionnalités qui ne seront plus prises en charge dans Qiskit 1.0. Pour cette raison, nous vous recommandons de plafonner de manière proactive votre version prise en charge à <1.0.

Voici quelques caractéristiques de Qiskit 0.45.0 :

  • À partir de cette version, toutes les portes non paramétrées de la bibliothèque de circuits standard de Qiskit sont désormais des singletons. Par défaut, ces portes partagent une seule instance en mémoire, de sorte qu'une fois qu'une porte d'un type spécifique, disons XGateest instanciée, toutes les instances suivantes de XGate sera une référence à la première. Il en résulte une réduction de l'utilisation de la mémoire et des coûts de construction lors de l'utilisation de plusieurs portes du même type dans un circuit. Pour réaliser cette fonctionnalité, de nouvelles classes de base ont été introduites : SingletonInstruction et SingletonGate. Voir les notes de caractéristiques pour plus de détails.
  • Nous avons ajouté une nouvelle interface générique de gestion des laissez-passer qui se trouve dans le nouveau module qiskit.passmanager module. Il s'agit d'une généralisation du gestionnaire de passe qui a été utilisé pour construire le transpileur Qiskit, et il introduit un cadre générique pour permettre aux utilisateurs de créer de nouveaux gestionnaires de passe qui utilisent différentes représentations intermédiaires (RI). Le module comprend une classe de base générique de gestionnaire de passe, des contrôleurs de flux et l'infrastructure nécessaire pour gérer l'exécution des tâches du gestionnaire de passe. La nouvelle interface a été utilisée pour reconstruire le gestionnaire de passe existant dans le module qiskit.transpiler ce qui a permis d'éliminer la dette technique dans le code et d'améliorer la convivialité et les performances. Voir les notes sur les fonctionnalités et les mises à jour pour plus de détails.
  • 0.45.0 permet aux utilisateurs d'interagir plus facilement avec les permutations de mise en page effectuées par le transpileur. Les données contenues dans la classe TranspileLayout sont désormais plus accessibles grâce à une série de nouvelles méthodes et de nouveaux attributs. Et une nouvelle SparsePauliOp.apply_layout() permet d'appliquer une permutation spécifique à un observable construit pour un circuit d'entrée du transpileur SparsePauliOp observable qui a été construit pour un circuit d'entrée du transpileur. Voir les notes de caractéristiques pour plus de détails.
  • Enfin, nous avons introduit des opérations annotées avec la nouvelle classe AnnotatedOperation qui permet de formuler des instructions de circuits complexes sous la forme d'une instruction de base accompagnée d'un ensemble de modificateurs. Par exemple, au lieu d'un type d'opération spécifique qui met en œuvre l'inverse contrôlé de a RXGatenous pouvons maintenant utiliser un type d'opération annoté RXGate annoté avec les attributs inverse et contrôle. Voir les notes de caractéristiques pour plus de détails.

Caractéristiques des circuits

  • Ajout d'une nouvelle classe AnnotatedOperation qui est une sous-classe de Operation et qui représente une "opération de base" modifiée par une liste de "modificateurs". L'opération de base est de type Operation et les modificateurs actuellement pris en charge sont de type InverseModifier, ControlModifier et PowerModifier. Les modificateurs sont appliqués dans l'ordre où ils apparaissent dans la liste.

    Exemple :

    gate = AnnotatedOperation(
      base_op=SGate(),
      modifiers=[
          InverseModifier(),
          ControlModifier(1),
          InverseModifier(),
          PowerModifier(2),
      ],
    )

    est logiquement équivalent à gate = SGate().inverse().control(1).inverse().power(2), ou à :

    gate = AnnotatedOperation(
      AnnotatedOperation(SGate(), [InverseModifier(), ControlModifier(1)]),
      [InverseModifier(), PowerModifier(2)],
    )

    Cependant, cette équivalence n'est que logique, les représentations internes étant très différentes.

    Par commodité, un seul modificateur peut également être transmis directement, de sorte que AnnotatedGate(SGate(), [ControlModifier(1)]) est équivalent à AnnotatedGate(SGate(), ControlModifier(1)).

    Une opération annotée se distingue par le fait que la définition du circuit n'est pas construite lorsque l'opération est déclarée, mais qu'elle n'intervient que lors de la transpilation, en particulier lors du passage du HighLevelSynthesis passage du transpileur.

    Une opération annotée peut également être considérée comme un objet "de niveau supérieur" ou "plus abstrait" qui peut être ajouté à un circuit quantique. Cela permet d'écrire des passes d'optimisation du transpondeur qui utilisent cette représentation de niveau supérieur, par exemple en supprimant une porte qui est immédiatement suivie de son inverse (notez que cette réduction peut ne pas être possible si la porte et son inverse sont d'abord synthétisés dans des portes plus simples).

    Dans un sens, une opération annotée peut être considérée comme une extension de ControlledGatequi permet également d'ajouter un contrôle à l'opération de base. À l'avenir, nous prévoyons de remplacer ControlledGate par AnnotatedOperation. Comme pour les portes contrôlées, le transpileur synthétise les opérations annotées avant la mise en page/l'acheminement.

    Pour l'instant, les opérations annotées ne peuvent apparaître qu'au niveau supérieur d'un circuit quantique, c'est-à-dire qu'elles ne peuvent pas apparaître à l'intérieur du circuit definition défini de manière récursive. Nous prévoyons de supprimer cette limitation ultérieurement.

  • Ajout d'une nouvelle option max_num_qubits à qiskit.circuit.CommutationChecker.commute() qui spécifie le nombre maximum de qubits à prendre en compte pour la vérification de la commutativité basée sur la multiplication des matrices, plus coûteuse. Cela évite d'essayer d'allouer en interne des tableaux de taille 2N×2N2^N \times 2^N. Des versions plus simples de la vérification de la commutativité (par exemple, deux opérations quantiques commutent lorsqu'elles portent sur des ensembles disjoints de qubits) continuent de fonctionner sans cette limite.

  • Ajout d'un nouvel argument, check_input, au constructeur de la classe UnitaryGate classe. Ce drapeau est utilisé pour désactiver les contrôles d'initialisation par défaut selon lesquels l'objet d'entrée représente une matrice unitaire. Ceci peut être utilisé pour accélérer la création d'objets si vous savez que l'entrée est déjà une matrice unitaire UnitaryGate si vous savez que l'entrée est déjà une matrice unitaire. Cette nouvelle option ne doit être utilisée que dans ces cas, car si elle est réglée sur False et que l'entrée n'est pas unitaire, il en résultera un objet UnitaryGate invalide.

  • Une nouvelle méthode Parameter.assign() a été ajoutée. Cette méthode sert principalement de moyen rapide d'améliorer les performances de QuantumCircuit.assign_parameters() pour le cas courant des circuits qui contiennent principalement des "expressions" qui ne sont en fait que des paramètres simples à assigner ultérieurement.

  • Les performances de QuantumCircuit.assign_parameters() lors de l'affectation d'un seul paramètre d'un circuit qui en comporte plusieurs a été améliorée.

  • Introduction de deux nouvelles classes, SingletonInstruction et SingletonGatequi sont des sous-classes de Instruction et Gate respectivement, qui utilisent une instance unique pour tous les objets de ce type. L'objectif de cette classe est de minimiser la mémoire et les coûts de construction liés à l'utilisation de plusieurs portes dans un circuit, en contrepartie d'un état global partagé. C'est pourquoi cette classe n'est applicable qu'aux portes qui n'ont pas d'état unique et/ou mutable stocké dans une instance. Par exemple, le meilleur exemple est XGate ne contient pas d'état et pourrait tirer parti de SingletonGate (et le fait à partir de cette version), alors que RXGate stocke un paramètre d'angle dans une instance et ne peut donc pas utiliser SingletonGate car une seule instance globale partagée ne peut pas représenter les valeurs des paramètres.

    L'autre problème potentiel à prendre en compte lors de l'utilisation de classes singleton est que le Instruction prend en charge certains états mutables. Plus précisément, les label, duration, unit, et condition sont tous accessibles et mutables dans la classe Instruction et ses sous-classes directes. Toutefois, cela est incompatible avec l'utilisation d'un objet partagé via la fonction SingletonInstruction. Pour les instances de SingletonInstructionla définition directe de ces attributs n'est pas autorisée et soulèvera une exception. Si elles sont nécessaires pour une instance particulière, vous devez vous assurer d'avoir une instance mutable en utilisant Instruction.to_mutable() (ou utiliser Instruction.c_if() pour condition). label, duration et unit peuvent également être donnés comme arguments de mot-clé lors de la construction de la classe.

  • Les portes suivantes de la bibliothèque standard sont maintenant des instances de SingletonGate:

    Cela signifie que si ces classes sont instanciées en tant que (par exemple) XGate() en utilisant toutes les valeurs par défaut du constructeur, ils partageront tous une seule instance globale. Il en résulte une forte réduction de la charge de mémoire pour > 1 objet de ces types et un temps de construction d'objet nettement plus rapide.

  • Introduction d'une nouvelle classe SingletonControlledGate qui est une sous-classe de ControlledGate qui utilise une instance unique pour tous les objets de ce type. L'objectif de cette classe est de minimiser la mémoire et les coûts de construction liés à l'utilisation de plusieurs portes dans un circuit, en contrepartie d'un état global partagé. C'est pourquoi cette classe n'est applicable qu'aux portes qui n'ont pas d'état unique et/ou mutable stocké dans une instance. Par exemple, un CXGate ne contient pas d'état et peut donc utiliser l'effet de levier de SingletonControlledGate (et le fait à partir de cette version). En revanche, CRXGate stocke un paramètre d'angle dans ses données d'instance et ne peut donc pas utiliser la fonction SingletonControlledGate.

    L'autre problème potentiel à prendre en compte lors de l'utilisation de SingletonControlledGate est que le modèle de données original de ControlledGate supporte la mutation. Plus précisément, les label, duration, unit, condition, et ctrl_state sont tous accessibles et mutables dans la base de données ControlledGatemais la mutation de ces attributs dans les sous-classes de SingletonControlledGate n'est pas autorisée et soulèvera une exception. Ces attributs peuvent être personnalisés, mais uniquement au moment de la création (c'est-à-dire via le constructeur). Dans ce cas, la porte nouvellement construite sera une instance distincte avec l'état personnalisé au lieu de l'instance globalement partagée. Vous pouvez également utiliser la méthode SingletonControlledGate.to_mutable() pour obtenir une copie mutable d'un objet gate et en modifier les attributs comme vous le feriez pour n'importe quel autre objet Instruction objet.

  • Les portes suivantes de la bibliothèque standard sont maintenant des instances de SingletonControlledGate:

    Cela signifie qu'à moins qu'une instance label, condition, duration, unit, ou ctrl_state ne soit définie au moment de la création, elle partagera une seule instance globale chaque fois qu'un nouvel objet gate sera créé. Il en résulte une forte réduction de la charge de mémoire pour > 1 objet de ces types.

  • Ajout d'une nouvelle méthode Instruction.to_mutable() et un attribut Instruction.mutable qui permettent d'obtenir une copie mutable et de vérifier si un objet Instruction est mutable. Avec l'introduction de SingletonGate ces méthodes peuvent être utilisées pour disposer d'une interface unifiée permettant de gérer la mutabilité des objets d'instruction.

  • Ajout d'un attribut Instruction.base_classqui permet d'obtenir le type "de base" d'une instruction. De nombreuses instructions satisferont type(obj) == obj.base_class, mais les instances uniques de SingletonInstruction et SingletonGate sont des sous-classes de leur type de base. Vous pouvez utiliser l'attribut new base_class pour trouver la classe de base de ces derniers. Voir la documentation sur les attributs pour savoir quand d'autres sous-classes peuvent modifier leur attribut base_classet ce que cela signifie pour l'exécution.

  • Ajout du circuit UnitaryOverlap à la bibliothèque de circuits Qiskit. Il peut être utilisé pour calculer la fidélité des états générés par les unitaires en examinant la probabilité de la distribution de sortie dans l'état tout-zéro ou, de manière équivalente, en calculant la valeur de l'espérance du projecteur sur l'état tout-zéro. Ceci est utile dans des applications telles que l'apprentissage automatique et le calcul des états excités en chimie quantique, pour n'en citer que quelques-unes.

Fonctionnalités Pulse

  • Activation de l'ordonnancement circuit-impulsion à l'aide de BackendV2.

    # import a fake backend which is a sub-class of BackendV2
    from qiskit.providers.fake_provider import FakePerth
    from qiskit.compiler.scheduler import schedule
    from qiskit.circuit import QuantumCircuit
    
    qc = QuantumCircuit(1, 1)
    qc.x(0)
    qc.measure(0,0)
    sched = schedule(circuits=qc, backend=FakePerth())

    Étant donné que BackendV2 n'est pas pris en charge par la fonction schedule() cela provoquait une erreur de la méthode schedule() lorsque l'argument backend était fourni avec une instance de BackendV2. Pour plus d'informations, voir le numéro 10837.

OpenQASM Caractéristiques

  • Le module OpenQASM 2 qiskit.qasm2 a obtenu les fonctions d'exportation dump() et dumps(). Elles sont utilisées de manière très similaire aux précédentes QuantumCircuit.qasm():

    from qiskit import qasm2, QuantumCircuit
    qc = QuantumCircuit(2, 2)
    qc.h(0)
    qc.cx(0, 1)
    qc.measure([0, 1], [0, 1])
    print(qasm2.dumps(qc))

    Les nouvelles fonctions proviennent du même code que QuantumCircuit.qasm()qui sera progressivement supprimé et remplacé par les nouveaux chemins, afin de fournir une interface plus cohérente par rapport aux sites OpenQASM 3 (qiskit.qasm3) et QPY (qiskit.qpy). C'est d'autant plus important que le nom de la méthode qasm() ne donne aucune indication sur la version de OpenQASM, et que depuis son ajout initial, Qiskit a gagné plusieurs modules de sérialisation qui pourraient facilement être confondus.

Caractéristiques du QPY

  • QPY prend désormais en charge l'utilisation de la sérialisation et de la désérialisation natives de Symengine pour les objets de type ParameterExpression ainsi que les expressions symboliques dans les blocs de planification Pulse. Il s'agit d'une alternative de sérialisation plus rapide, mais qui n'est pas prise en charge par toutes les plateformes. Veuillez vérifier que votre plateforme cible est supportée par la bibliothèque symengine avant de définir cette option, car qpy en aura besoin pour désérialiser la charge utile.

    Cette fonction peut être activée par le biais du paramètre use_symengine dans qpy.dump():

    from qiskit.circuit import QuantumCircuit, Parameter
    from qiskit import qpy
    
    theta = Parameter("theta")
    phi = Parameter("phi")
    sum_param = theta + phi
    
    qc = QuantumCircuit(1)
    qc.rz(sum_param, 0)
    qc.measure_all()
    
    with open('bell.qpy', 'wb') as fd:
        qpy.dump(qc, fd, use_symengine=True)
    
    with open('bell.qpy', 'rb') as fd:
        new_qc = qpy.load(fd)[0]

Caractéristiques de l'information quantique

  • Ajouté Clifford.from_linear_function() et Clifford.from_permutation() qui créent un objet Clifford à partir de LinearFunction et de PermutationGate respectivement. En conséquence, un Clifford peut maintenant être construit directement à partir de a LinearFunction, a PermutationGateou d'un circuit quantique contenant de telles portes.

  • La classe Operator dispose désormais d'une méthode draw() qui permet de l'afficher sous forme de matrice de texte, d'objet IPython LaTeX ou de source LaTeX. Le type de dessin par défaut est toujours l'ASCII __repr__ de l'opérateur.

  • Ajout d'une nouvelle méthode, apply_layout()à la classe SparsePauliOp classe. Cette méthode est utilisée pour appliquer une TranspileLayout du transpileur à un observable SparsePauliOp observable qui a été construit pour un circuit d'entrée du transpileur. Cela permet de travailler plus facilement avec les BaseEstimator et la transposition locale. Par exemple :

    from qiskit.circuit.library import RealAmplitudes
    from qiskit.quantum_info import SparsePauliOp
    from qiskit.primitives import BackendEstimator
    from qiskit.compiler import transpile
    from qiskit.providers.fake_provider import FakeNairobiV2
    
    psi = RealAmplitudes(num_qubits=2, reps=2)
    H1 = SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)])
    backend = FakeNairobiV2()
    estimator = BackendEstimator(backend=backend, skip_transpilation=True)
    
    thetas = [0, 1, 1, 2, 3, 5]
    transpiled_psi = transpile(psi, backend, optimization_level=3)
    permuted_op = H1.apply_layout(transpiled_psi.layout)
    res = estimator.run(transpiled_psi, permuted_op, thetas)

    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 en utilisant la fonction apply_layout() pour refléter les transformations effectuées par transpile().

Fonctionnalités du transpilateur

  • La classe HighLevelSynthesis est étendue pour synthétiser des circuits avec des objets de type AnnotatedOperation.

  • Un nouveau module qiskit.passmanager a été ajouté à la bibliothèque Qiskit. Ce module met en œuvre un gestionnaire de passe générique et des contrôleurs de flux, et fournit une infrastructure pour gérer l'exécution des tâches du gestionnaire de passe. Le module fournit des classes de base pour les passes (GenericPass) et les contrôleurs de flux (BaseController), ainsi qu'une nouvelle classe d'interface, passmanager.Task, pour gérer l'exécution du gestionnaire de passes (voir la méthode Task.execute() ). Ces nouvelles classes suivent le modèle composite, car les contrôleurs de flux sont des collections de passes, et un contrôleur peut être imbriqué de manière récursive dans le pipeline de tâches. Il convient également de noter que les classes de base ne connaissent pas les types d'objets d'entrée et de sortie et qu'elles doivent être sous-classées pour optimiser un type de programme particulier. Cette conception unifiée réduit la complexité du gestionnaire de passes conventionnel et ne nécessite plus l'utilisation de classes telles que RunningPassManager pour gérer la répartition de la logique d'exécution et la renormalisation de la structure des tâches. Le module qiskit.transpiler a été réorganisé pour reconstruire les gestionnaires de passe existants sur la base du gestionnaire de passe générique. Voir les notes de mise à jour pour plus de détails.

  • Ajout d'une nouvelle passe d'analyse SabrePreLayout qui crée un modèle de départ pour SabreLayouten écrivant la disposition dans la valeur de l'ensemble de propriétés sabre_starting_layouts.

    La passe fonctionne en augmentant la carte de couplage avec de plus en plus d'arêtes "supplémentaires" jusqu'à ce que l'on parvienne à trouver un isomorphisme parfait du graphe VF2Layout réussisse à trouver un isomorphisme graphique parfait. Plus précisément, la carte de couplage augmentée contient des arêtes entre les nœuds qui se trouvent à une distance donnée d dans la carte de couplage originale, et la valeur de d est augmentée jusqu'à ce qu'un isomorphisme soit trouvé. La passe minimise également, de manière optionnelle, le nombre d'arêtes supplémentaires impliquées dans le tracé jusqu'à ce qu'un minimum local soit trouvé. Il s'agit de supprimer les arêtes supplémentaires et d'appeler VF2Layout pour vérifier si un isomorphisme existe toujours.

    Voici un exemple d'appel de la fonction SabrePreLayout avant SabreLayout:

    import math
    from qiskit.transpiler import CouplingMap, PassManager
    from qiskit.circuit.library import EfficientSU2
    from qiskit.transpiler.passes import SabrePreLayout, SabreLayout
    
    qc = EfficientSU2(16, entanglement='circular', reps=6, flatten=True)
    qc.assign_parameters([math.pi / 2] * len(qc.parameters), inplace=True)
    qc.measure_all()
    
    coupling_map = CouplingMap.from_heavy_hex(7)
    
    pm = PassManager(
        [
            SabrePreLayout(coupling_map=coupling_map),
            SabreLayout(coupling_map),
        ]
    )
    
    pm.run(qc)
  • Ajout des arguments coupling_map, target et use_qubit_indices à la passe de HighLevelSynthesis transpiler pass. L'argument target spécifie le backend cible, permettant aux plugins de synthèse appelés dans la passe d'accéder à toutes les informations spécifiques à la cible, telles que la carte de couplage et le jeu de portes pris en charge. L'argument coupling_map ne spécifie que la carte de couplage et n'est utilisé que si target n'est pas spécifié. L'argument use_qubit_indices indique si la passe de synthèse de haut niveau est exécutée avant ou après l'établissement de la disposition, c'est-à-dire si les indices de qubits des objets de haut niveau correspondent aux indices de qubits sur le backend cible.

  • Ajout des arguments coupling_map, target et qubits à HighLevelSynthesisPlugin. L'argument positionnel target spécifie le backend cible, permettant au plugin d'accéder à toutes les informations spécifiques à la cible, telles que la carte de couplage, l'ensemble des portes supportées, etc. L'argument de position coupling_map ne spécifie que la carte de couplage et n'est utilisé que si target n'est pas spécifié. L'argument positionnel qubits spécifie la liste des qubits sur lesquels l'objet de niveau supérieur est défini, dans le cas où la synthèse est effectuée sur le circuit physique. La valeur None indique que la disposition n'a pas encore été choisie.

    Cela permet une séparation plus nette des options des plugins de synthèse en options d'interface générale pour les plugins (c'est-à-dire coupling_map, target, et qubits) et en options spécifiques aux plugins (un dictionnaire de configuration de forme libre spécifié via options). Si les options coupling_map, etc. ne sont pas explicitement ajoutées à la méthode run() du plugin, elles apparaîtront comme faisant partie de options.

  • Les DAGCircuit méthodes apply_operation_back() et apply_operation_front() ont gagné un argument de mot-clé check qui peut être défini à False pour ignorer la validation selon laquelle les entrées respectent les invariants de la structure des données DAGCircuit invariants de la structure des données. Cela permet d'optimiser les performances lorsque le DAG est construit à partir de données connues, par exemple lors des passages du transpilateur.

  • La méthode CouplingMap.reduce() accepte désormais un argument supplémentaire check_if_connected, qui est par défaut True. Cela correspond au comportement précédent, qui consiste à vérifier si la carte de couplage réduite reste connectée et à afficher CouplingError si ce n'est pas le cas. Lorsqu'elle est définie sur False, la vérification est ignorée, ce qui permet d'utiliser des cartes de couplage réduit déconnectées.

  • Le constructeur de HighLevelSynthesis transpiler pass accepte maintenant des arguments supplémentaires equivalence_library, basis_gates, et min_qubits. Cette passe peut désormais dérouler les définitions personnalisées de la même manière que la passe UnrollCustomDefinitionset, à ce titre, elle reprend complètement les fonctionnalités de cette dernière passe. En particulier, HighLevelSynthesis est désormais récursif, ce qui corrige un oubli dans l'implémentation initiale. Ainsi, lorsque target ou basis_gates sont spécifiés, HighLevelSynthesis synthétise récursivement tous les objets de haut niveau, les opérations annotées et les portes personnalisées du circuit, ne laissant que les portes supportées par la cible ou appartenant à la bibliothèque d'équivalence. Cela permet d'utiliser HighLevelSynthesis en remplacement de UnrollCustomDefinitions. En revanche, lorsque ni target ni basis_gates ne sont spécifiés, la passe ne synthétise que les objets de haut niveau et les opérations annotées de "premier niveau", c'est-à-dire qu'elle ne descend pas récursivement dans le champ custom gates definition . Ceci est rétrocompatible à la fois avec UnrollCustomDefinitions (qui ne ferait rien) et avec l'ancien comportement de la passe de synthèse de haut niveau, qui permet de l'utiliser comme transformation intermédiaire, en ne synthétisant que des objets de haut niveau comme spécifié par HLSConfig.

  • Amélioration significative des performances de la passe de MergeAdjacentBarriers qui reconstruisait le DAG complet pour fusionner les barrières.

  • Ajout d'un nouveau mot-clé, min_qubits, au constructeur de la passe de BasisTranslator transpiler pass. Lorsqu'il est fixé à une valeur non nulle, il est utilisé pour fixer un nombre minimum de qubits pour filtrer les opérations à traduire dans le circuit. Par exemple, si min_qubits=3 est défini, l'instance BasisTranslator ne traduira que les portes du circuit qui fonctionnent sur 3 qubits ou plus.

  • Ajout d'un nouveau mot-clé, min_qubits, au constructeur de la passe de UnrollCustomDefinitions transpiler pass. Lorsqu'il est fixé à une valeur non nulle, il est utilisé pour fixer un nombre minimum de qubits pour filtrer les opérations à traduire dans le circuit. Par exemple, si min_qubits=3 est défini, l'instance UnrollCustomDefinitions ne traduira que les portes du circuit qui fonctionnent sur 3 qubits ou plus.

  • Ajout d'un support à la passe SabreLayout pour ajouter des essais dont la disposition de départ est spécifiée. La passe de SabreLayout exécute généralement plusieurs essais de disposition qui commencent tous par des dispositions totalement aléatoires, puis utilise une passe de routage pour permuter cette disposition au lieu d'insérer des permutations afin de trouver une disposition qui entraînera une réduction du nombre de portes de permutation. Cette nouvelle fonctionnalité permet d'exécuter un AnalysisPass avant SabreLayout qui définit le champ "sabre_starting_layout" dans l'ensemble de propriétés afin de fournir à l'équipe d'experts de l'UE des modèles de départ supplémentaires à utiliser dans ses essais internes SabreLayout d'autres modèles de départ à utiliser dans ses essais internes. Par exemple, si vous voulez exécuter DenseLayout comme point de départ d'un essai dans SabreLayout vous feriez quelque chose comme :

    from qiskit.providers.fake_provider import FakeSherbrooke
    from qiskit.transpiler import AnalysisPass, PassManager
    from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
    from qiskit.transpiler.passes import DenseLayout
    
    class SabreDenseLayoutTrial(AnalysisPass):
    
      def __init__(self, target):
          self.dense_pass = DenseLayout(target=target)
          super().__init__()
    
      def run(self, dag):
          self.dense_pass.run(dag)
          self.property_set["sabre_starting_layouts"] = [self.dense_pass.property_set["layout"]]
    
    backend = FakeSherbrooke()
    opt_level_1 = generate_preset_pass_manager(1, backend)
    pre_layout = PassManager([SabreDenseLayoutTrial(backend.target)])
    opt_level_1.pre_layout = pre_layout

    Ensuite, lorsque le site opt_level_1 StagedPassManager est utilisé avec un circuit, la sortie du DenseLayout sera utilisée pour l'un des essais SabreLayout essais en plus des 5 essais totalement aléatoires qui s'exécutent par défaut au niveau d'optimisation 1.

  • Deux nouvelles passes de transpilation ont été ajoutées pour générer à la volée des étalonnages de portes RX à impulsion unique. Ces étalonnages RX à impulsion unique réduiront de moitié le temps d'accès, comme décrit dans P.Gokhale et al, Optimized Quantum Compilation for Near-Term Algorithms with OpenPulse (2020), arXiv:2004.11205.

    Pour réduire la quantité de données d'étalonnage RX qui doivent être générées, NormalizeRXAngle effectue trois optimisations : l'intégration des angles de rotation de RXGate à [0, pi], en remplaçant RX(pi/2) et RX(pi) par SXGate et XGateet quantifier les angles de rotation. Cette passe doit être exécutée avant RXCalibrationBuilderqui génère des calibrations RX à la volée.

    Les optimisations réalisées par NormalizeRXAngle réduisent la quantité de données d'étalonnage et nous permettent de tirer parti des impulsions plus précises, étalonnées par le matériel. Les calibrations générées par RXCalibrationBuilder sont obtenues à partir de l'étalonnage SXGate qui doit être déjà présente dans la cible. L'amplitude est mise à l'échelle de façon linéaire pour obtenir l'angle de rotation arbitraire souhaité.

    Ces étalonnages à une seule impulsion réduisent RXGate temps de moitié par rapport à la séquence conventionnelle qui consiste en deux impulsions SXGate impulsions. Cette réduction du temps d'accès pourrait améliorer la fidélité.

  • De nouvelles méthodes ont été ajoutées à TranspileLayout, initial_index_layout() et routing_permutation()qui sont utilisées pour générer une vue de liste de l'élément TranspileLayout.initial_layout et TranspileLayout.final_layout respectivement. Par exemple, si l'attribut final_layout était :

    Layout({
      qr[0]: 2,
      qr[1]: 3,
      qr[2]: 0,
      qr[3]: 1,
    })

    puis routing_permutation() renverra :

    [2, 3, 0, 1]
  • Ajout d'une nouvelle méthode pour TranspileLayout, initial_virtual_layout()qui est équivalente à l'attribut TranspileLayout.initial_layout mais qui permet de filtrer les qubits ancillaires ajoutés au circuit. Par défaut, le TranspileLayout.initial_layout inclut généralement les ancillas ajoutés par le transpileur.

  • Ajout d'une nouvelle méthode, final_index_layout() et final_virtual_layout() à la classe TranspileLayout classe. Ces méthodes sont utilisées pour renvoyer un schéma final (la correspondance entre les qubits du circuit d'entrée et la position finale dans la sortie). Ceci est différent de l'attribut final_layout qui est la permutation causée par le routage en tant qu'objet Layout objet. La méthode final_index_layout() renvoie une liste indiquant la position de sortie de chaque qubit dans le circuit d'entrée du transpileur. Par exemple, avec un circuit original :

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

    et la sortie du transpileur était :

    tqc = QuantumCircuit(3)
    tqc.h(2)
    tqc.cx(2, 1)
    tqc.swap(0, 1)
    tqc.cx(2, 1)

    alors la sortie de final_index_layout() renverrait une liste de :

    [2, 0, 1]

    Le final_virtual_layout() renvoie cet objet sous la forme d'un objet Layout donc le retour de l'exemple ci-dessus serait :

    Layout({
      qc.qubits[0]: 2,
      qc.qubits[1]: 0,
      qc.qubits[2]: 1,
    })

Fonctionnalités de visualisation

  • Ajout de la possibilité d'afficher les conditions sous forme d'expressions à partir de Expr dans la méthode QuantumCircuit.draw() et la fonction circuit_drawer() fonction lors de la visualisation de circuits comportant des ControlFlowOp instructions.

  • Ajout des styles de couleurs "iqp" et "iqp-dark" pour le tiroir de circuit matplotlib , qui sont basés sur le schéma de couleurs IBM Quantum Platform.

  • Dans TextDrawer, les opérations construites à partir de ControlFlowOpy compris if, else, while, for, et switch/case, qu'elles soient directement instanciées ou construites à l'aide de méthodes dans QuantumCircuitaffichent désormais entièrement les circuits définis dans ControlFlowOps, avec des crochets pour délimiter les circuits.

  • Lors de la définition d'une feuille de style personnalisée pour le tiroir de la chronologie des impulsions qiskit.visualization.timeline_drawer()les fonctions "generator" dont l'attribut d'objet accepts_program est défini sur True recevront un argument de mot-clé supplémentaire program contenant l'intégralité de l'ordonnance à dessiner QuantumCircuit qui est dessiné.

  • Les visualisations de la plot_gate_map(), plot_coupling_map(). plot_error_map(), et plot_circuit_layout() ont été considérablement améliorées pour le rendu des schémas des backends avec un grand nombre de qubits. Pour ce faire, nous avons tiré parti de graphviz grâce à la fonction graphviz_draw() de rustworkx afin d'effectuer une mise en page algorithmique plus sophistiquée du graphe qui s'adapte à un grand nombre de qubits.

    _images/release_notes-1.png

Divers. Fonctions

  • Ajout d'un support pour exprimer le signe d'un ParameterExpression. Au lieu d'assigner une valeur concrète et d'utiliser numpy.sign ou d'autres fonctions de la bibliothèque, l'utilisateur peut utiliser l'instance de la classe ParameterExpression pour calculer le signe et peut travailler avec le signe avant que l'expression ne soit entièrement affectée.

    Il peut être utilisé comme suit :

    from qiskit.circuit import Parameter
    
    b = Parameter("phi")
    sign_value = b.sign()
    print("sign of an unassigned Parameter is: ", sign_value)
    print("Sign of a Parameter assigned to -3 is: ", sign_value.assign(b,-3))

    Pour plus de détails, voir le numéro 10360.

  • Parameter dispose désormais d'un mot-clé d'utilisation avancée uuid dans son constructeur, qui peut être utilisé pour rendre le mot-clé Parameter égale à une autre du même nom. Cette fonction ne devrait pas être utilisée par les utilisateurs et est surtout utile pour la sérialisation et la désérialisation personnalisées.

Notes sur la mise à niveau des circuits

  • Les ControlledGate.definition de la sortie de la méthode Gate.control() peut être différente de celle des versions précédentes. La génération interne de la méthode Gate.control() n'utilise plus la passe de transposition, désormais obsolète, pour générer sa définition Unroller désormais obsolète, pour générer sa définition, ce qui peut potentiellement entraîner la génération d'une définition différente. La définition de l'objet de sortie ControlledGate sera unitairement équivalent à ce qui a été généré précédemment. Mais si vous avez besoin de la définition exacte de l'appel Gate.control() vous pouvez utiliser une version antérieure et sauvegarder le circuit avec qpy.dump() puis le charger avec une version plus récente.

  • La propriété num_ancilla_qubits de la classe PolynomialPauliRotations a été supprimée, car elle est dépréciée dans Qiskit 0.23.0. Au lieu de cela, utilisez la propriété PolynomialPauliRotations.num_ancillas.

  • Les portes de la bibliothèque standard suivantes :

    ne sont plus en mesure de fixer label, condition, duration, ou unit (et ctrl_state pour les ControlledGate (et pour les sous-classes) après l'instanciation d'un objet. Vous pouvez toujours définir condition par l'intermédiaire de l'utilisation c_if(). Vous pouvez utiliser to_mutable() pour obtenir une copie mutable de l'instruction, puis utiliser le setter sur cette copie au lieu de l'objet original. label, duration et unit peuvent être donnés comme arguments à ces portes au moment de la construction, et une instance mutable sera automatiquement renvoyée. Cette modification était nécessaire dans le cadre de la conversion de ces classes en classes SingletonGate et SingletonControlledGate ce qui réduit considérablement l'empreinte mémoire des instances répétées de ces portes.

  • Pour tout ce qui interagit avec Gate, Operationou Instruction ou qui travaille avec ces objets dans le cadre d'un QuantumCircuit ou DAGCircuit il est important de noter que l'utilisation de références partagées pour les instances est beaucoup plus courante aujourd'hui. Auparavant, il était possible de réutiliser et de partager une instance d'une opération de circuit, mais cela n'était pas très courant et une copie générait une instance unique. Ceci a changé à partir de cette version à cause de SingletonInstruction et SingletonGate étant disponibles (et un grand nombre de portes de la bibliothèque standard étant maintenant construites à partir d'eux). Si votre utilisation de ces objets suppose des instances uniques pour chaque opération de circuit, cela devient un problème potentiel, car un état partagé sera désormais réutilisé entre des opérations du même type (qui persisteront par le biais de copies et de copies approfondies). Vous pouvez vous appuyer sur l'attribut Instruction.mutable pour vérifier la mutabilité d'un objet ou utiliser l'attribut Instruction.to_mutable() pour obtenir une copie mutable d'une instruction.

  • Plus Instruction (celles qui renvoient des singletons) ne satisfont plus strictement (par exemple) :

    type(XGate()) is XGate

    L'objet retourné sera cependant toujours une sous-classe standard, de sorte que isinstance() (la manière correcte de vérifier le type) continuera à fonctionner correctement. Plusieurs instructions possédaient déjà cette propriété (par ex. MCXGate), mais c'est désormais plus courant, car de plus en plus de portes standard le permettent.

    Si vous avez besoin du type "de base" d'une porte pour une raison quelconque, en omettant les sous-classes singleton synthétiques, qui ne peuvent pas être instanciées, voir Instruction.base_class.

  • La définition de UnitaryGate pour les qubits unitaires est maintenant en termes de UGate au lieu de l'ancienne classe U3Gate ancienne.

Notes de mise à niveau des fournisseurs

  • Le simulateur QasmSimulatorPy le simulateur basé sur python inclus dans qiskit.providers.basicaer inclut désormais 'h' (HGate), 'p' (PhaseGate) et 'u' (UGate) dans son jeu de portes de base.

  • L'argument channel de la méthode PulseBackendConfiguration.control() est supprimé. Il a été supprimé dans Qiskit 0.33 (avec Terra 0.19 ), publié en décembre 2021. Utilisez plutôt l'argument qubits .

  • Remplacement de l'argument qobj[Qobj] dans QasmSimulatorPy.run() par run_input[QuantumCircuit or list]

    Voici un exemple de migration de votre code :

    # Importing necessary Qiskit libraries
    from qiskit import transpile, QuantumCircuit
    from qiskit.aer import QasmSimulator
    
    # Defining the Quantum Circuit
    qc = QuantumCircuit(2)
    qc.h(0)
    qc.cx(0, 1)
    qc.measure_all()
    
    # Transpile the circuit to optimize for the target simulator
    simulator = QasmSimulator()
    transpiled_circuit = transpile(qc, simulator)
    # Run the simulation
    job = simulator.run(transpiled_circuit, shots=1024)
    # Get the simulation result
    result = job.result()

    Tous ces éléments étaient obsolètes depuis 0.22 (publié le 13 octobre 2022) et sont désormais supprimés.

Notes de mise à jour Pulse

  • Les fonctions qiskit.scheduler.utils.format_meas_map(), qiskit.scheduler.utils.measure(), et qiskit.scheduler.utils.measure_all() ont été déplacées vers qiskit.pulse.utils.format_meas_map(), qiskit.pulse.macros.measure(), et qiskit.pulse.macros.measure_all() respectivement. L'emplacement précédent a été supprimé dans Qiskit 0.20.0 (Terra 0.15.0, publié le 2020-08-10) et n'est plus pris en charge.

  • Les méthodes to_dict dans les classes pulse.transforms.AlignmentKind, pulse.transforms.AlignEquispaced, et pulse.transforms.AlignFunc sont supprimées. Ils ont été supprimés dans Qiskit 0.37 (avec Terra 0.21 ), publié en juin 2022.

Notes de mise à niveau QPY

  • L'utilisation du mot-clé circuits pour le premier argument positionnel de la fonction qiskit.qpy.dump() est supprimée car son utilisation a été dépréciée dans Qiskit 0.37 (avec Terra 0.21 ), publié en juin 2022. A la place, on peut utiliser le mot-clé programs (ou simplement passer l'argument en position), qui se comporte de manière identique.

Notes de mise à jour sur les informations quantiques

  • La méthode qiskit.quantum_info.pauli_basis() n'accepte plus l'argument pauli_list . Il a été supprimé dans Qiskit 0.39 (avec Terra 0.22 ), publié en octobre 2022.

  • La fonction random_stabilizer_table du module qiskit.quantum_info.random est supprimée. Il a été supprimé dans Qiskit 0.39 (avec Terra 0.22 ), publié en octobre 2022. Utilisez plutôt qiskit.quantum_info.random.random_pauli_list().

  • Les classes qiskit.quantum_info.PauliTable et qiskit.quantum_info.StabilizerTable sont supprimées. La fonction random_pauli_table() est également supprimée. Ils ont été supprimés dans Qiskit 0.43 (avec Terra 0.24 ), publié en mai 2023. Au lieu de cela, vous devez utiliser PauliList et random_pauli_list().

  • Les arguments z et x de l'initialisateur de to Pauli ont été supprimés, car ils sont dépréciés dans Qiskit Terra 0.17 (publié en avril 2021). Une paire de x et z devrait être transmise positionnellement comme un seul tuple (Pauli((z, x))).

  • L'argument label de l'initialisateur de Pauli a été supprimé, car déprécié dans Qiskit Terra 0.17 (publié en avril 2021). Passez plutôt l'étiquette en position, comme Pauli("XYZ").

  • L'importation depuis qiskit.quantum_info.operators.pauli n'est plus autorisée, car elle a été supprimée dans Qiskit Terra 0.21 (publié en juin 2022). Importez plutôt directement depuis qiskit.quantum_info .

Notes de mise à niveau de Synthesis

  • Le paramètre order dans le constructeur synthesis.SuzukiTrotter soulève une exception au lieu d'un avertissement de dépréciation lorsqu'il est défini dans un nombre impair. Les formules du produit de Suzuki sont symétriques et ne sont donc définies que pour les ordres pairs.

Notes de mise à niveau du transpilateur

  • Suite aux efforts de refonte du gestionnaire de passage, les contrôleurs de flux existants : FlowControllerLinear, ConditionalController, et DoWhileController sont désormais des sous-classes du contrôleur de flux BaseController. Notez que ces contrôleurs ont abandonné la mise en œuvre de la méthode __iter__() . Ils ne sont désormais itérables que dans le contexte de l'exécution d'un contrôleur de flux, qui fait passer l'état de compilation après l'exécution de chaque tâche interne.

  • La fonctionnalité de la classe RunningPassManager a été remplacée par le nouveau cadre de gestion des laissez-passer (BasePassManager et BaseController). Le gestionnaire de passes en cours d'exécution est désormais un contrôleur de flux sans état (essentiellement un alias de FlowControllerLinear), car le gestionnaire de passes est responsable de la construction du pipeline de tâches, tandis que le contrôleur est responsable de l'exécution des tâches associées. La sous-classification de RunningPassManager n'est plus recommandée, et cette classe sera complètement remplacée par le contrôleur de flux dans les prochaines versions.

  • Une nouvelle classe, WorkflowStatusa été introduite pour suivre l'état du flux de travail du gestionnaire de laissez-passer. Cet objet portable est créé lors de l'exécution du gestionnaire de passe et transmis aux tâches sous-jacentes. Ce statut était auparavant géré par le site RunningPassManager à l'aide de variables d'instance.

  • L'option spécifique au transpileur transpiler.PassManager (utilisé dans transpile()) est maintenant une sous-classe de passmanager.BasePassManager. Toutefois, cette modification de la hiérarchie des classes n'introduit aucune rupture dans l'API publique.

  • Les exceptions soulevées lors de l'exécution du gestionnaire de passe héritent désormais de la nouvelle fonction PassManagerError. Une défaillance générique de la machinerie du gestionnaire de passe soulèvera PassManagerError pour les gestionnaires de passe généraux, mais le transpileur spécifique transpile.PassManager l'englobera actuellement dans son système spécifique TranspilerError pour des raisons de rétrocompatibilité. Cet emballage sera supprimé à l'avenir.

  • L'utilisation de FencedObject dans le cadre du gestionnaire de passe a été supprimée. Cette classe enveloppante ne peut pas protéger les attributs des objets mutables contre les modifications, ce qui ne devrait pas poser de problème pour un code correctement mis en œuvre. Les passes d'analyse ne doivent pas modifier un IR d'entrée, les contrôleurs ne doivent pas mettre à jour l'ensemble des propriétés, etc. Il incombe au développeur du gestionnaire de passe de s'assurer que la passe ne modifie pas les attributs de l'objet,

  • Le nom du plugin default est réservé aux étapes du plugin init, layout, optimization et scheduling. Ces étapes n'avaient auparavant pas de nom de plugin, mais le nom default est maintenant utilisé pour représenter la méthode par défaut intégrée à Qiskit pour ces étapes. Si vous utilisiez ces noms pour des plugins sur ces étapes, ils entreront en conflit avec l'utilisation de Qiskit et vous devrez renommer votre plugin.

  • Désactive l'utilisation de la classe RemoveResetInZeroState dans les gestionnaires de passe prédéfinis. Auparavant, lorsque transpile() ou generate_preset_pass_manager() était exécuté avec optimization_level au niveau 1, 2 ou 3, il exécutait RemoveResetInZeroState. Toutefois, cette passe interdisait la notion d'états initiaux arbitraires, à moins qu'ils ne soient explicitement mis à zéro avec des réinitialisations. Si vous avez besoin d'exécuter la passe dans le cadre de votre pipeline de compilation, vous pouvez exécuter quelque chose comme :

    pm = generate_preset_pass_manager(1, backend)
    pm.init.append(RemoveResetInZeroState())
    pm.run(circuit)

    afin de conserver cette fonctionnalité pour la compilation de vos circuits.

  • La passe de routage du transpilateur, BIPMapping , a été supprimée. Il a été marqué comme obsolète dans la version de Qiskit 0.43.0. Il a été remplacé par un plugin externe : qiskit-bip-mapper. Les détails de ce nouveau paquet sont disponibles sur le dépôt github du paquet :

    https://github.com/qiskit-community/qiskit-bip-mapper

    La passe a été intégrée dans un paquetage de plugin séparé pour deux raisons : premièrement, la dépendance à CPLEX rend son utilisation plus difficile, et deuxièmement, le paquetage de plugin s'intègre plus proprement à transpile(). L'option supplémentaire bip-mapper pour installer cplex et docplex pour supporter cette passe a été supprimée car rien dans Qiskit ne l'exige plus.

  • L'argument qubits dans la méthode InstructionDurations.get()n'accepte plus Qubit (ou une liste de ceux-ci). Cette fonctionnalité a été supprimée dans Qiskit 0.33 (avec Terra 0.19 ), publié en décembre 2021. Au lieu de cela, utilisez un entier pour les indices des qubits.

  • Suppression de l'argument qubit_channel_mapping dans RZXCalibrationBuilderqui était obsolète dans Qiskit 0.39 (publié le 20 octobre 2022, avec qiskit-terra 0.22 )

  • La méthode transpiler.CouplingMap la méthode subgraph est supprimée car elle est obsolète dans 0.20. reduce() peut être utilisée à la place de la méthode subgraph.

Notes de mise à niveau de la visualisation

  • Suppression de la prise en charge de l'utilisation du mot-clé rho pour le premier argument positionnel dans plot_state_hinton(), plot_bloch_multivector(), plot_state_city(), plot_state_paulivec(), et plot_state_qsphere(). L'utilisation de rho a été remplacée par state, qui peut être utilisé à la place. Suppression de qiskit.scheduler.utils car toutes les fonctions contenues ont été déplacées vers qiskit.pulse.macros et qiskit.pulse.utils. Tous ces éléments étaient obsolètes depuis 0.15 (publié le 6 août 2020) et sont désormais supprimés.

  • Les arguments du constructeur de classe qregs, cregs, layout et global_phase pour visualization.QCircuitImage sont supprimés, car ils étaient obsolètes dans 0.20.

  • Les fonctions de visualisation : plot_gate_map(), plot_coupling_map(). plot_error_map(), et plot_circuit_layout() dépendent maintenant de l'installation de graphviz pour fonctionner. Ce changement était nécessaire pour permettre la visualisation des backends avec un plus grand nombre de qubits. Cette exigence externe supplémentaire s'ajoute aux dépendances optionnelles existantes que ces fonctions nécessitaient auparavant. Vous trouverez des détails sur l'installation de graphviz ici : https://graphviz.org/download/

Divers. Mise à niveau

  • Les valeurs QuasiDistribution peuvent inclure des erreurs de virgule flottante. QuasiDistribution.__repr__ les tours de table utilisant numpy.round() et le paramètre ndigits peuvent être manipulés à l'aide de l'attribut de classe __ndigits__. La valeur par défaut est 15.

  • La classe qiskit.qobj.Qobj est supprimée. Il a été supprimé dans Qiskit 0.33 (avec Terra 0.19 ), publié en décembre 2021. Au lieu de cela, utilisez qiskit.qobj.QasmQobj ou qiskit.qobj.PulseQobj.

  • Le décorateur qiskit.utils.deprecation.deprecate_function() a été déprécié depuis Qiskit 0.39.0 (publié en octobre 2022, avec qiskit-terra 0.22.0 ) et a été supprimé. Utiliser qiskit.utils.deprecate_func() à la place.

  • La fonction execute() n'accepte plus les arguments qobj_id et qobj_header . Leur utilisation a été supprimée dans Qiskit 0.37 (avec Terra 0.21 ), publié en juin 2022.

  • La passe de transpilation qiskit.transpiler.passes.CXDirection est retirée. Son utilisation a été supprimée dans Qiskit 0.37 (avec Terra 0.21 ), publié en juin 2022. Au lieu de cela, utilisez l'option plus générique GateDirection passer.

  • La passe de transpilation qiskit.transpiler.passes.CheckCXDirection est retirée. Son utilisation a été supprimée dans Qiskit 0.37 (avec Terra 0.21 ), publié en juin 2022. Au lieu de cela, utilisez l'option plus générique CheckGateDirection passer.

  • La construction de Qiskit à partir des sources nécessite désormais un compilateur Rust compatible avec la version du langage 1.64. Ce nombre a été augmenté par rapport à la version Rust minimale supportée par 1.61 pour la construction des versions antérieures de Qiskit.

Algorithmes obsolètes

  • Les utilitaires d'algorithme dans qiskit.utils.validation et qiskit.utils.algorithm_globals sont maintenant obsolètes et seront supprimés dans au moins 3 mois à partir de la date de publication. Ces utilitaires ont été introduits avec le module qiskit.algorithms pour prendre en charge les algorithmes hérités et primitifs. Maintenant que qiskit.algorithms est obsolète et que la base de code des algorithmes primitifs a été migrée vers une bibliothèque autonome, ces utilitaires ne sont plus utilisés dans le contexte de Qiskit. Si votre application le permet, nous vous recommandons de migrer votre code pour utiliser qiskit_algorithms, où vous pourrez importer les utilitaires pertinents dans algorithm_globals et validation à partir de qiskit_algorithms.utils. Veuillez noter que les anciennes fonctionnalités n'ont pas été migrées vers le nouveau paquet.

Circuits obsolètes

Dépréciations du transcompilateur

  • La méthode d'usine du contrôleur de flux FlowController.controller_factory() est obsolète, tout comme les méthodes FlowController.add_flow_controller() et FlowController.remove_flow_controller(). À l'avenir, la construction de tâches avec des arguments de type mot-clé dans la méthode BasePassManager.append() sera également dépréciée. Les contrôleurs doivent être explicitement instanciés et ajoutés au gestionnaire de passe. Par exemple, la syntaxe conventionnelle utilisée précédemment

    pm.append([task1, task2], condition=lambda x: x["value1"] > 10)

    doit être remplacé par

    controller = ConditionalController([task1, task2], condition=lambda x: x["value1"] > 10)
    pm.append(controller)

    Cette dernière permet un contrôle plus précis de l'ordre des contrôleurs, en particulier lorsque plusieurs arguments de mots clés sont spécifiés ensemble, et permet la construction de contrôleurs de flux généraux qui peuvent avoir plus d'un pipeline ou qui ne prennent pas une seule fonction conditionnelle simple dans leurs constructeurs.

  • Les FlowControllerLinear.append(), DoWhileController.append(), et ConditionalController.append() sont toutes immédiatement obsolètes. La construction du pipeline de tâches du gestionnaire de passage est désormais du ressort de BasePassManageret les contrôleurs de flux individuels n'ont pas besoin de recourir à cette méthode. Pour un contrôleur de flux, toutes les passes doivent être spécifiées en une seule fois, directement dans le constructeur.

  • Le nom général de l'attribut et de la variable passes est remplacé par tasks dans tout le module qiskit.passmanager module. Notez qu'une tâche doit indiquer l'union de pass et controller, et que la forme singulière pass entre en conflit avec le mot-clé Python. En ce sens, l'utilisation de tâches est de loin préférable.

  • La passe Unroller a été dépréciée et sera supprimée dans une prochaine version. Le Unroller a été remplacé par le BasisTranslator qui fournit un ensemble de fonctionnalités similaires, mais de manière plus générale, de sorte que vous pouvez traduire un circuit dans n'importe quel ensemble de base universel. La classe Unroller ne fonctionne que dans les situations où les définitions des portes du circuit sont définies récursivement en termes de base cible; pour les portes de la bibliothèque standard de Qiskit, cela signifie UGate et CXGate. Si vous utilisez le passe Unroller il peut être remplacé par un gestionnaire de passe personnalisé du formulaire :

    from qiskit.transpiler import PassManager
    from qiskit.transpiler.passes import UnrollCustomDefinitions, BasisTranslator
    from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel
    
    pm = PassManager(
        [
            UnrollCustomDefinitions(sel, basis_gates=basis_gates),
            BasisTranslator(sel, target_basis=basis_gates),
        ]
    )
    pm.run(circuit)
  • L'utilisation de la valeur "unroller" pour l'argument du mot-clé translation_method sur les formulaires transpile() et generate_preset_pass_manager() a été supprimée. Ce plugin d'étape de traduction sera supprimé de Qiskit dans une prochaine version car il a été remplacé par la méthode par défaut "translator" qui fonctionnera de manière similaire au plugin "unroller" mais supportera un ensemble plus large de backends cibles.

Dépréciations de la visualisation

  • Le réglage par défaut du tiroir matplotlib produit désormais un FutureWarning, car le style par défaut passe au style "iqp" (anciennement connu sous le nom de "iqx"). L'ancienne valeur par défaut est disponible sous le style "clifford" . Pour faire taire l'avertissement, vous pouvez définir explicitement le style souhaité, par exemple. g.:

    from qiskit import QuantumCircuit
    
    circuit = QuantumCircuit(2)
    circuit.x(0)
    circuit.h(0)
    circuit.cp(0.5, 0, 1)
    
    circuit.draw("mpl", style="clifford")  # or style="iqp"
  • Le passage d'un circuit à qiskit.visualization.timeline_drawer() qui n'a pas d'information sur l'heure de début du nœud programmé est obsolète. Seuls les circuits ayant fait l'objet d'un des passages d'analyse de l'ordonnancement (par exemple ALAPScheduleAnalysis ou ASAPScheduleAnalysis) peuvent être visualisés. Si vous avez utilisé l'une des anciennes cartes de programmation (par exemple ALAPSchedule ou ASAPSchedule), vous pouvez propager les informations relatives à l'ordonnancement en exécutant la commande

    from qiskit import transpile
    from qiskit.transpiler import InstructionDurations
    
    scheduled = transpile(
      my_old_style_circuit,
      optimization_level=0,
      scheduling_method="alap",
      instruction_durations=InstructionDurations(),
    )

    Ce comportement devait être supprimé dans Qiskit 0.37, mais en raison d'un bogue dans l'avertissement, il n'a pas été affiché aux utilisateurs jusqu'à présent. Le comportement sera supprimé dans Qiskit 1.0.

Corrections des erreurs

  • Le nombre maximum de qubits à prendre en compte pour la vérification de la commutativité basée sur la multiplication des matrices en CommutationChecker est désormais limité à 3 par défaut. Corrigé #10488

  • La passe de GateDirection utilisera désormais des traductions en base discrète plutôt que de s'appuyer sur une base continue, ce qui devrait rendre certaines cibles en base discrète un peu plus fiables RYGatece qui devrait rendre certaines cibles en base discrète un peu plus fiables. En général, transpile() ne prend que partiellement en charge les ensembles de bases qui ne contiennent pas d'opération à paramètres continus, de sorte qu'il ne réussit pas toujours dans ces situations et qu'il est presque certain qu'il ne produira pas de résultats optimaux.

  • Fixe CommutationAnalysis pour regrouper les portes d'un fil en ensembles, chaque ensemble ne contenant que les portes qui s'interpénètrent. Cela permet d'éviter que CommutationCancellation ne procède à des optimisations non fondées. Voir #8020

  • CUGate se comportera désormais correctement lors des appels à QuantumCircuit.assign_parameters(). Auparavant, il provoquait diverses erreurs bizarres, souvent quelque temps après l'attribution initiale du circuit. Voir #7326, #7410, #9627, #10002, et #10131.

  • L'interface de construction du flux de contrôle (les formes de gestionnaire de contexte de QuantumCircuit.if_test(), while_loop(), for_loop() et switch()) suivra désormais correctement l'avancement d'une phase globale distincte au sein de ce bloc. Vous pouvez ajouter un avancement de phase global à un bloc interne en l'assignant à QuantumCircuit.global_phase dans un champ d'application du constructeur :

    from math import pi
    from qiskit import QuantumCircuit
    
    qc = QuantumCircuit(3, 3)
    qc.global_phase = pi / 2  # Set the outer circuit's global phase.
    
    with qc.if_test((qc.clbits[0], False)) as else_:
      # The global phase advancement in a control-flow block begins at 0,
      # because it represents how much the phase will be advanced by an
      # execution of the block.  The defined phase of the outer scope is not
      # affected by this set.
      qc.global_phase = pi
    with else_:
      # Similarly, the `else` block may induce a different global-phase
      # advancement to the `if`, so it can also be set separately.
      qc.global_phase = 1.5 * pi
    
    # The phase advancement caused directly by the outer scope is independent
    # of the phase advancement conditionally caused by each control-flow path.
    assert qc.global_phase == pi / 2

    La signification de QuantumCircuit.global_phase est considéré comme l'avancement global de la phase inhérent à une seule exécution du bloc. Il s'agit toujours d'une avancée de phase globale, en ce sens que si le bloc est saisi, la phase de tous les qubits de l'ensemble du programme sera avancée.

  • Corriger la coloration des schémas de couleurs matplotlib "iqx" et "iqx-dark" , qui dessinaient auparavant les symboles RZGate, RZZGate, (multi-)contrôlées PhaseGateet iSwapGate dans la mauvaise couleur.

  • Le hachage de a Parameter est maintenant égal aux hachages de tous les ParameterExpression auxquels il est comparé. Auparavant, les hachages étaient différents, ce qui entraînait l'ajout d'entrées parasites dans les hashmaps lorsque Parameter et ParameterExpression étaient mélangées dans la même carte, ce qui violait le modèle de données de Python.

  • Correction d'un bug dans la sérialisation QPY (qiskit.qpy) où les portes unitaires contrôlées dans un circuit pouvaient entraîner l'échec de la désérialisation. Correction #10802.

  • Corrige l'implémentation de random_statevector() afin qu'elle échantillonne à partir de la distribution uniforme.

  • Le laissez-passer NoiseAdaptiveLayout prend maintenant CouplingMap comme argument facultatif. Ceci est utilisé par le plugin pour contrôler l'incohérence entre configuration() et properties()comme dans le cas de FakeMelbourne. Correction #7677.

  • Les méthodes QuantumCircuit.copy() et copy_empty_like() lèveront désormais une erreur si l'argument name est mal typé, au lieu de générer un circuit invalide.

  • L'heuristique "decay" de SabreSwap et SabreLayout suit maintenant correctement la profondeur sur les qubits physiques au lieu de suivre par erreur la "profondeur" des échanges sur les qubits virtuels.

  • Correction d'une erreur dans le ECRGate qui empêchait de définir un attribut ECRGate.label lors de la construction de l'objet. Toutes les autres Gate permettent de définir un argument du mot-clé label dans le constructeur.

  • Correction d'un oubli dans le constructeur Gate (et les sous-classes de la bibliothèque standard) où les éléments duration et unit ne pouvaient pas être définis en tant qu'arguments de mot-clé pendant la construction. La classe mère Instruction prend en charge ce paramétrage, mais Gate n'exposait pas correctement cette interface.

  • Ajout d'un support pour permettre l'initialisation par défaut de SparsePauliOp en passant un itérable vide aux méthodes statiques from_list() et from_sparse_list(). Correction #10159.

  • L'utilisation de la classe (dépréciée) Optimizer sur AQC n'avait pas de chemin alternatif non déprécié, qui aurait dû être introduit dans Qiskit 0.44. Il accepte désormais un objet appelable qui implémente le protocole Minimizer comme l'indique explicitement l'avertissement de dépréciation. L'appelant peut ressembler à l'exemple suivant :

    from scipy.optimize import minimize
    from qiskit.transpiler.synthesis.aqc.aqc import AQC
    
    optimizer = partial(minimize, args=(), method="L-BFGS-B", options={"maxiter": 200})
    aqc = AQC(optimizer=optimizer)
  • Correction d'un problème avec la classe Barrier classe. Lors de l'ajout d'une instance Barrier à un QuantumCircuit avec la méthode QuantumCircuit.append() il n'y avait pas de validation que la taille de la barrière correspondait aux qargs spécifiés.

  • La passe de transposition BlockCollapser gère désormais correctement les circuits qui contiennent plus d'une condition sur le même registre classique.

  • BlueprintCircuit se comporteront désormais correctement lorsque la méthode semi-publique QuantumCircuit._append() est utilisée avec le plan dans un état non construit, c' est-à-dire que le circuit sera construit avant de tenter l'ajout.

  • Ajustement du zoom, de la taille des polices et des marges dans plot_state_city() afin de mieux adapter le tracé à un plus grand nombre de tailles de figures. Correction du comportement de l'ordre Z des barres et du plan d'amplitude zéro, et correction de l'affichage des barres à valeur réelle négative.

Autres remarques

  • Cette version de Qiskit est explicitement rattachée à la série Numpy 1.x, car elle inclut des extensions compilées qui ne sont pas encore compilées avec la série Numpy 2.x qui n'a pas encore été publiée. Nous publierons une nouvelle version de Qiskit avec le support de Numpy 2.x dès que possible.

    Nous ne pouvons pas empêcher votre gestionnaire de paquets de se résoudre à des versions plus anciennes de Qiskit (qui n'ont pas la même broche mais qui sont toujours susceptibles d'être incompatibles) si vous essayez d'installer Qiskit en même temps que Numpy 2, avant que nous n'ayons publié une version compatible.

  • Modification du comportement des boutons VF2Layout et VF2PostLayout qui exécutaient auparavant leur notation interne en utilisant le multithreading si les circuits d'entrée étaient suffisamment grands. L'utilisation du multithreading a été supprimée des passes, car il a été démontré qu'elle entraînait une régression des performances au lieu d'une amélioration comme prévu à l'origine.

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