Notas de la versión de Qiskit 0.35
0.35.0
Terra 0.20.0
Preludio
Los aspectos más destacados del lanzamiento de Qiskit Terra 0.20.0 son:
- La introducción de módulos multihilo escritos en Rust para acelerar el rendimiento de ciertas partes de Qiskit Terra y mejorar el escalado con un mayor número de qubits. Sin embargo, al compilar Qiskit a partir del código fuente, ahora se necesita un compilador de Rust.
- Más soporte nativo para trabajar con
Targeten el transpilador. Varios pases permiten ahora trabajar directamente con un objetoTargetlo que hace que el transpilador sea más robusto en cuanto a los tipos de backends a los que puede dirigirse. - La introducción del
qiskit.primitivesmódulo. Estas API ofrecen distintos niveles de abstracción para calcular resultados de interés a partir deQuantumCircuity utilizar backends. Por ejemplo, elBaseEstimatordefine una interfaz abstracta para estimar un valor de expectativa de un observable. Esto se puede utilizar para construir algoritmos de nivel superior y aplicaciones que se construyen utilizando la estimación de los valores de expectativa sin tener que preocuparse por la implementación de calcular el valor de expectativa. Este desacoplamiento permite que la implementación mejore en velocidad y calidad al tiempo que se adhiere a la interfaz abstracta definida. Asimismo, elBaseSamplercalcula distribuciones de cuasiprobabilidad a partir de mediciones de circuitos. En el futuro se introducirán otras primitivas.
Esta versión ya no es compatible con Python 3.6. Con esta versión, se requiere Python 3.7 a Python 3.10.
Nuevas funciones
-
Añadido un nuevo método constructor para la clase
OperatorclaseOperator.from_circuit()para crear un nuevoOperatora partir de un objetoQuantumCircuit. Aunque esto era posible normalmente utilizando el constructor por defecto, el métodoOperator.from_circuit()proporciona opciones adicionales para ajustar cómo se crea el operador. Principalmente permite permutar el orden de los qubits en función de un conjuntoLayout. Por ejemplo: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
operatortendrá los qubits permutados en función de la disposición de modo que sea idéntica a la devuelta porOperator(circuit)antes de la transpilación. -
Se ha añadido un nuevo método
DAGCircuit.copy_empty_like()a la claseDAGCircuitclase. Este método se utiliza para crear una nueva copia de un objetoDAGCircuitexistente con la misma estructura pero sin instrucciones. Este método es el mismo que el método privado_copy_circuit_metadata(), pero ahora forma parte de la API pública de la clase. -
Las clases de falso backend y falso proveedor que antes estaban disponibles en
qiskit.test.mockahora también están accesibles en un nuevo módulo:qiskit.providers.fake_provider. Este nuevo módulo sustituye al anteriorqiskit.test.mock, que quedará obsoleto en Qiskit 0.21.0. -
Añadida una nueva clase de puerta,
LinearFunctionque codifica eficientemente una función lineal (es decir, una función que puede ser representada por una secuencia deCXGateySwapGate). -
Añadido un nuevo pase de transpilador
CollectLinearFunctionsque recoge bloques deCXGateySwapGateconsecutivos en un circuito y sustituye cada bloque por una puertaLinearFunctionpuerta. -
Añadido un nuevo pase de transpilador
LinearFunctionsSynthesisque sintetiza cualquierLinearFunctionpuertas utilizando el algoritmo Patel-Markov-Hayes. Si se combina con elCollectLinearFunctionstranspiler pass esto permite recoger bloques deCXGateySwapGatede un circuito y resintetizarlos mediante el algoritmo Patel-Markov-Hayes. -
Añadido un nuevo pase de transpilador
LinearFunctionsToPermutationsque sustituye unaLinearFunctionpor un circuitoPermutationsiempre que sea posible. -
FlowController(comoConditionalController) pueden anidarse dentro de una instanciaPassManagercuando se utiliza el métodoPassManager.append()método Esto permite el uso de lógica anidada para controlar la ejecución de pases en elPassManager. Por ejemplo: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)El objeto
pmPassManagersólo ejecutará elBasisTranslatorpass (en el pasounroll) en cada iteración del bucle si se cumple elunroll_condition. -
Los constructores de los módulos
ZFeatureMapyZZFeatureMaptienen un nuevo argumento de palabra claveparameter_prefix. Este nuevo argumento se utiliza para fijar el prefijo de los parámetros del circuito de codificación de datos. Por ejemplo:from qiskit.circuit.library import ZFeatureMap feature_map = ZFeatureMap(feature_dimension=4, parameter_prefix="my_prefix") feature_map.decompose().draw('mpl')el circuito
ZFeatureMapha prefijado todos sus parámetros internos con el prefijo"my_prefix". -
El
TemplateOptimizationtranspiler pass ahora puede trabajar conGateque tienenParameterExpressionparámetros. Un ejemplo ilustrativo del uso deParameters conTemplateOptimizationes el siguiente: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)salidas
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 -
En
DAGOpNode,DAGInNodeyDAGOutNodedefinen ahora un método personalizado__repr__que genera una representación. Según la documentación de Python, la salida es una representación de cadena que es aproximadamente equivalente a la cadena Python utilizada para crear un objeto equivalente. -
El rendimiento del método
SparsePauliOp.simplify()ha mejorado considerablemente al sustituir el uso denumpy.uniquepara calcular los elementos únicos de una matriz por una nueva función similar implementada en Rust que no preordena la matriz. -
Se ha añadido un nuevo método
equiv()a la claseSparsePauliOppara comprobar la equivalencia de unSparsePauliOpcon otroSparsePauliOpobjeto. A diferencia del operador==que compara operadores elemento a elemento,equiv()compara si dos operadores son equivalentes o no. Por ejemplo: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 -
Añadidas nuevas clases falsas de backend a partir de instantáneas de los sistemas IBM Quantum basadas en la
BackendV2y proporcionó unTargetpara cada backend.BackendV2de todos los backends existentes, excepto los tres backends antiguosFakeRueschlikon,FakeTenerifeyFakeTokyo, ya que no disponen de los archivos de instantáneas necesarios para crear una nueva clase de backend falsa basada enBackendV2.Estos nuevos backends falsos de V2 permitirán probar y desarrollar las nuevas funciones introducidas por
BackendV2yTargetcomo la mejora del transpilador. -
Añadida una nueva clase de compuerta
XXMinusYYGatea la biblioteca de circuitos (qiskit.circuit.library) para la interacción XX-YY. Esta puerta puede utilizarse para implementar la puerta bSwap y sus potencias. También surge en la simulación de modelos fermiónicos superconductores. -
Añadida nueva clase gate,
XXPlusYYGatea la biblioteca de circuitos (qiskit.circuit.library). Esta puerta es una interacción XX+YY parametrizada de 2 qubits, también conocida como puerta XY, y está basada en la puerta descrita en https://arxiv.org/abs/1912.04424. -
Los backends falsos
FakeBogota,FakeManila,FakeRome, yFakeSantiagoque se pueden encontrar en el móduloqiskit.providers.fake_providerse pueden utilizar ahora como backends en los experimentos Pulse, ya que ahora incluyen un backendPulseDefaultscreado a partir de una instantánea de las propiedades de la máquina equivalente IBM Quantum. -
El pase
ConsolidateBlockspass tiene un nuevo argumento de palabra clave en su constructor,target. Este argumento se utiliza para especificar unTargetque representa el objetivo de compilación de la pasada. Si se especifica, sustituye al kwarg debasis_gates. Si se especifica un objetivo, el pase respetará las puertas y qubits de las instrucciones definidas en elTargeta la hora de decidir qué puertas consolidar en un unitario. -
La clase
Targettiene un nuevo método,instruction_supported()que se utiliza para consultar el objetivo y ver si una instrucción (la combinación de una operación y el qubit o qubits en los que se ejecuta) está soportada en el backend modelado por la claseTarget. -
Se ha añadido un nuevo kwarg,
metadata_serializer, a la funciónqpy.dump()para especificar una subclase personalizada deJSONEncoderque se utilizará al serializar el atributoQuantumCircuit.metadatay un kwarg doblemetadata_deserializera la funciónqpy.load()para especificar una subclase deJSONDecoder. Por defecto, los valoresdump()yload()intentarán serializar y deserializar JSON con el codificador y decodificador json por defecto de stdlib. Dado queQuantumCircuit.metadatapuede contener cualquier diccionario Python, incluso aquellos con contenidos no serializables en JSON por el codificador por defecto, dará lugar a circuitos que no pueden ser serializados. El nuevo argumentometadata_serializerparadump()permite a los usuarios especificar unJSONEncoderpersonalizado que se utilizará con la llamada internajson.dump()para serializar elQuantumCircuit.metadatadiccionario. Esto puede emparejarse con el nuevo argumentometadata_deserializerde la funciónqpy.load()para descodificar esas codificaciones JSON personalizadas. Si se especificametadata_serializerendump()pero no se especificametadata_deserializerenload()se cargará el QPY, pero es posible que los metadatos del circuito no se reconstruyan por completo.Por ejemplo si quisieras definir una serialización personalizada para metadatos y luego cargarla puedes hacer algo como:
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) -
El pase
DenseLayoutpass tiene un nuevo argumento de palabra clave en su constructor,target. Este argumento se utiliza para especificar unTargetque representa el objetivo de compilación de la pasada. Si se especifica, sustituye a los demás argumentos del constructor,coupling_mapybackend_prop. -
La clase
Targetclase tiene un nuevo método,operation_names_for_qargs(). Este método se utiliza para obtener los nombres de las operaciones (es decir, la clave de búsqueda en el destino) para las operaciones en una tuplaqargsdada. -
Se ha añadido un nuevo pase
DynamicalDecouplingPaddingal móduloqiskit.transpiler.passesmódulo. Este nuevo pase sustituye alDynamicalDecouplingexistente para trabajar con el nuevo flujo de trabajo de programación en el transpilador. Es una subclase del paseBasePaddingy depende de que los pases de análisis de programación y alineación se hayan ejecutado antes en un archivoPassManager. Este nuevo paso puede tomar un argumentopulse_alignmentque representa una restricción de hardware para la temporización de inicio de la forma de onda. El espaciado entre puertas que comprende una secuencia de desacoplamiento dinámico se ajusta ahora para satisfacer esta restricción, de modo que el circuito pueda ejecutarse en hardware con la restricción. Este valor suele encontrarse enBackendConfiguration.timing_constraints. Además, el pase también tiene una opciónextra_slack_distributionha sido controlar cómo distribuir la holgura extra cuando la duración de la secuencia de desacoplamiento dinámico creado es menor que el tiempo de inactividad de su circuito que desea llenar con la secuencia. Por defecto,middlees idéntico al comportamiento convencional. La nueva estrategiasplit_edgesdivide uniformemente la holgura extra entre el principio y el final de la secuencia, en lugar de añadirla al intervalo en mitad de la secuencia. Esto podría dar lugar a una mejor cancelación del ruido, especialmente cuandopulse_alignment> 1. -
La clase
Z2Symmetriesexpone ahora las tolerancias de umbral utilizadas para cortar pequeñas partes reales e imaginarias de los coeficientes. Con esto se puede controlar cómo se simplifican los coeficientes del operador cónico. Por ejemplo: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, )Por defecto, los coeficientes se trocean con una tolerancia de
tol=1e-14. -
Se ha añadido un
chop()a la claseSparsePauliOpque trunca las partes real e imaginaria de los coeficientes individualmente. Esto difiere del métodoSparsePauliOp.simplify()que elimina un coeficiente sólo si el valor absoluto es cercano a 0. Por ejemplo:>>> 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])Obsérvese que el método de la chuleta no acumula los coeficientes del mismo Paulis, por ejemplo.
>>> op = SparsePauliOp(["X", "X"], coeffs=[1+1e-17j, 1e-17+1j) >>> op.chop() SparsePauliOp(['X', 'X'], coeffs=[1.+0.j, 0.+1.j]) -
Añadido un nuevo kwarg,
target, al constructor para elGatesInBasistranspiler pass. Este nuevo argumento puede utilizarse para especificar opcionalmente un objetoTargetque representa el backend. Cuando se establece esteTargetse utilizará para determinar si unDAGCircuitcontiene puertas fuera del conjunto de bases y no se utilizará el argumentobasis_gates. -
Se ha añadido compatibilidad parcial con las plataformas ppc64le y s390x Linux. Esta versión empezará a publicar binarios precompilados para las plataformas ppc64le y s390x Linux en todas las versiones Python. Sin embargo, a diferencia de otras plataformas soportadas, no todas las dependencias de Qiskit soportan estas plataformas todavía. Así que puede ser necesario un compilador C/C++ para construir e instalar estas dependencias y un simple
pip install qiskit-terracon sólo un entorno Python no será suficiente para instalar Qiskit. Además, estas mismas limitaciones nos impiden probar las ruedas precompiladas antes de publicarlas, por lo que las mismas garantías de compatibilidad que existen para las demás plataformas no se aplican en este caso. -
En
GradientyQFIpueden calcular ahora la parte imaginaria de los gradientes del valor de expectativa. Cuando se utiliza una base de medición diferente, es decir-Yen lugar deZ, podemos medir la parte imaginaria de los gradientes La base de medición puede establecerse con el argumentoaux_meas_op.Para los gradientes,
aux_meas_op = Zcalcula0.5Re[(⟨ψ(ω)|)O(θ)|dωψ(ω)〉]yaux_meas_op = -Ycalcula0.5Im[(⟨ψ(ω)|)O(θ)|dωψ(ω)〉]. Para los QFI,aux_meas_op = Zcalcula4Re[(dω⟨<ψ(ω)|)(dω|ψ(ω)〉)]yaux_meas_op = -Ycalcula4Im[(dω⟨<ψ(ω)|)(dω|ψ(ω)〉)]. Por ejemplo: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 clase
InstructionDurationstiene ahora soporte para trabajar con parámetros de una instrucción. Cada entrada de un objetoInstructionDurationsconsiste ahora en una tupla de(inst_name, qubits, duration, parameters, unit). Esto permiteInstructionDurationsdefinir duraciones para una instrucción dado un cierto valor de parámetro para tener en cuenta diferentes duraciones con diferentes valores de parámetro en una instrucción que toma un parámetro numérico. -
Se ha añadido un nuevo valor para el argumento de la palabra clave
styleen la función de cajón de circuitoscircuit_drawer()y el métodoQuantumCircuit.draw()método,iqx_dark. Cuandostylese establece eniqx_darkcon el backend de cajónmpl, la visualización de salida utilizará un esquema de color similar al esquema de color de modo oscuro utilizado por el compositor IBM Quantum. Por ejemplo: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") -
Se han añadido al nuevo módulo varios comprobadores de dependencias perezosas
qiskit.utils.optionalsque pueden utilizarse para comprobar si determinadas funciones de Qiskit están disponibles. Por ejemplo, puedes preguntar si Qiskit ha detectado la presencia dematplotlibpreguntando aif qiskit.utils.optionals.HAS_MATPLOTLIB. Estos objetos sólo intentan importar sus dependencias cuando son consultados, por lo que puedes utilizarlos en código en tiempo de ejecución sin afectar al tiempo de importación. -
El tiempo de importación de
qiskitse ha mejorado significativamente, especialmente para aquellos con muchas de las dependencias opcionales de Qiskit Terra instaladas. -
La función
marginal_counts()permite ahora marginar el campomemoryde un objeto de entradaResultde entrada. Por ejemplo, si el argumento de entradaresultes un objeto qiskitResultobtenido a partir de una medición de 4 qubits, podemos marginar en el primer qubit con:print(result.results[0].data.memory) marginal_result = marginal_counts(result, [0]) print(marginal_result.results[0].data.memory)La salida es:
['0x0', '0x1', '0x2', '0x3', '0x4', '0x5', '0x6', '0x7'] ['0x0', '0x1', '0x0', '0x1', '0x0', '0x1', '0x0', '0x1'] -
El funcionamiento interno del algoritmo
StochasticSwaphan sido reimplementadas para ser multihilo y ahora están escritas en el lenguaje de programación Rust en lugar de Cython. Esto aumenta significativamente el rendimiento en tiempo de ejecución de la pasada del compilador y por extensióntranspile()cuando se ejecuta conoptimization_level0, 1 y 2. Por defecto, el pase utilizará hasta el número de CPUs lógicas de su sistema local, pero puede controlar el número de hilos utilizados por el pase configurando la variable de entornoRAYON_NUM_THREADScon un valor entero. Por ejemplo, configurandoRAYON_NUM_THREADS=4se ejecutará elStochasticSwapcon 4 hilos. -
Una nueva variable de entorno
QISKIT_FORCE_THREADSestá disponible para que los usuarios controlen directamente si las partes potencialmente multihilo del código de Qiskit se ejecutarán en múltiples hilos. Actualmente esto sólo es utilizado por elStochasticSwappero es probable que se utilice en otras partes de Qiskit en el futuro. Cuando esta variable env se establece enTRUEcualquier código multihilo en Qiskit Terra siempre utilizará múltiples hilos independientemente de cualquier otra condición de tiempo de ejecución que de otro modo podría haber causado que la función utilice una variante de un solo hilo. Por ejemplo, enStochasticSwapsi el pase se está ejecutando como parte de unatranspile()llamada con > 1 circuito que se está ejecutando en paralelo conmultiprocessinga través deparallel_map()elStochasticSwapno utilizará múltiples hilos para evitar una posible sobre-suscripción de recursos de CPU. Sin embargo, si desea utilizar varios subprocesos en la pasada junto con varios procesos, puede configurarQISKIT_FORCE_THREADS=TRUE. -
Las nuevas clases de backend falso están disponibles en
qiskit.providers.fake_provider. Se trata de versiones simuladas deibm_cairo,ibm_hanoi,ibmq_kolkata,ibm_nairobiyibm_washington. Al igual que los demás backends falsos, incluyen instantáneas de los datos de calibración y error tomados del sistema real, y pueden utilizarse para pruebas locales, compilación y simulación. -
Introducida una nueva clase
StatePreparation. Esta clase permite a los usuarios preparar un estado deseado de la misma manera queInitializesin que el restablecimiento se aplique automáticamente.Por ejemplo, para preparar un qubit en el estado :
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()La salida es como:
┌─────────────────────────────────────┐ q_0: ┤ State Preparation(0.70711,-0.70711) ├ └─────────────────────────────────────┘ -
El transpilador
Optimize1qGatestranspiler pass ahora tiene soporte para optimizarU1Gate,U2GateyPhaseGatecon parámetros no vinculados en un circuito. Anteriormente, si estas puertas tenían parámetros no vinculados, el pase no los utilizaba. Por ejemplo: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)se combinará al circuito con una sola puerta single-qubit:
qc = QuantumCircuit(1) qc.u1(2*phi + alpha + 0.3, 0) -
Los métodos
Pauli.evolve()yPauliList.evolve()tienen ahora un nuevo argumento de palabra clave,frame, que se utiliza para realizar una evolución de un Pauli por un Clifford. Siframe='h'(por defecto) entonces hace la evolución de la imagen de Heisenberg de un Pauli por un Clifford ( ), y siframe='s'entonces hace la evolución de la imagen de Schrödinger de un Pauli por un Clifford ( ). Esta última opción permite un cálculo más rápido y también es útil en algunos casos. Esta nueva opción hace que el cálculo del método de descomposición greedy Clifford endecompose_cliffordsea significativamente más rápido. -
Añadido un nuevo módulo a Qiskit:
qiskit.primitives. El módulo de primitivas es donde se definen las API que proporcionan diferentes abstracciones en torno a la computación de ciertas funciones comunes deQuantumCircuitque abstrae los detalles de la ejecución subyacente en unBackend. Esto permite a los algoritmos y aplicaciones de nivel superior concentrarse en realizar el cálculo y no tener que preocuparse por la ejecución y el procesamiento de los resultados, además de disponer de una interfaz estandarizada para los cálculos habituales. Por ejemplo, la estimación de un valor de expectativa de un circuito cuántico y observable puede ser realizada por cualquier clase que implemente la claseBaseEstimatory consumirse de manera estandarizada independientemente de la implementación subyacente. Las aplicaciones pueden escribirse utilizando directamente la interfaz primitiva.Para empezar el módulo contiene dos tipos de primitivas, la
Sampler(véaseBaseSamplerpara la definición de la clase abstracta) yEstimator(véaseBaseEstimatorpara la definición de la clase abstracta). Las implementaciones de referencia se incluyen en el móduloqiskit.primitivesy se construyen utilizando el móduloqiskit.quantum_infoque realizan una simulación ideal de la operación primitiva. Se espera que los paquetes de proveedores ofrezcan sus propias implementaciones de estas interfaces para los proveedores que puedan implementar eficazmente el protocolo de forma nativa (normalmente utilizando un tiempo de ejecución clásico). Además, en el futuro, para los proveedores que no ofrezcan una implementación nativa de las primitivas se proporcionará un método que permitirá construir objetos primitivos a partir de un archivoBackend. -
Se ha añadido un nuevo módulo
qiskit.qpyque contiene la funcionalidad anteriormente expuesta enqiskit.circuit.qpy_serialization. Las funciones públicas expuestas anteriormente enqiskit.circuit.qpy_serialization,dump()yload()están ahora disponibles desde este nuevo módulo (aunque siguen siendo accesibles desdeqiskit.circuit.qpy_serialization, pero esto quedará obsoleto en una futura versión). Este nuevo módulo se ha añadido en aras de la futura orientación del formato de archivo QPY, que en futuras versiones admitirá la representación depulseScheduleyScheduleBlockademás de los objetosQuantumCircuitobjetos que soporta actualmente. -
Se ha añadido un nuevo atributo
qubit_propertiesa la claseTargetclase. Este atributo contiene una lista deQubitPropertiesobjetos para cada qubit del objetivo. Por ejemplo:target.qubit_properties[2]contendrá el
QubitPropertiespara el qubit número 2 en el objetivo.Para los autores de
BackendV2autores, si antes definíanQubitPropertiesdirectamente en su implementaciónBackendV2anulandoBackendV2.qubit_properties()esto seguirá funcionando correctamente. Sin embargo, si traslada la definición al objeto subyacenteTargety elimina la implementación especializadaBackendV2.qubit_properties()lo que permitirá utilizar las propiedades qubit en el transpilador y también mantener la compatibilidad de la API con su implementación anterior. -
Se ha añadido una nueva función,
qiskit.algorithms.eval_observables()que se utiliza para evaluar observables dado un límiteQuantumCircuit. Se origina en un método privado,_eval_aux_ops(), de la claseqiskit.algorithms.VQEpero la nueva funcióneval_observables()es ahora más general para que pueda utilizarse en otros algoritmos, por ejemplo, algoritmos de evolución temporal. -
La estrategia de búsqueda de bases en
BasisTranslatortranspiler pass se ha modificado en una variante de la búsqueda Dijkstra que mejora enormemente el rendimiento en tiempo de ejecución del pass cuando se intenta apuntar a una base inalcanzable. -
El transpilador
DenseLayouttranspilador es ahora multihilo, lo que mejora en gran medida el rendimiento en tiempo de ejecución del pase. Por defecto, utilizará el número de CPUs lógicas de su sistema local, pero puede controlar el número de hilos utilizados por el pase estableciendo la variable de entornoRAYON_NUM_THREADSen un valor entero. Por ejemplo, configurandoRAYON_NUM_THREADS=4se ejecutará elDenseLayoutcon 4 hilos. -
Los cálculos internos de
Statevector.expectation_value()yDensityMatrix.expectation_value()se han reimplementado en el lenguaje de programación Rust. Esta nueva implementación es multihilo y, por defecto, para un archivoStatevectoroDensityMatrix>= 19 qubits generará un grupo de hilos con el número de CPU lógicas disponibles en el sistema local. Puede controlar el número de hilos utilizados configurando la variable de entornoRAYON_NUM_THREADScon un valor entero. Por ejemplo, configurandoRAYON_NUM_THREADS=4sólo se utilizarán 4 hilos en el pool de hilos. -
Se ha añadido un nuevo
SparsePauliOp.from_sparse_list()que toma un iterable, donde los elementos representan términos de Pauli que a su vez son dispersos, de modo que"XIIIIIIIIIIIIIIIX"ahora se puede escribir como("XX", [0, 16]). Por ejemplo, el operador
se puede construir ahora como
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)])Esto facilita la construcción de operadores muy dispersos en muchos qubits, como suele ser el caso de los Hamiltonianos de Ising.
-
El
UnitarySynthesistranspiler pass tiene un nuevo argumento de palabra clave en su constructor,target. Puede utilizarse para especificar opcionalmente un objetoTargetque representa el objetivo de compilación de la pasada. Cuando se especifique, sustituirá a los valores establecidos parabasis_gates,coupling_map, ybackend_props. -
La clase plugin abstracta
UnitarySynthesisPlugintiene un nuevo atributo opcional que las implementaciones pueden añadir,supports_target. Si un complemento tiene este atributo establecido enTrue, se pasará un objetoTargeten la carga útil deoptionsen el campotarget. Se espera que este objetoTargetse utilice en lugar decoupling_map,gate_lengths,basis_gatesygate_errors. -
Se ha introducido un nuevo flujo de trabajo de paso de transpilador para construir
PassManagerobjetos para programarQuantumCircuitobjetos en el transpilador. En el nuevo flujo de trabajo los pases de programación y alineación son todosAnalysisPassque sólo actualizan el conjunto de propiedades del gestor de pases, concretamente el nuevo elemento del conjunto de propiedadesnode_start_time, que contiene la hora de inicio absoluta de cada opnode. UnaTransformationPasscomoPadDelayse utiliza posteriormente para aplicar la programación al DAG. Este nuevo flujo de trabajo es más eficiente y puede corregir las restricciones de tiempo adicionales expuestas por un backend.Anteriormente, la cadena de pases se habría implementado como
scheduling -> alignmentque eran ambos pases de transformación por lo que había múltiplesDAGCircuitinstancias recreadas durante cada pasada. Además, en cada pasada se programaba la hora de inicio de las instrucciones. Ahora la cadena de pases requerida se convierte enscheduling -> alignment -> paddingdonde laDAGCircuitactualización sólo se produce al final con el pasepadding.Si crea objetos personalizados
PassManagerque impliquen la programación de circuitos tendrán que ajustar suPassManagerpara insertar uno de los pases deBasePadding(actualmentePadDelayoPadDynamicalDecoupling) al final de la cadena de pases de programación. Sin el pase de relleno los pases de programación no se reflejarán en el circuito de salida delrun()de su método personalizadoPassManager.Por ejemplo, si antes construía su
PassManagercon algo comofrom 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)puede utilizar en su lugar:
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)que será más eficiente y alineará las instrucciones en función de las restricciones del hardware.
-
Añadido un nuevo transpiler pass
ConstrainedReschedulepass. El pasoConstrainedReschedulepass considera tanto las restricciones de alineación del hardware que se pueden definir en unBackendConfigurationpulse_alignmentyacquire_alignment. Esta nueva clase sustituye a la anteriormente existenteAlignMeasuresya que realiza la misma alineación (a través del conjunto de propiedades) para instrucciones de medida además de la alineación general de instrucciones. Estableciendo el argumento de restricciónacquire_alignmentpara el paseConstrainedReschedulese puede sustituir directamente porAlignMeasurescuando se combina con un nuevo paseBasePadding. -
Añadidos dos nuevos pases de transpilador
ALAPScheduleAnalysisyASAPScheduleAnalysisque sustituyen a los pasesALAPScheduleyASAPSchedulecomo parte del nuevo flujo de trabajo del transpilador para schedling. Los nuevos pases realizan la misma programación pero en el conjunto de propiedades y confiando en un pase deBasePaddingpara ajustar el circuito basándose en todo el análisis de alineación de la programación.El comportamiento estándar de estos pases también alinea la ordenación temporal con la ordenación topológica de los nodos del DAG. Este cambio puede afectar al resultado de la programación si incluye operaciones condicionales o la medición simultánea de dos qubits con el mismo registro clásico (caso límite). Para reproducir el comportamiento convencional, configure
clbit_write_latencyde forma idéntica a la longitud de la instrucción de medida.Por ejemplo, considere programar un circuito de entrada como:
┌───┐┌─┐ 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))Como se puede ver en la vista de línea de tiempo, la medición en
q_2comienza antes de la puerta X condicional en elq_1, lo que parece ser opuesto al orden topológico del nodo. Este es también el comportamiento esperado porque el acceso de escritura de clbit ocurre en el extremo final de la instrucción de medida, y el acceso de lectura de la puerta condicional ocurre en el extremo inicial de la instrucción. De este modo, se conserva el orden topológico en la franja horaria del registro clásico, que no es capturado por la vista de la línea de tiempo. Sin embargo, esto supone un diseño de microarquitectura paticular, y el circuito no está necesariamente programado así.Utilizando la configuración por defecto de pases, el circuito queda programado como se muestra a continuación.
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))Tenga en cuenta que clbit está bloqueado durante todo el intervalo de instrucciones de medición. Este comportamiento está diseñado en base al Qiskit Pulse, en el que la instrucción acquire toma
AcquireChannelyMemorySlotque no pueden solaparse con otras instrucciones, es decir, está prohibido el acceso simultáneo a memoria desde las diferentes instrucciones. Esto también alinea siempre la ordenación temporal con la ordenación topológica de los nodos. -
Añadido un nuevo pase de transpilador
PadDynamicalDecouplingque sustituye alDynamicalDecouplingcomo parte del nuevo flujo de trabajo del transpilador para la programación. Esta nueva pasada insertará secuencias dinámicas de desacoplamiento en el circuito según cualquier análisis de programación y alineación que haya tenido lugar en pasadas anteriores. -
La función de visualización
plot_gate_map()función de visualización y las funciones construidas sobre ella,plot_error_map()yplot_circuit_layout()tienen un nuevo argumento clave,qubit_coordinates. Este argumento toma una secuencia de coordenadas 2D a utilizar para trazar cada qubit en el backend que se está visualizando. Si se especifica, esta secuencia debe tener una longitud igual al número de qubits del backend y se utilizará en lugar del comportamiento por defecto. -
La función de visualización
plot_gate_map()función de visualización y las funciones construidas sobre ella,plot_error_map()yplot_circuit_layout()son ahora capaces de trazar cualquier backend, no sólo aquellos con el número de qubits igual a uno de los backends de IBM. Esto se basa en la función retworkxspring_layout()para generar el diseño de la visualización. Si el diseño predeterminado no funciona con un gráfico de acoplamiento particular de un backend, puede utilizar la funciónqubit_coordinatespara establecer un diseño personalizado. -
La función de visualización
plot_gate_map()función de visualización y las funciones construidas sobre ella,plot_error_map()yplot_circuit_layout()son ahora capaces de funcionar con unBackendV2. Anteriormente, estas funciones sólo funcionaban conBaseBackendo con backends basados enBackendV1. -
Añadido un nuevo pase de transpilador,
SetIOLatency. Esta pasada toma dos argumentosclbit_write_latencyyconditional_latencypara definir la latencia de E/S para bits clásicos y condiciones clásicas en un backend. Este pase definirá entonces estos valores en el conjunto de propiedades del gestor de pases para permitir que los pases de programación y alineación posteriores corrijan estas latencias y proporcionen una salida de programación más precisa de un circuito dinámico. -
Se ha añadido un nuevo
PadDelayse ha añadido. Este paso llena el tiempo ocioso en los cables del qubit conDelayinstrucciones. Este pase forma parte del nuevo flujo de trabajo para la programación de pases en el transpilador y depende de un pase de análisis de programación (comoALAPScheduleAnalysisoASAPScheduleAnalysis) y de cualquier pase de alineación (comoConstrainedReschedule) que se ejecuten antes dePadDelay. -
El pase de transpilador
VF2Layoutpass del transpilador tiene un nuevo argumento de palabra clave,targetque se utiliza para proporcionar unTargetobjeto para el pase. Cuando se especifica, elTargetserá utilizado por el pase para toda la información sobre el dispositivo de destino. Si se especifica, la opcióntargettendrá prioridad sobre los argumentoscoupling_mapyproperties. -
Permitir callables como optimizadores en
VQEyQAOA. Ahora, el optimizador puede ser uno de los optimizadores de Qiskit, como por ejemploSPSAo un callable con la siguiente firma: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 firma anterior también permite pasar directamente cualquier minimizador de SciPy, por ejemplo como
from functools import partial from scipy.optimize import minimize optimizer = partial(minimize, method="L-BFGS-B")
Problemas conocidos
- Cuando se ejecuta
parallel_map()(lo que hacen internamente funciones sensibles al rendimiento comotranspile()yassemble()) en un subproceso lanzado fuera deparallel_map()es posible que el despacho paralelo realizado dentro deparallel_map()se cuelgue y nunca regrese. Esto se debe a problemas en CPython relacionados con el método por defecto para lanzar subprocesos en Linux y macOS con Python 3.7 (ver https://bugs.python.org/issue40379 para más detalles). Si te encuentras con esto, tienes dos opciones: puedes eliminar los procesos paralelos anidados, ya que llamar aparallel_map()desde un proceso principal debería funcionar bien; o puedes llamar manualmente al módulomultiprocessingde la biblioteca estándar de CPython para realizar un despacho paralelo similar desde un subproceso, pero utilizando los métodos de lanzamiento"spawn"o"forkserver"para evitar la posibilidad de que las cosas se atasquen y nunca vuelvan.
Notas de actualización
-
Las clases
Qubit,ClbityAncillaQubittienen ahora el atributo__slots__. Esto es para reducir su uso de memoria. Como efecto secundario, ya no pueden tener datos arbitrarios adjuntos como atributos. Es muy poco probable que esto tenga algún efecto en el código posterior, aparte de las ventajas de rendimiento. -
El requisito de versión de la dependencia principal
retworkxha pasado de 0.10.1 a 0.11.0. Esto mejora el rendimiento del pase de transpilaciónConsolidateBlocks. -
La versión mínima compatible de
symenginees ahora 0.9.0. Esto era necesario para mejorar la compatibilidad con el módulopicklede Python que se utiliza internamente como parte del envío paralelo conparallel_map(). -
El valor por defecto de
QISKIT_PARALLELcuando se ejecuta con Python 3.9 en Linux se establece ahora enTRUE. Esto significa que al ejecutarparallel_map()o funciones que lo llamen internamente, comotranspile()yassemble()la función se ejecutará en múltiples procesos y debería tener un mejor rendimiento en tiempo de ejecución. Este cambio se ha realizado porque parece que se han resuelto los problemas de fiabilidad del envío en paralelo (véase #6188 para más detalles). Si sigue teniendo problemas por este motivo, puede desactivar el multiprocesamiento y volver al comportamiento predeterminado anterior estableciendo la variable de entornoQISKIT_PARALLELenFALSE, o estableciendo la opciónparallelenFalseen su archivo de configuración de usuario (también puede enviar una incidencia para que podamos rastrear cualquier problema relacionado con el multiprocesamiento). -
Se ha eliminado la clase de compuerta
MSGateanteriormente obsoleta que se encontraba enqiskit.circuit.libraryha sido eliminada. Originalmente fue obsoleto en la versión 0.16.0. En su lugar debe utilizarse la claseGMSya que permite crear una puerta MS equivalente de 2 qubits además deMSGatepara cualquier número de qubits. -
El método
mirror()de la claseInstructionha sido eliminado. Originalmente fue obsoleto en la versión 0.15.0. En su lugar debe utilizarInstruction.reverse_ops(). -
El método
num_ancilla_qubits()de la directivaqiskit.circuit.library.PiecewiseLinearPauliRotationsyqiskit.circuit.library.WeightedAdderha sido eliminado. Originalmente fue obsoleto en la versión 0.16.0. En su lugar, deben utilizarse los métodosPiecewiseLinearPauliRotations.num_ancillas()yWeightedAdder.num_ancillas(). -
El argumento
reversedel constructor de la clasePolynomialPauliRotationsha sido eliminado. Originalmente fue obsoleto en la versión 0.15.0. En su lugar, debe utilizar el métodoQuantumCircuit.reverse_bits()para invertir el circuitoPolynomialPauliRotationscircuito si es necesario. -
El argumento
angle, anteriormente obsoleto, en los constructores de los módulosC3SXGateyC3XGateha sido eliminado. Originalmente fue obsoleto en la versión 0.17.0. En cambio, para las compuertas X fraccionarias controladas por 3 se puede utilizar el métodoC3XGate.power(). -
Compatibilidad con el uso de objetos
np.ndarraycomo parte del atributoparamsde un objetoGatese ha eliminado. Esto ha sido obsoleto desde Qiskit Terra 0.16.0 y ahora ya no funcionará. En su lugar, debería crearse una nueva subclase deGatey permitir explícitamente una entradanp.ndarraysobrecargando el métodovalidate_parameter()método -
Se ha añadido un nuevo extra
csp-layout-passal objetivo de instalación depip install qiskit-terra, y también se incluye en el extraall. Esto no tiene ningún efecto en Qiskit Terra 0.20, pero a partir de Qiskit Terra 0.21, las dependencias necesarias sólo para laCSPLayouttranspiler pass serán degradadas de requerimientos a opcionales, e instaladas por este extra. Puede preparar un paquete que dependa de este pase estableciendo sus requisitos (o el comandopip install) en el objetivoqiskit-terra[csp-layout-pass]. -
Se ha eliminado la compatibilidad con Python 3.6. Para ejecutar Qiskit necesitas una versión mínima de Python 3.7.
-
La clase
AmplitudeEstimatorhereda ahora de la claseABCde la biblioteca estándar Python. Esto requiere que cualquier subclase implemente el métodoestimate()cuando antes no era necesario. Esto se hizo porque la intención original de la clase era ser siempre una clase hija deABC, ya que la claseestimate()es necesario para el funcionamiento de un objetoAmplitudeEstimatorobjeto. Sin embargo, si antes definía una subclaseAmplitudeEstimatorque no implementabaestimate()se producirá un error. -
El error generado por
HoareOptimizersi la dependencia opcionalz3no está disponible ha cambiado deTranspilerErroraMissingOptionalLibraryError(que es a la vez unQiskitErroryImportError). Esto se hizo para ser coherente con las otras dependencias opcionales. -
En Linux, el soporte mínimo de biblioteca se ha aumentado de la VM manylinux2010 a manylinux2014. Esto refleja cambios similares en Numpy y Scipy. No debería haber ningún efecto significativo para la mayoría de los usuarios, a menos que su sistema aún contenga una versión muy antigua de
glibc. -
La función
marginal_counts()cuando se llama con un objetoResultobjeto de entrada, ahora marginará el campomemoryde los datos del experimento si se establece en la entradaResult. Anteriormente, el campomemoryde la entrada no estaba marginado. Este cambio se ha realizado porque el comportamiento anterior provocaba que el campocountsno coincidiera con el campomemorydespués de que se llamara amarginal_counts()fuera llamado. Si se desea el comportamiento anterior, puede restaurarse estableciendomarginalize_memory=Nonecomo argumento demarginal_counts()que no marginará el campomemory. -
El pase del transpilador
StochasticSwaptranspiler pass puede devolver resultados diferentes con el mismo valor de semilla establecido. Esto se debe a la reescritura interna del pase del transpilador para mejorar el rendimiento en tiempo de ejecución. Sin embargo, esto significa que si ejecutótranspile()conoptimization_level0, 1 (el valor por defecto), o 2 con un valor establecido paraseed_transpilerusted puede obtener una salida con diferentes mapeos de swap presentes después de actualizar a Qiskit Terra 0.20.0. -
Para compilar Qiskit Terra desde el código fuente se necesita ahora un compilador de Rust. Esto se debe a la reescritura interna del
StochasticSwapque mejora considerablemente el rendimiento del transpilador en tiempo de ejecución. El compilador rust puede instalarse fácilmente usando rustup, que puede encontrarse aquí: https://rustup.rs/ -
El atributo
namede la clasePauliEvolutionGatese ha cambiado para que sea siempre"PauliEvolution". Este cambio se hizo para ser coherente con otras puertas en Qiskit y permite a otras partes de Qiskit para identificar rápidamente cuando una operación particular en un circuito es unPauliEvolutionGate. Por ejemplo, permite el desenrollado a puertas de evolución Pauli.Anteriormente, el nombre contenía los operadores que se evolucionan, que ahora está disponible a través de la
PauliEvolutionGate.labelatributo. Si se dibuja un circuito con unaPauliEvolutionGatela puerta seguirá mostrando la misma información, qué puertas se están evolucionando. -
Los métodos anteriormente obsoletos:
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
que originalmente estaban obsoletos en la versión de Qiskit Terra 0.18.0 han sido eliminados y ya no funcionarán.
-
La clase
qiskit.algorithms.VariationalAlgorithmse define ahora como una clase base abstracta (ABC) que requerirá que las clases que hereden de ella definan un método getter y setterVariationalAlgorithm.initial_point. -
El kwarg
pass_managerpara la funcióntranspile()se ha eliminado. Originalmente fue obsoleto en la versión 0.13.0. La forma preferida de transpilar un circuito con un objeto personalizadoPassManagerpersonalizado es utilizar el métodorun()del objetoPassManagerobjeto. -
La clase
ParametrizedSchedule, anteriormente obsoleta, ha sido eliminada y ya no existe. Esta clase quedó obsoleta en la versión 0.17.0. En lugar de utilizar esta clase puede parametrizar directamenteScheduleoScheduleBlockespecificando un objetoParameterobjeto al argumento parametrizar. -
El módulo
qiskit.circuit.library.probability_distributionsha sido eliminado y ya no existe según el aviso de desaprobación de qiskit-terra 0.17.0 (publicado el 1 de abril de 2021). Las clases afectadas sonUniformDistribution,NormalDistribution, yLogNormalDistribution. Todos ellos se trasladan a la biblioteca qiskit-finance, en su módulo de biblioteca de circuitos:qiskit_finance.circuit.library.probability_distributions. -
La clase anterior
qiskit.test.mock.fake_mumbai_v2.FakeMumbaiV2ha sido renombrada aFakeMumbaiFractionalCXpara diferenciarla delBackendV2para el dispositivo IBM de Bombay,qiskit.test.mock.backends.FakeMumbaiV2. Si anteriormente confiaba en la claseFakeMumbaiV2para obtener un backend falso que tuviera aplicaciones fraccionarias deCXGatedefinidas en su objetivo, deberá utilizar la claseFakeMumbaiFractionalCX, ya queFakeMumbaiV2ya no tendrá esas definiciones de puerta adicionales en su claseTarget. -
El resolver utilizado por
QuantumCircuit.append()(y, en consecuencia, todos los métodos que añaden una instrucción a un métodoQuantumCircuit) para convertir los especificadores de bits ha cambiado para hacerlo más rápido y fiable. Ciertas construcciones como:import numpy as np from qiskit import QuantumCircuit qc = QuantumCircuit(1, 1) qc.measure(np.array([0]), np.array([0]))funcionarán ahora donde antes daban error incorrectamente, pero ciertas entradas patológicas como:
from sympy import E, I, pi qc.x(E ** (I * pi))ahora generarán errores donde antes podían haber tenido éxito (erróneamente). Para casi todos los usos correctos, no debería haber ningún cambio perceptible, salvo una aceleración general.
-
El método interno semipúblico
QuantumCircuit._append()ya no comprueba los tipos de sus entradas, y asume que no hay duplicados inválidos en sus listas de argumentos. Esta función es utilizada por ciertas partes internas de Qiskit y otras bibliotecas para construirQuantumCircuitinstancias lo más rápidamente posible saltándose la comprobación de errores cuando ya se sabe que los datos son correctos. En general, los usuarios o funciones que toman datos de usuario deben utilizar el método publicQuantumCircuit.append()que resuelve los especificadores de bits enteros, emite sus argumentos y comprueba que las entradas sean correctas. -
Cython ya no es una dependencia de construcción de Qiskit Terra y ya no es necesario instalarlo cuando se construye Qiskit Terra desde el código fuente.
-
Los gestores de paso preestablecidos en
qiskit.transpiler.preset_passmanagerspara todos los niveles de optimización 2 y 3 generados porlevel_2_pass_manager()ylevel_3_pass_manager()se han modificado para que ejecuten elVF2Layoutpor defecto antes del pase de diseño. El paseVF2Layoutcomprobará rápidamente si se puede encontrar un trazado perfecto y sustituye a lo que se hacía anteriormente para los niveles de optimización 2 y 3, que utilizaban una combinación deTrivialLayoutyCSPLayoutpara intentar encontrar una disposición perfecta. Esto resultará en un comportamiento potencialmente diferente cuandotranspile()es llamado por defecto ya que elimina una ruta por defecto para todos los niveles de optimización >=2 de usar una disposición trivial (dondecircuit.qubits[0]es mapeado al qubit físico 0,circuit.qubits[1]es mapeado al qubit físico 1, etc) asumiendo que la disposición trivial es perfecta. Si su caso de uso dependía del diseño trivial, puede solicitarlo explícitamente al transpilar especificandolayout_method="trivial"al llamar atranspile(). -
El gestor de pases preestablecido para el nivel de optimización 1 (cuando se llama a
transpile()conoptimization_level=1o cuando no se establece ningún argumentooptimization_level) generado porlevel_1_pass_manager()para queVF2Layoutpara comprobar rápidamente si se puede encontrar un diseño perfecto antes de ejecutar el comandoDenseLayout. Sin embargo, a diferencia de lo que ocurre con los niveles de optimización 2 y 3, se sigue intentando realizar un trazado trivial antes de ejecutarVF2Layouty si es un mapeo perfecto se utilizará la salida deVF2Layoutse utilizará.
Notas sobre características en desuso
-
El argumento
max_creditsdeexecute()y todas las configuraciones deQobj(p. ej.QasmQobjConfigyPulseQobjConfig), está obsoleto y se eliminará en una futura versión. El sistema de créditos no se utiliza en los backends de IBM Quantum desde hace dos años, y la opción no tiene ningún efecto. No es necesaria ninguna alternativa. Por ejemplo, si llamara aexecute()comojob = execute(qc, backend, shots=4321, max_credits=10)puede omitir el argumento
max_credits:job = execute(qc, backend, shots=4321) -
El uso de un número entero impar para el argumento
orderen el constructor de la claseSuzukiTrotterestá obsoleto y dejará de funcionar en futuras versiones. Las fórmulas del productoSuzukiTrottersólo se definen cuando el orden es par, ya que las fórmulas del producto Suzuki son simétricas. -
Los kwargs
qregs,cregs,layout, yglobal_phasepara las clasesMatplotlibDrawer,TextDrawing, yQCircuitImage, y el kwargcalibrationspara la claseMatplotlibDrawer, están ahora obsoletos y serán eliminados en una versión posterior.
Corrección de errores
-
Corregido un error en las funciones de conversión de circuitos
circuit_to_gate()ycircuit_to_instruction()(y sus métodos de circuito asociadosQuantumCircuit.to_gate()yQuantumCircuit.to_instruction()) al actuar sobre un circuito con bits sin registro, o bits en más de un registro. -
Se ha corregido un problema por el que llamar a
QuantumCircuit.copy()en los circuitos "body" de una operación de flujo de control creada con la interfaz del constructor provocaba un error. Por ejemplo, esto antes era un error, pero ahora volverá con éxito: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() -
Se ha añadido una entrada que faltaba de la biblioteca de equivalencia de sesiones estándar entre
CXGateyCPhaseGateasí como entreCXGateyCRZGate. -
Se ha corregido un problema por el que la ejecución del operador
==entre dosSparsePauliOpprovocaba un error cuando los dos operadores tenían diferentes números de coeficientes. Por ejemplo:op = SparsePauliOp.from_list([("X", 1), ("Y", 1)]) op2 = SparsePauliOp.from_list([("X", 1), ("Y", 1), ("Z", 0)]) print(op == op2)Anteriormente, en lugar de devolver
False, se generaba un mensajeValueError. -
Corregido el soporte en
transpile()para pasar un objetoInstructionScheduleMapal objeto subyacentePassManagerbasado en el métodoTargetparaBackendV2based backends. Anteriormente, la funcióntranspile()no realizaba este procesamiento y los pases del transpilador que aún no admiten el trabajo con un objetoTargettodavía no tendrían acceso a las calibraciones de pulso predeterminadas para las instrucciones de unBackendV2backend. -
La dirección
AmplitudeAmplifierestá ahora correctamente disponible desde la raízqiskit.algorithmsdirectamente. Antes no se incluía en las clases reexportadas del módulo raíz y sólo era accesible desdeqiskit.algorithms.amplitude_amplifiers. Corregido #7751. -
Se ha solucionado un problema con el backend
mplpara la función de cajón de circuitoscircuit_drawer()y el métodoQuantumCircuit.draw()por el que las compuertas con condiciones no se mostraban correctamente cuando un número suficiente de compuertas hacía que el cajón se plegara a una segunda fila. Corregido: #7752. -
Se ha corregido un problema por el que el método
HHL.construct_circuit()en determinadas condiciones no devolvía un valor correctoQuantumCircuit. Anteriormente, la función tenía un error de redondeo al calcular cuántos qubits eran necesarios para representar los valores propios, lo que provocaba una salida incorrecta del circuito. -
Se ha corregido un error de ancho de banda en
BaseReadoutMitigator.expectation_value()cuando se pasaba una cadenadiagonal. Ahora se interpretará correctamente como little endian del mismo modo que el resto de Qiskit Terra, en lugar de big endian. -
Se ha solucionado un problema con la función
quantum_info.partial_trace()cuando se pedía a la función que no trazara ningún subsistema, ahora devolverá correctamente elDensityMatrixdel estado de entrada con todas las dimensiones restantes en lugar de lanzar un error. Corregido #7613 -
Se ha solucionado un problema con el backend
textpara la función de cajón de circuitoscircuit_drawer()y el métodoQuantumCircuit.draw()cuando las compuertas que utilizan texto lateral, como las compuertasCPhaseGateyRZZGatecon condiciones clásicas establecidas no se mostraban correctamente. Corregido #7532. -
Se ha solucionado un problema con la función
circuit_drawer()y el métododraw()deQuantumCircuit. Al utilizar la opciónreverse_bitscon las opcionesmpl,latexotext, los bits sin registros no se mostraban en el orden correcto. Corregido #7303. -
Se ha corregido un problema en el método
LocalReadoutMitigator.assignment_matrix()que anteriormente rechazaba un valor de entrada para el argumentoqubitsque no fuera una secuencia trivial de qubits de la forma:[0, 1, 2, ..., n-1]. Esto se ha corregido para que ahora cualquier lista de índices de qubits a medir sean aceptados por el método. -
Se ha corregido un problema en el cálculo del valor de expectativa del método
StabilizerState.expectation_value()donde el valor de la expectativa de salida era incorrecto si el operador de entrada para el argumento dePaulipara el argumentoopertenía una fase no trivial. Corregido #7441. -
Una expresión opflow que contenga la identidad de Pauli
opflow.Iya no produce unIGatecuando se convierte en un circuito. Este cambio soluciona una diferencia de expectativas; la puerta de identidad del circuito indica un retardo, mientras que en opflow esperamos una identidad matemática, es decir, ninguna operación. -
La página
PauliGateya no inserta unIGatepara Paulis con la etiqueta"I". -
PauliSumOplas pruebas de igualdad ahora tratan el caso en que uno de los elementos comparados es un únicoPauliOp. Por ejemplo,0 * X + I == Iahora se evalúa como True, mientras que antes de esta versión era False. -
Se ha solucionado un problema con los botones
ALAPScheduleyASAPSchedulecuando se trabajaba con instrucciones que tenían calibraciones de pulso personalizadas (es decir, puertas de pulso). Anteriormente, los pases de programación no utilizaban la duración de la calibración de pulsos personalizada para estas instrucciones, lo que provocaba que se generara una programación incorrecta para el circuito. Esto se ha corregido para que ahora los pases de programación utilicen la duración de la calibración de pulsos personalizada para cualquier instrucción del circuito que tenga una calibración personalizada. -
Se ha corregido la compatibilidad con el uso de
ParameterExpressionparámetros de instrucción en elRZXCalibrationBuildertranspilador. Anteriormente, si un parámetro de instrucción incluía un límiteParameterExpressionel pase no podía manejarlo correctamente. -
Detenido el analizador sintáctico en
QuantumCircuit.from_qasm_str()yfrom_qasm_file()de aceptar programas OpenQASM que se identificaban como de una versión del lenguaje distinta de 2.0. Este analizador sintáctico es sólo para OpenQASM 2.0; el soporte para circuitos importados de OpenQASM 3.0 se añadirá en una próxima versión. -
El exportador OpenQASM 3,
qasm3.Exporterahora escapará a los nombres de registro y parámetro que choquen con palabras clave reservadas de OpenQASM 3 generando un nuevo nombre único. Los registros y parámetros con el mismo nombre ya no tendrán conflictos de nombres en la salida de código del exportador OpenQASM 3. Corregido #7742.
Aer 0.10.3
No cambia
Ignis 0.7.0
No cambia
IBM Proveedor Q 0.18.3
No cambia