Notes de publication de Qiskit 0.35
0.35.0
Terra 0.20.0
Prélude
Les points forts de la version Qiskit Terra 0.20.0 sont les suivants :
- L'introduction de modules multithreads écrits en Rust pour accélérer les performances de certaines parties de Qiskit Terra et améliorer la mise à l'échelle avec un plus grand nombre de qubits. Cependant, lors de la construction de Qiskit à partir des sources, un compilateur Rust est maintenant nécessaire.
- Plus de support natif pour travailler avec un
Targetdans le transpileur. Plusieurs passes permettent maintenant de travailler directement avec un objetTargetce qui rend le transpileur plus robuste dans les types de backends qu'il peut cibler. - L'introduction du
qiskit.primitivesmodule. Ces API offrent différents niveaux d'abstraction pour le calcul des résultats d'intérêt à partir deQuantumCircuitet l'utilisation de backends. Par exemple, l'interfaceBaseEstimatordéfinit une interface abstraite permettant d'estimer la valeur attendue d'un observable. Cela peut ensuite être utilisé pour construire des algorithmes et des applications de plus haut niveau qui sont construits en utilisant l'estimation des valeurs d'espérance sans avoir à se soucier de la mise en œuvre du calcul de la valeur d'espérance. Ce découplage permet à la mise en œuvre d'améliorer la vitesse et la qualité tout en respectant l'interface abstraite définie. De même, l'outilBaseSamplercalcule des distributions de quasi-probabilité à partir de mesures de circuits. D'autres primitives seront introduites à l'avenir.
Cette version ne prend plus en charge Python 3.6. Avec cette version, Python 3.7 à Python 3.10 sont nécessaires.
Nouvelles fonctions
-
Ajout d'une nouvelle méthode de construction pour la classe
Operatorpour créer une nouvelle classe,Operator.from_circuit()pour créer un nouvel objetOperatorà partir d'unQuantumCircuit. Alors que cela était possible normalement en utilisant le constructeur par défaut, la méthodeOperator.from_circuit()fournit des options supplémentaires pour ajuster la façon dont l'opérateur est créé. Cela permet principalement de permuter l'ordre des qubits sur la base d'un ensembleLayout. Par exemple :from qiskit.circuit import QuantumCircuit from qiskit import transpile from qiskit.transpiler import CouplingMap from qiskit.quantum_info import Operator circuit = QuantumCircuit(3) circuit.h(0) circuit.cx(0, 1) circuit.cx(1, 2) cmap = CouplingMap.from_line(3) out_circuit = transpile(circuit, initial_layout=[2, 1, 0], coupling_map=cmap) operator = Operator.from_circuit(out_circuit)la variable
operatoraura les qubits permutés en fonction de la disposition, de sorte qu'elle sera identique à ce qui est renvoyé parOperator(circuit)avant la transpilation. -
Ajout d'une nouvelle méthode
DAGCircuit.copy_empty_like()à la classeDAGCircuitclasse. Cette méthode est utilisée pour créer une nouvelle copie d'un objet existant avec la même structure mais sans aucune instructionDAGCircuitexistant avec la même structure mais vide de toute instruction. Cette méthode est identique à la méthode privée_copy_circuit_metadata(), mais elle fait désormais partie de l'API publique de la classe. -
Les classes de faux backend et de faux fournisseurs qui étaient auparavant disponibles sur
qiskit.test.mocksont désormais également accessibles dans un nouveau module :qiskit.providers.fake_provider. Ce nouveau module remplace le module précédentqiskit.test.mockqui sera supprimé dans Qiskit 0.21.0. -
Ajout d'une nouvelle classe de porte,
LinearFunctionqui encode efficacement une fonction linéaire (c'est-à-dire une fonction qui peut être représentée par une séquence deCXGateetSwapGate). -
Ajout d'une nouvelle passe de transposition
CollectLinearFunctionsqui collecte des blocs deCXGateetSwapGatedans un circuit, et remplace chaque bloc par une porteLinearFunctionporte. -
Ajout d'une nouvelle passe de transposition
LinearFunctionsSynthesisqui synthétise toutes les portesLinearFunctionen utilisant l' algorithme Patel-Markov-Hayes. Combiné avec le passage du transpondeur, il permet de collecter des blocs consécutifsCollectLinearFunctionsil est possible de collecter des blocs de données consécutifsCXGateetSwapGatedans un circuit, et de les resynthétiser en utilisant l' algorithme de Patel-Markov-Hayes. -
Ajout d'une nouvelle passe de transpilation
LinearFunctionsToPermutationsqui remplace unLinearFunctionpar un circuitPermutationchaque fois que c'est possible. -
FlowController(telles queConditionalController) peuvent désormais être imbriquées dans une instancePassManagerlors de l'utilisation de la méthodePassManager.append()méthode. Cela permet d'utiliser une logique imbriquée pour contrôler l'exécution des passes dans le systèmePassManager. Par exemple :from qiskit.transpiler import ConditionalController, PassManager from qiskit.transpiler.passes import ( BasisTranslator, GatesInBasis, Optimize1qGatesDecomposition, FixedPoint, Depth ) from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel pm = PassManager() def opt_control(property_set): return not property_set["depth_fixed_point"] def unroll_condition(property_set): return not property_set["all_gates_in_basis"] depth_check = [Depth(), FixedPoint("depth")] opt = [Optimize1qGatesDecomposition(['rx', 'ry', 'rz', 'rxx'])] unroll = [BasisTranslator(sel, ['rx', 'ry', 'rz', 'rxx'])] unroll_check = [GatesInBasis(['rx', 'ry', 'rz', 'rxx'])] flow_unroll = [ConditionalController(unroll, condition=unroll_condition)] pm.append(depth_check + opt + unroll_check + flow_unroll, do_while=opt_control)L'objet
pmPassManagern'exécutera la passeBasisTranslator(dans l'étapeunroll) à chaque itération de la boucle si la conditionunroll_conditionest remplie. -
Les constructeurs pour les
ZFeatureMapetZZFeatureMapdisposent d'un nouveau mot-cléparameter_prefix. Ce nouvel argument est utilisé pour définir le préfixe des paramètres du circuit d'encodage des données. Par exemple :from qiskit.circuit.library import ZFeatureMap feature_map = ZFeatureMap(feature_dimension=4, parameter_prefix="my_prefix") feature_map.decompose().draw('mpl')le circuit généré
ZFeatureMaple circuit généré a préfixé tous ses paramètres internes avec le préfixe"my_prefix". -
La passe de
TemplateOptimizationle transpiler pass peut maintenant travailler avec desGatequi ont des paramètresParameterExpressionparamètres. Un exemple illustratif de l'utilisation deParameteravecTemplateOptimizationest le suivant :from qiskit import QuantumCircuit, transpile, schedule from qiskit.circuit import Parameter from qiskit.transpiler import PassManager from qiskit.transpiler.passes import TemplateOptimization # New contributions to the template optimization from qiskit.transpiler.passes.calibration import RZXCalibrationBuilder, rzx_templates from qiskit.test.mock import FakeCasablanca backend = FakeCasablanca() phi = Parameter('φ') qc = QuantumCircuit(2) qc.cx(0,1) qc.p(2*phi, 1) qc.cx(0,1) print('Original circuit:') print(qc) pass_ = TemplateOptimization(**rzx_templates.rzx_templates(['zz2'])) qc_cz = PassManager(pass_).run(qc) print('ZX based circuit:') print(qc_cz) # Add the calibrations pass_ = RZXCalibrationBuilder(backend) cal_qc = PassManager(pass_).run(qc_cz.bind_parameters({phi: 0.12})) # Transpile to the backend basis gates cal_qct = transpile(cal_qc, backend) qct = transpile(qc.bind_parameters({phi: 0.12}), backend) # Compare the schedule durations print('Duration of schedule with the calibration:') print(schedule(cal_qct, backend).duration) print('Duration of standard with two CNOT gates:') print(schedule(qct, backend).duration)sorties
Original circuit: q_0: ──■──────────────■── ┌─┴─┐┌────────┐┌─┴─┐ q_1: ┤ X ├┤ P(2*φ) ├┤ X ├ └───┘└────────┘└───┘ ZX based circuit: ┌─────────────┐ » q_0: ────────────────────────────────────┤0 ├────────────» ┌──────────┐┌──────────┐┌──────────┐│ Rzx(2.0*φ) │┌──────────┐» q_1: ┤ Rz(-π/2) ├┤ Rx(-π/2) ├┤ Rz(-π/2) ├┤1 ├┤ Rx(-2*φ) ├» └──────────┘└──────────┘└──────────┘└─────────────┘└──────────┘» « «q_0: ──────────────────────────────────────────────── « ┌──────────┐┌──────────┐┌──────────┐┌──────────┐ «q_1: ┤ Rz(-π/2) ├┤ Rx(-π/2) ├┤ Rz(-π/2) ├┤ P(2.0*φ) ├ « └──────────┘└──────────┘└──────────┘└──────────┘ Duration of schedule with the calibration: 1600 Duration of standard with two CNOT gates: 6848 -
Les
DAGOpNode,DAGInNodeetDAGOutNodedéfinissent maintenant une méthode personnalisée__repr__qui produit une représentation. Selon la documentation de Python, la sortie est une représentation sous forme de chaîne qui est à peu près équivalente à la chaîne de Python utilisée pour créer un objet équivalent. -
Les performances de la méthode
SparsePauliOp.simplify()a été grandement améliorée en remplaçant l'utilisation denumpy.uniquepour calculer les éléments uniques d'un tableau par une nouvelle fonction similaire implémentée en Rust qui ne trie pas le tableau au préalable. -
Ajout d'une nouvelle méthode
equiv()à la classeSparsePauliOppour tester l'équivalence d'unSparsePauliOpavec un autre objetSparsePauliOpobjet. Contrairement à l'opérateur==qui compare les opérateurs par élément,equiv()compare si deux opérateurs sont équivalents ou non. Par exemple :op = SparsePauliOp.from_list([("X", 1), ("Y", 1)]) op2 = SparsePauliOp.from_list([("X", 1), ("Y", 1), ("Z", 0)]) op3 = SparsePauliOp.from_list([("Y", 1), ("X", 1)]) print(op == op2) # False print(op == op3) # False print(op.equiv(op2)) # True print(op.equiv(op3)) # True -
Ajout de nouvelles fausses classes de backend à partir d'instantanés des systèmes IBM Quantum basés sur l'interface
BackendV2et a fourni unTargetpour chaque backend.BackendV2de tous les backends existants sont ajoutées, à l'exception de trois anciens backendsFakeRueschlikon,FakeTenerifeetFakeTokyoqui ne disposent pas de fichiers snapshots, nécessaires à la création d'une nouvelle classe de backend basé surBackendV2.Ces nouveaux backends V2 permettront de tester et de développer de nouvelles fonctionnalités introduites par
BackendV2etTargettelles que l'amélioration du transpileur. -
Ajout d'une nouvelle classe de porte
XXMinusYYGateà la bibliothèque de circuits (qiskit.circuit.library) pour l'interaction XX-YY. Cette porte peut être utilisée pour implémenter la porte bSwap et ses pouvoirs. Elle apparaît également dans la simulation de modèles fermioniques supraconducteurs. -
Ajout d'une nouvelle classe de porte,
XXPlusYYGateà la bibliothèque de circuits (qiskit.circuit.library). Cette porte est une interaction XX+YY paramétrée à 2 qubits, également connue sous le nom de porte XY, et est basée sur la porte décrite dans https://arxiv.org/abs/1912.04424. -
Les faux backends
FakeBogota,FakeManila,FakeRome, etFakeSantiagoqui se trouvent dans le moduleqiskit.providers.fake_providerpeuvent maintenant être utilisés comme backends dans les expériences Pulse puisqu'ils incluent maintenant un backendPulseDefaultscréé à partir d'un instantané des propriétés de la machine IBM Quantum équivalente. -
La passe
ConsolidateBlocksa un nouveau mot-clé argument sur son constructeur,target. Cet argument est utilisé pour spécifier un objetTargetreprésentant la cible de compilation pour la passe. S'il est spécifié, il remplace le kwargbasis_gates. Si une cible est spécifiée, le pass respectera les portes et les qubits pour les instructions définies dans la cibleTargetlorsqu'il décidera des portes à consolider en unitaire. -
La classe
Targetdispose d'une nouvelle méthode,instruction_supported()qui permet d'interroger la cible pour savoir si une instruction (la combinaison d'une opération et du ou des qubits sur lesquels elle est exécutée) est prise en charge par le backend modélisé par la classeTarget. -
Ajout d'un nouveau kwarg,
metadata_serializer, à la fonctionqpy.dump()pour spécifier une sous-classe personnalisée deJSONEncoderà utiliser lors de la sérialisation de l'attributQuantumCircuit.metadataet un double kwarg,metadata_deserializer, à la fonctionqpy.load()pour spécifier une sous-classeJSONDecoder. Par défaut, les boutonsdump()etload()tenteront de sérialiser et de désérialiser JSON avec l'encodeur et le décodeur json par défaut de la stdlib. PuisqueQuantumCircuit.metadatapeut contenir n'importe quel dictionnaire Python, même ceux dont le contenu n'est pas sérialisable en JSON par l'encodeur par défaut, il en résultera des circuits qui ne pourront pas être sérialisés. Le nouvel argumentmetadata_serializerpourdump()permet aux utilisateurs de spécifier unJSONEncoderpersonnalisé qui sera utilisé avec l'appel internejson.dump()pour sérialiser leQuantumCircuit.metadatadictionnaire. Il peut ensuite être associé au nouvel argumentmetadata_deserializerde la fonctionqpy.load()pour décoder ces encodages JSON personnalisés. Simetadata_serializerest spécifié surdump()mais quemetadata_deserializern'est pas spécifié surload()le QPY sera chargé, mais les métadonnées du circuit risquent de ne pas être entièrement reconstituées.Par exemple, si vous voulez définir une sérialisation personnalisée pour les métadonnées et la charger ensuite, vous pouvez faire quelque chose comme :
from qiskit.qpy import dump, load from qiskit.circuit import QuantumCircuit, Parameter import json import io class CustomObject: """Custom string container object.""" def __init__(self, string): self.string = string def __eq__(self, other): return self.string == other.string class CustomSerializer(json.JSONEncoder): """Custom json encoder to handle CustomObject.""" def default(self, o): if isinstance(o, CustomObject): return {"__type__": "Custom", "value": o.string} return json.JSONEncoder.default(self, o) class CustomDeserializer(json.JSONDecoder): """Custom json decoder to handle CustomObject.""" def __init__(self, *args, **kwargs): super().__init__(*args, object_hook=self.object_hook, **kwargs) def object_hook(self, o): """Hook to override default decoder.""" if "__type__" in o: obj_type = o["__type__"] if obj_type == "Custom": return CustomObject(o["value"]) return o theta = Parameter("theta") qc = QuantumCircuit(2, global_phase=theta) qc.h(0) qc.cx(0, 1) qc.measure_all() circuits = [qc, qc.copy()] circuits[0].metadata = {"key": CustomObject("Circuit 1")} circuits[1].metadata = {"key": CustomObject("Circuit 2")} with io.BytesIO() as qpy_buf: dump(circuits, qpy_buf, metadata_serializer=CustomSerializer) qpy_buf.seek(0) new_circuits = load(qpy_buf, metadata_deserializer=CustomDeserializer) -
La passe
DenseLayouta un nouveau mot-clé argument sur son constructeur,target. Cet argument est utilisé pour spécifier un objetTargetreprésentant la cible de compilation pour la passe. S'il est spécifié, il remplace les autres arguments du constructeur,coupling_mapetbackend_prop. -
La classe
Targeta une nouvelle méthode,operation_names_for_qargs(). Cette méthode est utilisée pour obtenir les noms des opérations (c'est-à-dire la clé de consultation dans la cible) pour les opérations sur un tupleqargsdonné. -
Un nouveau laissez-passer
DynamicalDecouplingPaddinga été ajouté au moduleqiskit.transpiler.passesmodule. Ce nouveau laissez-passer remplace le laissez-passer existantDynamicalDecouplingexistante pour fonctionner avec le nouveau flux de travail d'ordonnancement dans le transpondeur. Il s'agit d'une sous-classe de la passeBasePaddinget dépend de l'exécution préalable des passes d'ordonnancement et d'analyse de l'alignement dans le cadre d'un processus d'ordonnancement et d'analyse de l'alignementPassManager. Cette nouvelle passe peut prendre un argumentpulse_alignmentqui représente une contrainte matérielle pour la synchronisation du début de la forme d'onde. L'espacement entre les portes comprenant une séquence de découplage dynamique est maintenant ajusté pour satisfaire cette contrainte afin que le circuit puisse être exécuté sur du matériel avec la contrainte. Cette valeur se trouve généralement à l'adresseBackendConfiguration.timing_constraints. En outre, la passe dispose également d'une optionextra_slack_distributionqui permet de contrôler comment distribuer le mou supplémentaire lorsque la durée de la séquence de découplage dynamique créée est plus courte que le temps d'inactivité de votre circuit que vous souhaitez remplir avec la séquence. La valeur par défaut estmiddle, ce qui est identique au comportement conventionnel. La nouvelle stratégiesplit_edgesrépartit uniformément le jeu supplémentaire entre le début et la fin de la séquence, au lieu de l'ajouter à l'intervalle au milieu de la séquence. Cela pourrait permettre une meilleure annulation du bruit, en particulier lorsquepulse_alignment> 1. -
La classe
Z2Symmetriesexpose maintenant les tolérances de seuil utilisées pour couper les petites parties réelles et imaginaires des coefficients. Cela permet de contrôler la manière dont les coefficients de l'opérateur conique sont simplifiés. Par exemple :from qiskit.opflow import Z2Symmetries from qiskit.quantum_info import Pauli z2_symmetries = Z2Symmetries( symmetries=[Pauli("IIZI"), Pauli("IZIZ"), Pauli("ZIII")], sq_paulis=[Pauli("IIXI"), Pauli("IIIX"), Pauli("XIII")], sq_list=[1, 0, 3], tapering_values=[1, -1, -1], tol=1e-10, )Par défaut, les coefficients sont hachés avec une tolérance de
tol=1e-14. -
Ajout d'une méthode
chop()à la classeSparsePauliOpqui tronque les parties réelles et imaginaires des coefficients individuellement. Cette méthode est différente de celle qui consiste à ne supprimer un coefficient que si sa valeur absolue est proche de 0SparsePauliOp.simplify()qui ne supprime un coefficient que si sa valeur absolue est proche de 0. Par exemple :>>> from qiskit.quantum_info import SparsePauliOp >>> op = SparsePauliOp(["X", "Y", "Z"], coeffs=[1+1e-17j, 1e-17+1j, 1e-17]) >>> op.simplify() SparsePauliOp(['X', 'Y'], coeffs=[1.e+00+1.e-17j, 1.e-17+1.e+00j]) >>> op.chop() SparsePauliOp(['X', 'Y'], coeffs=[1.+0.j, 0.+1.j])Notez que la méthode chop ne cumule pas les coefficients d'un même Paulis, par exemple
>>> op = SparsePauliOp(["X", "X"], coeffs=[1+1e-17j, 1e-17+1j) >>> op.chop() SparsePauliOp(['X', 'X'], coeffs=[1.+0.j, 0.+1.j]) -
Ajout d'un nouveau kwarg,
target, au constructeur de la passe deGatesInBasistranspiler pass. Ce nouvel argument peut être utilisé pour spécifier optionnellement un objetTargetqui représente le backend. Lorsqu'il est défini, ce paramètreTargetsera utilisé pour déterminer si unDAGCircuitcontient des portes en dehors de l'ensemble de base et l'argumentbasis_gatesne sera pas utilisé. -
Ajout d'une prise en charge partielle de l'exécution sur les plates-formes ppc64le et s390x Linux. Cette version commencera à publier des binaires précompilés pour les plateformes ppc64le et s390x Linux sur toutes les versions de Python. Cependant, contrairement aux autres plateformes supportées, toutes les dépendances en amont de Qiskit ne supportent pas encore ces plateformes. Un compilateur C/C++ peut donc être nécessaire pour construire et installer ces dépendances et un simple
pip install qiskit-terraavec un environnement Python fonctionnel ne sera pas suffisant pour installer Qiskit. En outre, ces mêmes contraintes nous empêchent de tester les roues précompilées avant de les publier, de sorte que les mêmes garanties concernant la prise en charge des plates-formes qui existent pour les autres plates-formes ne s'appliquent pas ici. -
Les
GradientetQFIpeuvent maintenant calculer la partie imaginaire des gradients de la valeur d'espérance. En cas d'utilisation d'une base de mesure différente, c'est-à-dire-Yau lieu deZ, nous pouvons mesurer la partie imaginaire des gradients La base de mesure peut être définie à l'aide de l'argumentaux_meas_op.Pour les gradients,
aux_meas_op = Zcalcule0.5Re[(⟨ψ(ω)|)O(θ)|dωψ(ω)〉]etaux_meas_op = -Ycalcule0.5Im[(⟨ψ(ω)|)O(θ)|dωψ(ω)〉]. Pour les QFI,aux_meas_op = Zcalcule4Re[(dω⟨<ψ(ω)|)(dω|ψ(ω)〉)]etaux_meas_op = -Ycalcule4Im[(dω⟨<ψ(ω)|)(dω|ψ(ω)〉)]. Par exemple :from qiskit import QuantumRegister, QuantumCircuit from qiskit.opflow import CircuitStateFn, Y from qiskit.opflow.gradients.circuit_gradients import LinComb from qiskit.circuit import Parameter a = Parameter("a") b = Parameter("b") params = [a, b] q = QuantumRegister(1) qc = QuantumCircuit(q) qc.h(q) qc.rz(params[0], q[0]) qc.rx(params[1], q[0]) op = CircuitStateFn(primitive=qc, coeff=1.0) aux_meas_op = -Y prob_grad = LinComb(aux_meas_op=aux_meas_op).convert(operator=op, params=params) -
La classe
InstructionDurationspermet désormais de travailler avec les paramètres d'une instruction. Chaque entrée d'un objetInstructionDurationsconsiste désormais en un tuple de(inst_name, qubits, duration, parameters, unit). Cela permet à unInstructionDurationsde définir les durées d'une instruction pour une certaine valeur de paramètre afin de tenir compte des différentes durées pour différentes valeurs de paramètre sur une instruction qui prend un paramètre numérique. -
Ajout d'une nouvelle valeur pour l'argument du mot-clé
styledans la fonction de dessinateur de circuitscircuit_drawer()etQuantumCircuit.draw()de la fonction et de la méthode "tiroir",iqx_dark. Lorsquestyleest configuré pouriqx_darkavec le tiroirmpl, la visualisation de sortie utilisera une palette de couleurs similaire à la palette de couleurs en mode sombre utilisée par le compositeur IBM Quantum. Par exemple :from qiskit.circuit import QuantumCircuit from matplotlib.pyplot import show circuit = QuantumCircuit(2) circuit.h(0) circuit.cx(0, 1) circuit.p(0.2, 1) circuit.draw("mpl", style="iqx-dark") -
Plusieurs vérificateurs de dépendances paresseuses ont été ajoutés au nouveau module
qiskit.utils.optionalsqui peut être utilisé pour vérifier si certaines fonctionnalités de Qiskit sont disponibles. Par exemple, vous pouvez demander si Qiskit a détecté la présence dematplotliben demandantif qiskit.utils.optionals.HAS_MATPLOTLIB. Ces objets ne tentent d'importer leurs dépendances que lorsqu'ils sont interrogés, de sorte que vous pouvez les utiliser dans le code d'exécution sans affecter le temps d'importation. -
Le temps d'importation pour
qiskita été considérablement amélioré, en particulier pour ceux qui ont installé de nombreuses dépendances optionnelles de Qiskit Terra. -
La fonction
marginal_counts()permet désormais de marginaliser le champmemoryd'un objet d'entréeResultd'un objet. Par exemple, si l'argument d'entréeresultest un objet qiskitResultobtenu à partir d'une mesure de 4 qubits, nous pouvons marginaliser le premier qubit avec :print(result.results[0].data.memory) marginal_result = marginal_counts(result, [0]) print(marginal_result.results[0].data.memory)La sortie est la suivante :
['0x0', '0x1', '0x2', '0x3', '0x4', '0x5', '0x6', '0x7'] ['0x0', '0x1', '0x0', '0x1', '0x0', '0x1', '0x0', '0x1'] -
Les éléments internes de l'algorithme
StochasticSwapont été réimplémentés pour être multithreadés et sont maintenant écrits dans le langage de programmation Rust au lieu de Cython. Cela permet d'augmenter considérablement les performances du compilateur et, par extension, celles de la passetranspile()lorsqu'il est exécuté avecoptimization_level0, 1 et 2. Par défaut, la passe utilisera jusqu'au nombre de CPU logiques de votre système local, mais vous pouvez contrôler le nombre de threads utilisés par la passe en fixant la variable d'environnementRAYON_NUM_THREADSà une valeur entière. Par exemple, l'adresseRAYON_NUM_THREADS=4permet d'exécuter le programmeStochasticSwapavec 4 threads. -
Une nouvelle variable d'environnement
QISKIT_FORCE_THREADSest disponible pour permettre aux utilisateurs de contrôler directement si les parties du code de Qiskit potentiellement multithreadées s'exécuteront dans plusieurs threads. Actuellement, cela n'est utilisé que par la passe de transpositionStochasticSwapmais il sera probablement utilisé par d'autres parties de Qiskit dans le futur. Lorsque cette variable ENV est définie àTRUE, tout code multithread dans Qiskit Terra utilisera toujours plusieurs threads, indépendamment de toute autre condition d'exécution qui aurait pu entraîner l'utilisation d'une variante à un seul thread. Par exemple, enStochasticSwapsi la passe est exécutée dans le cadre d'un appel detranspile()avec > 1 circuit qui est exécuté en parallèle avecmultiprocessingviaparallel_map()l'outilStochasticSwapn'utilisera pas de threads multiples afin d'éviter une sursouscription potentielle des ressources de l'unité centrale. Cependant, si vous souhaitez utiliser plusieurs threads dans la passe ainsi que plusieurs processus, vous pouvez définirQISKIT_FORCE_THREADS=TRUE. -
De nouvelles classes de faux backend sont disponibles à l'adresse
qiskit.providers.fake_provider. Il s'agit notamment des versions simulées deibm_cairo,ibm_hanoi,ibmq_kolkata,ibm_nairobietibm_washington. Comme pour les autres faux backends, ceux-ci comprennent des instantanés de données d'étalonnage et d'erreur provenant du système réel et peuvent être utilisés pour des tests, des compilations et des simulations au niveau local. -
Introduction d'une nouvelle classe
StatePreparation. Cette classe permet aux utilisateurs de préparer un état désiré de la même manière queInitializesans que la réinitialisation soit automatiquement appliquée.Par exemple, pour préparer un qubit dans l'état :
import numpy as np from qiskit import QuantumCircuit circuit = QuantumCircuit(1) circuit.prepare_state([1/np.sqrt(2), -1/np.sqrt(2)], 0) circuit.draw()Le résultat est le suivant :
┌─────────────────────────────────────┐ q_0: ┤ State Preparation(0.70711,-0.70711) ├ └─────────────────────────────────────┘ -
La passe de
Optimize1qGatesle transpileur supporte maintenant l'optimisation deU1Gate,U2Gate, etPhaseGateavec des paramètres non liés dans un circuit. Auparavant, si ces portes avaient des paramètres non liés, la passe ne les utilisait pas. Par exemple :from qiskit import QuantumCircuit from qiskit.circuit import Parameter from qiskit.transpiler import PassManager from qiskit.transpiler.passes import Optimize1qGates, Unroller phi = Parameter('φ') alpha = Parameter('α') qc = QuantumCircuit(1) qc.u1(2*phi, 0) qc.u1(alpha, 0) qc.u1(0.1, 0) qc.u1(0.2, 0) pm = PassManager([Unroller(['u1', 'cx']), Optimize1qGates()]) nqc = pm.run(qc)sera combiné au circuit avec une seule porte à qubit unique :
qc = QuantumCircuit(1) qc.u1(2*phi + alpha + 0.3, 0) -
Les méthodes
Pauli.evolve()etPauliList.evolve()disposent désormais d'un nouveau mot-clé,frame, qui est utilisé pour effectuer une évolution d'un Pauli par un Clifford. Siframe='h'(valeur par défaut), l'évolution de l'image de Heisenberg d'un Pauli par un Clifford ( ) est effectuée, et siframe='s', l'évolution de l'image de Schrödinger d'un Pauli par un Clifford ( ) est effectuée. Cette dernière option permet un calcul plus rapide et est également utile dans certains cas. Cette nouvelle option accélère considérablement le calcul de la méthode de décomposition de Clifford dansdecompose_clifford. -
Ajout d'un nouveau module à Qiskit :
qiskit.primitives. Le module primitif est celui dans lequel sont définies les API qui fournissent différentes abstractions autour du calcul de certaines fonctions communes à partir deQuantumCircuit, ce qui permet d'abstraire les détails de l'exécution sous-jacente surBackend. Cela permet aux algorithmes et aux applications de niveau supérieur de se concentrer sur l'exécution du calcul sans avoir à se préoccuper de l'exécution et du traitement des résultats, et de disposer d'une interface normalisée pour les calculs courants. Par exemple, l'estimation d'une valeur d'espérance d'un circuit quantique et d'un observable peut être effectuée par n'importe quelle classe mettant en œuvre cette classe et consommée de manière normalisée, quelle que soit la mise en œuvre sous-jacenteBaseEstimatoret consommée de manière normalisée, quelle que soit l'implémentation sous-jacente. Les applications peuvent alors être écrites en utilisant directement l'interface primitive.Pour commencer, le module contient deux types de primitives, les
Sampler(voirBaseSamplerpour la définition de la classe abstraite) etEstimator(voirBaseEstimatorpour la définition de la classe abstraite). Les implémentations de référence sont incluses dans le moduleqiskit.primitiveset sont construites à l'aide du moduleqiskit.quantum_infoqui réalisent une simulation idéale de l'opération primitive. On s'attend à ce que les fournisseurs proposent leurs propres implémentations de ces interfaces pour les fournisseurs qui peuvent efficacement mettre en œuvre le protocole de manière native (généralement en utilisant un moteur d'exécution classique). En outre, à l'avenir, pour les fournisseurs qui ne proposent pas d'implémentation native des primitives, une méthode sera fournie qui permettra de construire des objets primitifs à partir d'un fichierBackend. -
Ajout d'un nouveau module,
qiskit.qpyqui contient la fonctionnalité précédemment exposée dansqiskit.circuit.qpy_serialization. Les fonctions publiques précédemment exposées à l'adresseqiskit.circuit.qpy_serialization,dump()etload()sont désormais disponibles à partir de ce nouveau module (bien qu'elles soient toujours accessibles à partir deqiskit.circuit.qpy_serialization, mais cela sera supprimé dans une prochaine version). Ce nouveau module a été ajouté dans l'intérêt de l'orientation future du format de fichier QPY, qui, dans les versions ultérieures, permettra la représentation depulseScheduleetScheduleBlocken plus des objetsQuantumCircuitobjets qu'il prend en charge aujourd'hui. -
Ajout d'un nouvel attribut,
qubit_propertiesà la classeTargetclasse. Cet attribut contient une liste d'objetsQubitPropertiespour chaque qubit de la cible. Par exemple :target.qubit_properties[2]contiendra le
QubitPropertiespour le qubit numéro 2 de la cible.Pour les
BackendV2auteurs, si vous définissiez auparavantQubitPropertiesdirectement dans votre implémentationBackendV2en surchargeant l'implémentationBackendV2.qubit_properties()cela fonctionnera toujours. Toutefois, si vous déplacez la définition vers l'objet sous-jacentTargetet que vous supprimez l'implémentation spécialisée deBackendV2.qubit_properties()ce qui permettra d'utiliser les propriétés des qubits dans le transpileur et de maintenir la compatibilité API avec votre ancienne implémentation. -
Ajout d'une nouvelle fonction,
qiskit.algorithms.eval_observables()qui est utilisée pour évaluer les observables à partir d'une borneQuantumCircuit. Elle provient d'une méthode privée,_eval_aux_ops(), de la classeqiskit.algorithms.VQEmais la nouvelle fonctioneval_observables()est désormais plus générale et peut donc être utilisée dans d'autres algorithmes, par exemple les algorithmes d'évolution temporelle. -
La stratégie de recherche de base dans
BasisTranslatora été modifiée en une variante de la recherche de Dijkstra, ce qui améliore considérablement les performances d'exécution de la passe lorsqu'elle tente de cibler une base inaccessible. -
La passe de
DenseLayoutest désormais multithreadée, ce qui améliore grandement les performances d'exécution de la passe. Par défaut, il utilisera le nombre de CPU logiques de votre système local, mais vous pouvez contrôler le nombre de threads utilisés par la passe en fixant la variable d'environnementRAYON_NUM_THREADSà une valeur entière. Par exemple, l'adresseRAYON_NUM_THREADS=4permet d'exécuter la passeDenseLayoutavec 4 threads. -
Les calculs internes de
Statevector.expectation_value()etDensityMatrix.expectation_value()ont été réimplémentés dans le langage de programmation Rust. Cette nouvelle implémentation est multithreadée et, par défaut, pour un fichierStatevectorouDensityMatrix>= 19 qubits, un pool de threads est créé avec le nombre de CPU logiques disponibles sur le système local. Vous pouvez contrôler le nombre de threads utilisés en définissant la variable d'environnementRAYON_NUM_THREADSsur une valeur entière. Par exemple, le paramètreRAYON_NUM_THREADS=4n'utilisera que 4 threads dans le pool de threads. -
Ajout d'un nouveau constructeur
SparsePauliOp.from_sparse_list()qui prend un itérable, où les éléments représentent des termes de Pauli qui sont eux-mêmes épars, de sorte que"XIIIIIIIIIIIIIIIX"peut maintenant être écrit comme("XX", [0, 16]). Par exemple, l'opérateur
peut maintenant être construit comme suit
op = SparsePauliOp.from_sparse_list([("XZ", [0, 3], 1), ("YY", [1, 4], 2)], num_qubits=5)
# or equivalently, as previously
op = SparsePauliOp.from_list([("IZIIX", 1), ("YIIYI", 2)])Cela facilite la construction d'opérateurs très épars sur de nombreux qubits, comme c'est souvent le cas pour les hamiltoniens d'Ising.
-
La passe
UnitarySynthesisdispose d'un nouveau mot-clé dans son constructeur,target. Ceci peut être utilisé pour spécifier optionnellement un objetTargetqui représente la cible de compilation pour la passe. Lorsqu'elle est spécifiée, elle remplace les valeurs définies pourbasis_gates,coupling_mapetbackend_props. -
La classe
UnitarySynthesisPlugina un nouvel attribut optionnel que les implémentations peuvent ajouter,supports_target. Si un plugin a cet attribut défini surTrue, un objetTargetsera transmis dans la charge utileoptionssous le champtarget. On s'attend à ce que cet objetTargetsoit utilisé à la place decoupling_map,gate_lengths,basis_gates, etgate_errors. -
Introduction d'un nouveau flux de travail pour la construction d'objets pour la programmation
PassManagerd'objets pour l'ordonnancementQuantumCircuitdans le transpondeur. Dans le nouveau flux de travail, les passes d'ordonnancement et d'alignement sont toutes des objets qui ne font que mettre à jour l'ensemble des propriétés du gestionnaire de passesAnalysisPassqui ne font que mettre à jour l'ensemble des propriétés du gestionnaire de passes, en particulier le nouvel élément de l'ensemble des propriétésnode_start_time, qui contient l'heure de début absolue de chaque opnode. Un autreTransformationPassdistinct, tel quePadDelayest ensuite utilisé pour appliquer l'ordonnancement au DAG. Ce nouveau flux de travail est à la fois plus efficace et permet de corriger les contraintes de temps supplémentaires exposées par un backend.Auparavant, la chaîne de passage était mise en œuvre sous la forme de
scheduling -> alignment, qui étaient tous deux des passages de transformation, de sorte que plusieurs instances étaient recréées lors de chaque passageDAGCircuitinstances recréées lors de chaque passe. En outre, une programmation a été effectuée à chaque passage pour obtenir l'heure de début des instructions. La chaîne de passe requise devient alorsscheduling -> alignment -> paddingoù la mise à jour n'intervient qu'à la fin avec la passeDAGCircuitne se produit qu'à la fin avec la passepadding.Pour ceux qui créent des objets personnalisés
PassManagerqui impliquent un ordonnancement des circuits, vous devrez ajuster votrePassManagerpour insérer l'une des passesBasePadding(actuellement soitPadDelayouPadDynamicalDecouplingpeut être utilisé) à la fin de la chaîne de passes d'ordonnancement. Sans la passe de remplissage, les passes d'ordonnancement ne seront pas reflétées dans le circuit de sortie de la méthode de la méthode personnaliséerun()de votre méthode personnaliséePassManager.Par exemple, si vous construisiez auparavant votre
PassManageravec quelque chose comme :from qiskit.transpiler import PassManager from qiskit.transpiler.passes import TimeUnitConversion, ALAPSchedule, ValidatePulseGates, AlignMeasures pm = PassManager() scheduling = [ ALAPSchedule(instruction_durations), PadDelay()), ValidatePulseGates(granularity=timing_constraints.granularity, min_length=timing_constraints.min_length), AlignMeasures(alignment=timing_constraints.acquire_alignment), ] pm.append(scheduling)vous pouvez utiliser à la place :
from qiskit.transpiler import PassManager from qiskit.transpiler.passes import TimeUnitConversion, ALAPScheduleAnalysis, ValidatePulseGates, AlignMeasures, PadDelay pm = PassManager() scheduling = [ ALAPScheduleAnalysis(instruction_durations), PadDelay()), ConstrainedReschedule(acquire_alignment=timing_constraints.acquire_alignment, pulse_alignment=timing_constraints.pulse_alignment), ValidatePulseGates(granularity=timing_constraints.granularity, min_length=timing_constraints.min_length), PadDelay() ] pm.append(scheduling)qui sera à la fois plus efficace et alignera les instructions en fonction des contraintes matérielles.
-
Ajout d'un nouveau pass transpiler
ConstrainedReschedulepass. La passeConstrainedRescheduleprend en compte les contraintes d'alignement du matériel qui peuvent être définies dans un objet, etBackendConfigurationpulse_alignmentetacquire_alignment. Cette nouvelle classe remplace l'ancienne classeAlignMeasurescar elle effectue le même alignement (via le jeu de propriétés) pour les instructions de mesure en plus de l'alignement général des instructions. En définissant l'argument de la contrainteacquire_alignmentpour la passeConstrainedRescheduleil est possible de remplacer directementAlignMeasureslorsqu'il est associé à une nouvelle passeBasePadding. -
Ajout de deux nouvelles passes de transpilateur
ALAPScheduleAnalysisetASAPScheduleAnalysisqui supplantent les passesALAPScheduleetASAPScheduledans le cadre de la refonte du flux de travail du transpileur pour schedling. Les nouvelles passes effectuent le même ordonnancement, mais dans l'ensemble des propriétés et en s'appuyant sur une passeBasePaddingpour ajuster le circuit sur la base de toutes les analyses d'alignement de l'ordonnancement.Le comportement standard de ces passes aligne également l'ordre temporel sur l'ordre topologique des nœuds du DAG. Ce changement peut affecter le résultat de l'ordonnancement s'il comprend des opérations conditionnelles ou la mesure simultanée de deux qubits avec le même registre classique (cas limite). Pour reproduire le comportement conventionnel, réglez
clbit_write_latencysur une longueur identique à celle de l'instruction de mesure.Par exemple, considérons la programmation d'un circuit d'entrée comme :
┌───┐┌─┐ q_0: ┤ X ├┤M├────────────── └───┘└╥┘ ┌───┐ q_1: ──────╫────┤ X ├────── ║ └─╥─┘ ┌─┐ q_2: ──────╫──────╫─────┤M├ ║ ┌────╨────┐└╥┘ c: 1/══════╩═╡ c_0=0x1 ╞═╩═ 0 └─────────┘ 0from qiskit import QuantumCircuit from qiskit.transpiler import InstructionDurations, PassManager from qiskit.transpiler.passes import ALAPScheduleAnalysis, PadDelay, SetIOLatency from qiskit.visualization.timeline import draw circuit = QuantumCircuit(3, 1) circuit.x(0) circuit.measure(0, 0) circuit.x(1).c_if(0, 1) circuit.measure(2, 0) durations = InstructionDurations([("x", None, 160), ("measure", None, 800)]) pm = PassManager( [ SetIOLatency(clbit_write_latency=800, conditional_latency=0), ALAPScheduleAnalysis(durations), PadDelay(), ] ) draw(pm.run(circuit))Comme vous pouvez le voir sur la ligne de temps, la mesure sur
q_2commence avant la porte X conditionnelle surq_1, ce qui semble contraire à l'ordre topologique du nœud. C'est également un comportement attendu car l'accès en écriture de clbit se fait sur le front de fin de l'instruction de mesure, et l'accès en lecture de la porte conditionnelle se fait sur le front de début de l'instruction. Ainsi, l'ordre topologique est préservé sur le timeslot du registre classique, ce qui n'est pas pris en compte par la vue chronologique. Toutefois, cela suppose une conception particulière de la microarchitecture, et le circuit n'est pas nécessairement programmé de cette manière.En utilisant la configuration par défaut des passes, le circuit est programmé comme ci-dessous.
from qiskit import QuantumCircuit from qiskit.transpiler import InstructionDurations, PassManager from qiskit.transpiler.passes import ALAPScheduleAnalysis, PadDelay from qiskit.visualization.timeline import draw circuit = QuantumCircuit(3, 1) circuit.x(0) circuit.measure(0, 0) circuit.x(1).c_if(0, 1) circuit.measure(2, 0) durations = InstructionDurations([("x", None, 160), ("measure", None, 800)]) pm = PassManager([ALAPScheduleAnalysis(durations), PadDelay()]) draw(pm.run(circuit))Notez que clbit est verrouillé pendant toute la durée de l'intervalle d'instruction de mesure. Ce comportement est basé sur le Qiskit Pulse, dans lequel l'instruction d'acquisition prend
AcquireChanneletMemorySlotqui ne sont pas autorisés à se chevaucher avec d'autres instructions, c'est-à-dire que l'accès simultané à la mémoire à partir des différentes instructions est interdit. Cela permet également de toujours aligner l'ordre temporel sur l'ordre topologique des nœuds. -
Ajout d'une nouvelle passe de transpilation
PadDynamicalDecouplingqui remplace la passeDynamicalDecouplingdans le cadre de la refonte du flux de travail du transpileur pour l'ordonnancement. Cette nouvelle passe insère des séquences de découplage dynamique dans le circuit en fonction de l'analyse de l'ordonnancement et de l'alignement effectuée lors des passes précédentes. -
La fonction de
plot_gate_map()fonction de visualisation et les fonctions construites au-dessus d'elle,plot_error_map()etplot_circuit_layout()ont un nouveau mot-clé,qubit_coordinates. Cet argument prend une séquence de coordonnées 2D à utiliser pour tracer chaque qubit dans le backend visualisé. Si elle est spécifiée, cette séquence doit avoir une longueur égale au nombre de qubits sur le backend et elle sera utilisée à la place du comportement par défaut. -
La fonction de
plot_gate_map()fonction de visualisation et les fonctions construites au-dessus d'elle,plot_error_map()etplot_circuit_layout()sont maintenant capables de tracer n'importe quel backend et pas seulement ceux dont le nombre de qubits est égal à l'un des backends de IBM. Elle s'appuie sur la fonction retworkxspring_layout()pour générer la mise en page de la visualisation. Si la présentation par défaut ne fonctionne pas avec le graphe de couplage particulier d'un backend, vous pouvez utiliser la fonctionqubit_coordinatespour définir une présentation personnalisée. -
La fonction de
plot_gate_map()fonction de visualisation et les fonctions construites au-dessus d'elle,plot_error_map()etplot_circuit_layout()sont maintenant capables de fonctionner avec un backend basé surBackendV2sont maintenant en mesure de fonctionner avec un backend basé sur le Auparavant, ces fonctions ne fonctionnaient qu'avec les backends basés surBaseBackendouBackendV1ou avec des backends basés sur la technologie -
Ajout d'une nouvelle passe de transpilateur,
SetIOLatency. Cette passe prend deux argumentsclbit_write_latencyetconditional_latencypour définir la latence des E/S pour les bits classiques et les conditions classiques sur un backend. Cette passe définira ensuite ces valeurs dans l'ensemble des propriétés du gestionnaire de passe afin de permettre aux passes d'ordonnancement et d'alignement suivantes de corriger ces latences et de fournir une sortie d'ordonnancement plus précise d'un circuit dynamique. -
Un nouveau passeur de transpondeur
PadDelaya été ajoutée. Cette passe remplit les temps morts sur les fils des qubits avec des instructionsDelayinstructions. Cette passe fait partie du nouveau flux de travail pour l'ordonnancement des passes dans le transpileur et dépend d'une passe d'analyse d'ordonnancement (telle queALAPScheduleAnalysisouASAPScheduleAnalysis) et de toutes les passes d'alignement (telles queConstrainedReschedule) à exécuter avantPadDelay. -
La passe
VF2Layouttranspiler a un nouvel argument clé,target, qui est utilisé pour fournir unTargetpour la passe. Lorsqu'il est spécifié, leTargetsera utilisé par le pass pour toutes les informations sur le périphérique cible. Si elle est spécifiée, l'optiontargetaura la priorité sur les argumentscoupling_mapetproperties. -
Permettre l'utilisation de callables comme optimiseurs dans
VQEetQAOA. Maintenant, l'optimiseur peut être soit l'un des optimiseurs de Qiskit, tel queSPSAsoit un appelable avec la signature suivante :from qiskit.algorithms.optimizers import OptimizerResult def my_optimizer(fun, x0, jac=None, bounds=None) -> OptimizerResult: # Args: # fun (callable): the function to minimize # x0 (np.ndarray): the initial point for the optimization # jac (callable, optional): the gradient of the objective function # bounds (list, optional): a list of tuples specifying the parameter bounds result = OptimizerResult() result.x = # optimal parameters result.fun = # optimal function value return resultLa signature ci-dessus permet également de passer directement n'importe quel minimiseur SciPy, par exemple en tant que
from functools import partial from scipy.optimize import minimize optimizer = partial(minimize, method="L-BFGS-B")
Problèmes connus
- Lors de l'exécution
parallel_map()(ce qui est fait en interne par des fonctions sensibles aux performances telles quetranspile()etassemble()) dans un sous-processus lancé en dehors deparallel_map()il est possible que le traitement parallèle effectué à l'intérieur deparallel_map()se bloque et ne revienne jamais. Cela est dû à des problèmes en amont dans CPython concernant la méthode par défaut pour lancer des sous-processus sur Linux et macOS avec Python 3.7 (voir https://bugs.python.org/issue40379 pour plus de détails). Si vous rencontrez ce problème, vous avez deux options : vous pouvez soit supprimer les processus parallèles imbriqués, car l'appel àparallel_map()à partir d'un processus principal devrait fonctionner correctement; soit vous appelez manuellement le modulemultiprocessingde la bibliothèque standard CPython pour effectuer une distribution parallèle similaire à partir d'un sous-processus, mais utilisez les méthodes de lancement"spawn"ou"forkserver"pour éviter que les choses ne se bloquent et ne reviennent jamais.
Mise à niveau
-
Les classes
Qubit,ClbitetAncillaQubitpossèdent désormais l'attribut__slots__. Cela permet de réduire l'utilisation de la mémoire. Par ailleurs, il n'est plus possible d'y attacher des données arbitraires en tant qu'attributs. Il est très peu probable que cela ait un effet sur le code en aval autre que des avantages en termes de performances. -
La dépendance principale
retworkxa vu sa version requise passer de 0.10.1 à 0.11.0. Cela permet d'améliorer les performances de la passe de transpilationConsolidateBlocks. -
La version minimale supportée de
symengineest désormais 0.9.0. Cette modification était nécessaire pour améliorer la compatibilité avec le modulepicklede Python, qui est utilisé en interne dans le cadre de la répartition parallèle avec le moduleparallel_map(). -
La valeur par défaut de
QISKIT_PARALLELlors de l'exécution avec Python 3.9 sur Linux est maintenant fixée àTRUE. Cela signifie que lorsque l'on exécuteparallel_map()ou des fonctions qui l'appellent en interne, telles quetranspile()etassemble()la fonction sera exécutée dans plusieurs processus et devrait avoir de meilleures performances d'exécution. Ce changement a été effectué parce que les problèmes de fiabilité du dispatching parallèle semblent avoir été résolus (voir #6188 pour plus de détails). Si vous rencontrez encore des problèmes à cause de cela, vous pouvez désactiver le multiprocessing et revenir au comportement par défaut précédent en définissant la variable d'environnementQISKIT_PARALLELàFALSE, ou en définissant l'optionparallelàFalsedans votre fichier de configuration utilisateur (veuillez également déposer un problème afin que nous puissions suivre tous les problèmes liés au multiprocessing). -
La classe de porte
MSGate, précédemment dépréciée, que l'on trouvait dansqiskit.circuit.librarya été supprimée. Il était à l'origine obsolète dans la version 0.16.0. Il est préférable d'utiliser la classeGMScar elle permet de créer une porte MS équivalente pour 2 qubits en plus d'une porteMSGatepour n'importe quel nombre de qubits. -
La méthode
mirror()de la classeInstructiona été supprimée. Il était à l'origine obsolète dans la version 0.15.0. Au lieu de cela, vous devez utiliserInstruction.reverse_ops(). -
La méthode
num_ancilla_qubits(), précédemment obsolète, de l'élémentqiskit.circuit.library.PiecewiseLinearPauliRotationsetqiskit.circuit.library.WeightedAddera été supprimée. Il était à l'origine obsolète dans la version 0.16.0. Les méthodesPiecewiseLinearPauliRotations.num_ancillas()etWeightedAdder.num_ancillas()doivent être utilisées à la place. -
L'argument
reversedu constructeur de la classePolynomialPauliRotationsa été supprimé. Il était à l'origine obsolète dans la version 0.15.0. Au lieu de cela, vous devez utiliser la méthodeQuantumCircuit.reverse_bits()pour inverser le circuitPolynomialPauliRotationssi nécessaire. -
L'argument
angle, précédemment déprécié, des constructeurs de l'élémentC3SXGateetC3XGatea été supprimé. Il était à l'origine obsolète dans la version 0.17.0. Au lieu de cela, pour les portes X fractionnaires à 3 commandes, vous pouvez utiliser la méthodeC3XGate.power(). -
Prise en charge de l'utilisation des objets
np.ndarraydans le cadre de l'attributparamsd'un objetGatea été supprimée. Ceci est obsolète depuis Qiskit Terra 0.16.0 et ne fonctionne plus. Au lieu de cela, il faut créer une nouvelle sous-classe deGateet autoriser explicitement une entréenp.ndarrayen surchargeant la méthodevalidate_parameter()en surchargeant la méthode -
Un nouveau supplément
csp-layout-passa été ajouté à la cible d'installation depip install qiskit-terraet est également inclus dans le supplémentall. Ceci n'a pas d'effet dans Qiskit Terra 0.20, mais à partir de Qiskit Terra 0.21, les dépendances nécessaires uniquement pour le passage du transpilateur seront déclassées d'exigences à optionnellesCSPLayoutseront déclassées d'exigences en optionnelles, et installées par cet extra. Vous pouvez préparer un paquet qui dépend de cette passe en définissant ses exigences (ou la commandepip install) pour ciblerqiskit-terra[csp-layout-pass]. -
La prise en charge de l'exécution avec Python 3.6 a été supprimée. Pour faire fonctionner Qiskit, vous avez besoin d'une version minimale de Python de 3.7.
-
Le
AmplitudeEstimatorhérite maintenant de la classeABCde la bibliothèque standard Python. Cela oblige toute sous-classe à implémenter la méthodeestimate()alors que cela n'était pas nécessaire auparavant. Cela s'explique par le fait qu'à l'origine, la classe devait toujours être une classe enfant deABC, car la classeestimate()est nécessaire au fonctionnement d'un objetAmplitudeEstimatorobjet. Cependant, si vous définissiez auparavant uneAmplitudeEstimatorqui n'implémentait pasestimate()il en résultera une erreur. -
L'erreur soulevée par
HoareOptimizersi la dépendance optionnellez3n'est pas disponible est passée deTranspilerErroràMissingOptionalLibraryError(qui est à la fois unQiskitErroret unImportError). Ceci a été fait pour être cohérent avec les autres dépendances optionnelles. -
Sur Linux, le support minimum de la bibliothèque a été augmenté de manylinux2010 VM à manylinux2014. Cela reflète des changements similaires dans Numpy et Scipy. Il ne devrait pas y avoir d'effet significatif pour la plupart des utilisateurs, à moins que votre système ne contienne encore une très ancienne version de
glibc. -
La fonction
marginal_counts()lorsqu'elle est appelée avec un objetResultmarginalisera désormais le champmemorydes données de l'expérience s'il est défini dans l'entréeResult. Auparavant, le champmemorydans l'entrée n'était pas marginalisé. Cette modification a été apportée parce que le comportement précédent faisait que le champcountsne correspondait pas au champmemoryaprès l'appel de la fonctionmarginal_counts()a été appelé. Si le comportement précédent est souhaité, il peut être rétabli en définissantmarginalize_memory=Noneen tant qu'argument demarginal_counts()ce qui ne marginalisera pas le champmemory. -
Le passage du transpondeur peut donner des résultats différents avec la même valeur de semence
StochasticSwappeut donner des résultats différents avec la même valeur de départ. Cela est dû à la réécriture interne de la passe de transposition afin d'améliorer les performances d'exécution. Cependant, cela signifie que si vous avez exécutétranspile()avecoptimization_level0, 1 (la valeur par défaut), ou 2 avec une valeur définie pourseed_transpiler, vous pouvez obtenir une sortie avec un mappage de swap différent après la mise à jour vers Qiskit Terra 0.20.0. -
Pour construire Qiskit Terra à partir des sources, un compilateur Rust est maintenant nécessaire. Ceci est dû à la réécriture interne de la passe du transpileur qui améliore grandement les performances d'exécution du transpileur
StochasticSwapqui améliore considérablement les performances d'exécution du transpileur. Le compilateur rust peut être facilement installé à l'aide de rustup, qui peut être trouvé ici : https://rustup.rs/ -
L'attribut
namede la classePauliEvolutionGatea été modifié pour être toujours"PauliEvolution". Ce changement a été fait pour être cohérent avec les autres portes de Qiskit et permet aux autres parties de Qiskit d'identifier rapidement quand une opération particulière dans un circuit est unPauliEvolutionGate. Par exemple, il permet de dérouler les portes d'évolution de Pauli.Auparavant, le nom contenait les opérateurs qui sont évolués, ce qui est maintenant disponible via l'attribut
PauliEvolutionGate.labelattribut. Si l'on dessine un circuit avec unPauliEvolutionGateest dessiné, la porte indiquera toujours la même information, à savoir quelles portes sont en cours d'évolution. -
Les méthodes précédemment dépréciées :
qiskit.algorithms.VQE.get_optimal_costqiskit.algorithms.VQE.get_optimal_circuitqiskit.algorithms.VQE.get_optimal_vectorqiskit.algorithms.VQE.optimal_paramsqiskit.algorithms.HamiltonianPhaseEstimationResult.most_likely_phaseqiskit.algorithms.PhaseEstimationResult.most_likely_phase
qui étaient à l'origine dépréciées dans la version de Qiskit Terra 0.18.0 ont été supprimées et ne fonctionneront plus.
-
La classe
qiskit.algorithms.VariationalAlgorithmest désormais définie comme une classe de base abstraite (ABC) qui obligera les classes qui en héritent à définir une méthode getter et setterVariationalAlgorithm.initial_point. -
Le kwarg
pass_managerpour la fonctiontranspile()a été supprimé. Il était à l'origine obsolète dans la version 0.13.0. La meilleure façon de transpiler un circuit avec un objet personnalisé est d'utiliser l'objetPassManagerest d'utiliser la méthoderun()de l'objetPassManagerobjet. -
La classe
ParametrizedSchedule, précédemment obsolète, a été supprimée et n'existe plus. Cette classe a été supprimée lors de la publication de la version 0.17.0. Au lieu d'utiliser cette classe, vous pouvez paramétrer directementScheduleouScheduleBlocken spécifiant un objetParameterà l'argument de l'impulsion paramétrique. -
Le module
qiskit.circuit.library.probability_distributionsa été supprimé et n'existe plus selon la notice de dépréciation de qiskit-terra 0.17.0 (publiée le 1er avril 2021). Les classes concernées sontUniformDistribution,NormalDistributionetLogNormalDistribution. Ils sont tous déplacés dans la bibliothèque qiskit-finance, dans son module circuit library :qiskit_finance.circuit.library.probability_distributions. -
L'ancienne classe
qiskit.test.mock.fake_mumbai_v2.FakeMumbaiV2a été renomméeFakeMumbaiFractionalCXpour la différencier du faux backend basé sur le dispositif Mumbai,BackendV2pour le dispositif IBM Mumbai,qiskit.test.mock.backends.FakeMumbaiV2. Si vous utilisiez auparavant la classeFakeMumbaiV2pour obtenir un faux backend ayant des applications fractionnaires deCXGatedéfinies dans sa cible, vous devez utiliser la classeFakeMumbaiFractionalCXcar la classeFakeMumbaiV2n'aura plus ces définitions de portes supplémentaires dans son fichierTarget. -
Le résolveur utilisé par
QuantumCircuit.append()(et par conséquent toutes les méthodes qui ajoutent une instruction à unQuantumCircuit) pour convertir les spécificateurs de bits a été modifié pour le rendre plus rapide et plus fiable. Certaines constructions telles que :import numpy as np from qiskit import QuantumCircuit qc = QuantumCircuit(1, 1) qc.measure(np.array([0]), np.array([0]))fonctionneront désormais alors qu'ils auraient auparavant soulevé une erreur, mais certaines entrées pathologiques telles que :
from sympy import E, I, pi qc.x(E ** (I * pi))soulèveront désormais des erreurs alors qu'ils auraient pu réussir occasionnellement (par erreur) auparavant. Pour presque toutes les utilisations correctes, il ne devrait pas y avoir de changement notable, à l'exception d'une accélération générale.
-
La méthode interne semi-publique
QuantumCircuit._append()ne vérifie plus les types de ses entrées et suppose qu'il n'y a pas de doublons non valides dans ses listes d'arguments. Cette fonction est utilisée par certaines parties internes de Qiskit et d'autres bibliothèques pour construire des instances aussi rapidement que possible en sautant la vérification des erreurs lorsque les données sont déjà connues pour être correctesQuantumCircuitle plus rapidement possible en sautant la vérification des erreurs lorsque les données sont déjà connues pour être correctes. En général, les utilisateurs ou les fonctions qui reçoivent des données d'utilisateur doivent utiliser la méthode publicQuantumCircuit.append()qui résout les spécificateurs de bits entiers, diffuse ses arguments et vérifie l'exactitude des entrées. -
Cython n'est plus une dépendance de construction de Qiskit Terra et n'a plus besoin d'être installé lors de la construction de Qiskit Terra à partir des sources.
-
Les passmanagers prédéfinis en
qiskit.transpiler.preset_passmanagerspour tous les niveaux d'optimisation 2 et 3 tels que générés parlevel_2_pass_manager()etlevel_3_pass_manager()ont été modifiés de manière à ce que le gestionnaire de passe soit exécuté par défaut avant la passe de mise en pageVF2Layoutpar défaut avant la passe de mise en page. La passeVF2Layoutpermet de vérifier rapidement si une disposition parfaite peut être trouvée et remplace ce qui était fait auparavant pour les niveaux d'optimisation 2 et 3 qui utilisaient une combinaison deTrivialLayoutetCSPLayoutpour essayer de trouver une disposition parfaite. Il en résultera un comportement potentiellement différent lorsquetranspile()est appelé par défaut car il supprime un chemin par défaut pour tous les niveaux d'optimisation >=2 d'utilisation d'une disposition triviale (oùcircuit.qubits[0]est mappé au qubit physique 0,circuit.qubits[1]est mappé au qubit physique 1, etc) en supposant que la disposition triviale est parfaite. Si votre cas d'utilisation dépend de la disposition triviale, vous pouvez explicitement la demander lors de la transpilation en spécifiantlayout_method="trivial"lorsque vous appeleztranspile(). -
Le gestionnaire de passes prédéfini pour le niveau d'optimisation 1 (lors d'un appel à
transpile()avecoptimization_level=1ou lorsqu'aucun argumentoptimization_leveln'est défini) tel que généré parlevel_1_pass_manager()a été modifié de sorte queVF2Layoutest appelé par défaut pour vérifier rapidement si une disposition parfaite peut être trouvée avant que la commandeDenseLayout. Cependant, contrairement aux niveaux d'optimisation 2 et 3, une mise en page triviale est toujours tentée avant l'exécution du programmeVF2Layoutet s'il s'agit d'une correspondance parfaite, la sortie deVF2Layoutsera utilisée.
Remarques concernant la dépréciation
-
L'argument
max_creditsdeexecute()et toutes les configurations deQobj(par ex.QasmQobjConfigetPulseQobjConfig), est obsolète et sera supprimée dans une prochaine version. Le système de crédit n'a pas été utilisé sur IBM Quantum depuis deux ans, et l'option n'a aucun effet. Aucune alternative n'est nécessaire. Par exemple, si vous appelezexecute()comme :job = execute(qc, backend, shots=4321, max_credits=10)vous pouvez simplement omettre l'argument
max_credits:job = execute(qc, backend, shots=4321) -
L'utilisation d'un entier impair pour l'argument
orderdans le constructeur de la classeSuzukiTrotterest dépréciée et ne fonctionnera plus dans les versions ultérieures. Les formules de produit utilisées par leSuzukiTrotterne sont définies que lorsque l'ordre est pair, car les formules de produit de Suzuki sont symétriques. -
Les kwargs
qregs,cregs,layoutetglobal_phasedes classesMatplotlibDrawer,TextDrawingetQCircuitImage, ainsi que le kwargcalibrationsde la classeMatplotlibDrawer, sont désormais obsolètes et seront supprimés dans une version ultérieure.
Corrections des erreurs
-
Correction d'une erreur dans les fonctions de conversion des circuits
circuit_to_gate()etcircuit_to_instruction()(et leurs méthodes de circuit associéesQuantumCircuit.to_gate()etQuantumCircuit.to_instruction()) lorsqu'elles agissent sur un circuit avec des bits sans registre ou des bits dans plus d'un registre. -
Correction d'un problème où l'appel à
QuantumCircuit.copy()sur les circuits "body" d'une opération de flux de contrôle créée avec l'interface du constructeur provoquait une erreur. Par exemple, le message suivant, qui était auparavant une erreur, sera désormais renvoyé avec succès :from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister qreg = QuantumRegister(4) creg = ClassicalRegister(1) circ = QuantumCircuit(qreg, creg) with circ.if_test((creg, 0)): circ.h(0) if_else_instruction, _, _ = circ.data[0] true_body = if_else_instruction.params[0] true_body.copy() -
Ajout d'une entrée manquante dans la bibliothèque d'équivalence de session standard entre
CXGateetCPhaseGateainsi qu'entreCXGateetCRZGate. -
Correction d'un problème où l'exécution de l'opérateur
==entre deux objetsSparsePauliOpprovoquait une erreur lorsque les deux opérateurs avaient des nombres de coefficients différents. Par exemple :op = SparsePauliOp.from_list([("X", 1), ("Y", 1)]) op2 = SparsePauliOp.from_list([("X", 1), ("Y", 1), ("Z", 0)]) print(op == op2)Auparavant, cela aurait soulevé un
ValueErrorau lieu de renvoyerFalse. -
Correction de la prise en charge dans
transpile()pour passer un objetInstructionScheduleMapà l'objet sous-jacentPassManageren fonction de la méthodeTargetpourBackendV2sous-jacents. Auparavant, la fonctiontranspile()n'effectuait pas ce traitement et toutes les passes de transpilation qui ne permettent pas encore de travailler avec un objetTargetn'auraient pas accès aux calibrations d'impulsions par défaut pour les instructions d'un objetBackendV2backend. -
L'option
AmplitudeAmplifierest désormais correctement disponible à partir du module racineqiskit.algorithmsdirectement. Auparavant, il n'était pas inclus dans les classes réexportées du module racine et n'était accessible qu'à partir deqiskit.algorithms.amplitude_amplifiers. Correction #7751. -
Correction d'un problème avec le backend de
mplpour la fonction de tiroir de circuitcircuit_drawer()et la méthodeQuantumCircuit.draw()où les portes avec des conditions ne s'affichaient pas correctement lorsqu'un nombre suffisant de portes faisait basculer le tiroir sur une deuxième rangée. Corrigé : #7752. -
Correction d'un problème où la méthode
HHL.construct_circuit(), dans certaines conditions, ne renvoyait pas une valeur correcteQuantumCircuit. Auparavant, la fonction comportait une erreur d'arrondi dans le calcul du nombre de qubits nécessaires pour représenter les valeurs propres, ce qui entraînait une sortie incorrecte du circuit. -
Correction d'un bug d'endianness dans
BaseReadoutMitigator.expectation_value()lorsqu'une chaînediagonalest transmise. Il sera désormais correctement interprété en little endian de la même manière que le reste de Qiskit Terra, au lieu de big endian. -
Correction d'un problème avec le
quantum_info.partial_trace()lorsque la fonction a été invitée à ne tracer aucun sous-système, elle renverra désormais correctement leDensityMatrixde l'état d'entrée avec toutes les dimensions restantes plutôt que de générer une erreur. Corrigé #7613 -
Correction d'un problème avec le backend de
textpour la fonction de tiroir de circuitcircuit_drawer()et la méthodeQuantumCircuit.draw()lorsque des portes utilisant du texte latéral, telles que les portesCPhaseGateetRZZGateavec des conditions classiques, ne s'affichaient pas correctement. Correction #7532. -
Correction d'un problème avec la fonction
circuit_drawer()et la méthodedraw()de la méthodeQuantumCircuit. Lors de l'utilisation de l'optionreverse_bitsavec les optionsmpl,latexoutext, les bits sans registres ne s'affichaient pas dans le bon ordre. Correction #7303. -
Correction d'un problème dans la méthode
LocalReadoutMitigator.assignment_matrix()qui rejetait auparavant une valeur d'entrée pour l'argumentqubitsqui n'était pas une séquence triviale de qubits sous la forme :[0, 1, 2, ..., n-1]. Cette erreur a été corrigée de sorte que la méthode accepte désormais n'importe quelle liste d'indices de qubits à mesurer. -
Correction d'un problème dans le calcul de la valeur d'espérance de la méthode
StabilizerState.expectation_value()où la valeur de l'espérance de sortie était incorrecte si l'opérateur d'entrée de l'argument avait une phase non trivialePaulipour l'argumentoperavait une phase non triviale. Correction #7441. -
Une expression opflow contenant l'identité de Pauli
opflow.Ine produit plus de circuitIGatelorsqu'elle est convertie en circuit. Ce changement corrige une différence d'attente; la porte d'identité dans le circuit indique un retard, alors que dans le flux optique, nous nous attendons à une identité mathématique, c'est-à-dire à aucune opération. -
Les
PauliGaten'insère plus deIGatepour Paulis avec l'étiquette"I". -
PauliSumOples tests d'égalité gèrent désormais le cas où l'un des éléments comparés est un simplePauliOp. Par exemple,0 * X + I == Iest désormais évalué à True, alors qu'il était False avant cette version. -
Correction d'un problème avec les
ALAPScheduleetASAPSchedulelors de l'utilisation d'instructions pour lesquelles des calibrations d'impulsions personnalisées (c'est-à-dire des portes d'impulsions) ont été définies. Auparavant, les passes d'ordonnancement n'utilisaient pas la durée de l'étalonnage personnalisé des impulsions pour ces instructions, ce qui entraînait la génération d'un ordonnancement incorrect pour le circuit. Ce problème a été corrigé de sorte que les passes d'ordonnancement utilisent désormais la durée de l'étalonnage de l'impulsion personnalisée pour toute instruction dans le circuit qui a un étalonnage personnalisé. -
Correction de la prise en charge de l'utilisation de
ParameterExpressiondans la passe de transpositionRZXCalibrationBuildertranspiler pass. Auparavant, si un paramètre d'instruction comprenait une borneParameterExpressionla passe n'était pas en mesure de le gérer correctement. -
Arrêt de l'analyseur dans
QuantumCircuit.from_qasm_str()etfrom_qasm_file()d'accepter les programmes OpenQASM qui s'identifiaient comme provenant d'une version linguistique autre que 2.0. Cet analyseur ne concerne que OpenQASM 2.0; la prise en charge des circuits importés de OpenQASM 3.0 sera ajoutée dans une prochaine version. -
L'exportateur OpenQASM 3,
qasm3.Exporterévite désormais les noms de registres et de paramètres qui entrent en conflit avec les mots-clés réservés de OpenQASM 3 en générant un nouveau nom unique. Les registres et les paramètres portant le même nom ne seront plus confondus dans le code produit par l'exportateur OpenQASM 3. Correction #7742.
Aer 0.10.3
Pas de modification
Ignis 0.7.0
Pas de modification
IBM 0.18.3 du fournisseur Q
Pas de modification