Skip to main content
IBM Quantum Platform

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 Target en el transpilador. Varios pases permiten ahora trabajar directamente con un objeto Target lo 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.primitives módulo. Estas API ofrecen distintos niveles de abstracción para calcular resultados de interés a partir de QuantumCircuit y utilizar backends. Por ejemplo, el BaseEstimator define 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, el BaseSampler calcula 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 Operator clase Operator.from_circuit() para crear un nuevo Operator a partir de un objeto QuantumCircuit. Aunque esto era posible normalmente utilizando el constructor por defecto, el método Operator.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 conjunto Layout. 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 operator tendrá los qubits permutados en función de la disposición de modo que sea idéntica a la devuelta por Operator(circuit) antes de la transpilación.

  • Se ha añadido un nuevo método DAGCircuit.copy_empty_like() a la clase DAGCircuit clase. Este método se utiliza para crear una nueva copia de un objeto DAGCircuit existente 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.mock ahora también están accesibles en un nuevo módulo: qiskit.providers.fake_provider. Este nuevo módulo sustituye al anterior qiskit.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 de CXGate y SwapGate ).

  • Añadido un nuevo pase de transpilador CollectLinearFunctions que recoge bloques de CXGate y SwapGate consecutivos en un circuito y sustituye cada bloque por una puerta LinearFunction puerta.

  • Añadido un nuevo pase de transpilador LinearFunctionsSynthesis que sintetiza cualquier LinearFunction puertas utilizando el algoritmo Patel-Markov-Hayes. Si se combina con el CollectLinearFunctions transpiler pass esto permite recoger bloques de CXGate y SwapGate de un circuito y resintetizarlos mediante el algoritmo Patel-Markov-Hayes.

  • Añadido un nuevo pase de transpilador LinearFunctionsToPermutations que sustituye una LinearFunction por un circuito Permutation siempre que sea posible.

  • FlowController (como ConditionalController) pueden anidarse dentro de una instancia PassManager cuando se utiliza el método PassManager.append() método Esto permite el uso de lógica anidada para controlar la ejecución de pases en el PassManager. 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 pm PassManager sólo ejecutará el BasisTranslator pass (en el paso unroll ) en cada iteración del bucle si se cumple el unroll_condition .

  • Los constructores de los módulos ZFeatureMap y ZZFeatureMap tienen un nuevo argumento de palabra clave parameter_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 ZFeatureMap ha prefijado todos sus parámetros internos con el prefijo "my_prefix".

  • El TemplateOptimization transpiler pass ahora puede trabajar con Gate que tienen ParameterExpression parámetros. Un ejemplo ilustrativo del uso de Parameters con TemplateOptimization es 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, DAGInNode y DAGOutNode definen 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 de numpy.unique para 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 clase SparsePauliOp para comprobar la equivalencia de un SparsePauliOp con otro SparsePauliOp objeto. 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 BackendV2 y proporcionó un Target para cada backend. BackendV2 de todos los backends existentes, excepto los tres backends antiguos FakeRueschlikon, FakeTenerife y FakeTokyo , ya que no disponen de los archivos de instantáneas necesarios para crear una nueva clase de backend falsa basada en BackendV2.

    Estos nuevos backends falsos de V2 permitirán probar y desarrollar las nuevas funciones introducidas por BackendV2 y Target como la mejora del transpilador.

  • Añadida una nueva clase de compuerta XXMinusYYGate a 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, y FakeSantiago que se pueden encontrar en el módulo qiskit.providers.fake_provider se pueden utilizar ahora como backends en los experimentos Pulse, ya que ahora incluyen un backend PulseDefaults creado a partir de una instantánea de las propiedades de la máquina equivalente IBM Quantum.

  • El pase ConsolidateBlocks pass tiene un nuevo argumento de palabra clave en su constructor, target. Este argumento se utiliza para especificar un Target que representa el objetivo de compilación de la pasada. Si se especifica, sustituye al kwarg de basis_gates . Si se especifica un objetivo, el pase respetará las puertas y qubits de las instrucciones definidas en el Target a la hora de decidir qué puertas consolidar en un unitario.

  • La clase Target tiene 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 clase Target.

  • Se ha añadido un nuevo kwarg, metadata_serializer, a la función qpy.dump() para especificar una subclase personalizada de JSONEncoder que se utilizará al serializar el atributo QuantumCircuit.metadata y un kwarg doble metadata_deserializer a la función qpy.load() para especificar una subclase de JSONDecoder . Por defecto, los valores dump() y load() intentarán serializar y deserializar JSON con el codificador y decodificador json por defecto de stdlib. Dado que QuantumCircuit.metadata puede 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 argumento metadata_serializer para dump() permite a los usuarios especificar un JSONEncoder personalizado que se utilizará con la llamada interna json.dump() para serializar el QuantumCircuit.metadata diccionario. Esto puede emparejarse con el nuevo argumento metadata_deserializer de la función qpy.load() para descodificar esas codificaciones JSON personalizadas. Si se especifica metadata_serializer en dump() pero no se especifica metadata_deserializer en load() 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 DenseLayout pass tiene un nuevo argumento de palabra clave en su constructor, target. Este argumento se utiliza para especificar un Target que representa el objetivo de compilación de la pasada. Si se especifica, sustituye a los demás argumentos del constructor, coupling_map y backend_prop.

  • La clase Target clase 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 tupla qargs dada.

  • Se ha añadido un nuevo pase DynamicalDecouplingPadding al módulo qiskit.transpiler.passes módulo. Este nuevo pase sustituye al DynamicalDecoupling existente para trabajar con el nuevo flujo de trabajo de programación en el transpilador. Es una subclase del pase BasePadding y depende de que los pases de análisis de programación y alineación se hayan ejecutado antes en un archivo PassManager. Este nuevo paso puede tomar un argumento pulse_alignment que 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 en BackendConfiguration.timing_constraints. Además, el pase también tiene una opción extra_slack_distribution ha 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, middle es idéntico al comportamiento convencional. La nueva estrategia split_edges divide 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 cuando pulse_alignment > 1.

  • La clase Z2Symmetries expone 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 clase SparsePauliOp que trunca las partes real e imaginaria de los coeficientes individualmente. Esto difiere del método SparsePauliOp.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 el GatesInBasis transpiler pass. Este nuevo argumento puede utilizarse para especificar opcionalmente un objeto Target que representa el backend. Cuando se establece este Target se utilizará para determinar si un DAGCircuit contiene puertas fuera del conjunto de bases y no se utilizará el argumento basis_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-terra con 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 Gradient y QFI pueden calcular ahora la parte imaginaria de los gradientes del valor de expectativa. Cuando se utiliza una base de medición diferente, es decir -Y en lugar de Z, podemos medir la parte imaginaria de los gradientes La base de medición puede establecerse con el argumento aux_meas_op .

    Para los gradientes, aux_meas_op = Z calcula 0.5Re[(⟨ψ(ω)|)O(θ)|dωψ(ω)〉] y aux_meas_op = -Y calcula 0.5Im[(⟨ψ(ω)|)O(θ)|dωψ(ω)〉]. Para los QFI, aux_meas_op = Z calcula 4Re[(dω⟨<ψ(ω)|)(dω|ψ(ω)〉)] y aux_meas_op = -Y calcula 4Im[(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 InstructionDurations tiene ahora soporte para trabajar con parámetros de una instrucción. Cada entrada de un objeto InstructionDurations consiste ahora en una tupla de (inst_name, qubits, duration, parameters, unit). Esto permite InstructionDurations definir 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 style en la función de cajón de circuitos circuit_drawer() y el método QuantumCircuit.draw() método, iqx_dark. Cuando style se establece en iqx_dark con el backend de cajón mpl , 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 de matplotlib preguntando a if 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 qiskit se 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 campo memory de un objeto de entrada Result de entrada. Por ejemplo, si el argumento de entrada result es un objeto qiskit Result obtenido 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 StochasticSwap han 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ón transpile() cuando se ejecuta con optimization_level 0, 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 entorno RAYON_NUM_THREADS con un valor entero. Por ejemplo, configurando RAYON_NUM_THREADS=4 se ejecutará el StochasticSwap con 4 hilos.

  • Una nueva variable de entorno QISKIT_FORCE_THREADS está 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 el StochasticSwap pero es probable que se utilice en otras partes de Qiskit en el futuro. Cuando esta variable env se establece en TRUE cualquier 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, en StochasticSwap si el pase se está ejecutando como parte de una transpile() llamada con > 1 circuito que se está ejecutando en paralelo con multiprocessing a través de parallel_map() el StochasticSwap no 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 configurar QISKIT_FORCE_THREADS=TRUE.

  • Las nuevas clases de backend falso están disponibles en qiskit.providers.fake_provider. Se trata de versiones simuladas de ibm_cairo, ibm_hanoi, ibmq_kolkata, ibm_nairobi y ibm_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 que Initialize sin que el restablecimiento se aplique automáticamente.

    Por ejemplo, para preparar un qubit en el estado (01)/2(|0\rangle - |1\rangle) / \sqrt{2} :

    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 Optimize1qGates transpiler pass ahora tiene soporte para optimizar U1Gate, U2Gatey PhaseGate con 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() y PauliList.evolve() tienen ahora un nuevo argumento de palabra clave, frame, que se utiliza para realizar una evolución de un Pauli por un Clifford. Si frame='h' (por defecto) entonces hace la evolución de la imagen de Heisenberg de un Pauli por un Clifford ( P=CPCP' = C^\dagger P C ), y si frame='s' entonces hace la evolución de la imagen de Schrödinger de un Pauli por un Clifford ( P=CPCP' = C P C^\dagger ). 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 en decompose_clifford sea 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 de QuantumCircuit que abstrae los detalles de la ejecución subyacente en un Backend. 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 clase BaseEstimator y 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éase BaseSampler para la definición de la clase abstracta) y Estimator (véase BaseEstimator para la definición de la clase abstracta). Las implementaciones de referencia se incluyen en el módulo qiskit.primitives y se construyen utilizando el módulo qiskit.quantum_info que 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 archivo Backend.

  • Se ha añadido un nuevo módulo qiskit.qpyque contiene la funcionalidad anteriormente expuesta en qiskit.circuit.qpy_serialization. Las funciones públicas expuestas anteriormente en qiskit.circuit.qpy_serialization, dump() y load() están ahora disponibles desde este nuevo módulo (aunque siguen siendo accesibles desde qiskit.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 de pulse Schedule y ScheduleBlock además de los objetos QuantumCircuit objetos que soporta actualmente.

  • Se ha añadido un nuevo atributo qubit_properties a la clase Target clase. Este atributo contiene una lista de QubitProperties objetos para cada qubit del objetivo. Por ejemplo:

    target.qubit_properties[2]

    contendrá el QubitProperties para el qubit número 2 en el objetivo.

    Para los autores de BackendV2 autores, si antes definían QubitProperties directamente en su implementación BackendV2 anulando BackendV2.qubit_properties() esto seguirá funcionando correctamente. Sin embargo, si traslada la definición al objeto subyacente Target y elimina la implementación especializada BackendV2.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ímite QuantumCircuit. Se origina en un método privado, _eval_aux_ops(), de la clase qiskit.algorithms.VQE pero la nueva función eval_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 BasisTranslator transpiler 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 DenseLayout transpilador 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 entorno RAYON_NUM_THREADS en un valor entero. Por ejemplo, configurando RAYON_NUM_THREADS=4 se ejecutará el DenseLayout con 4 hilos.

  • Los cálculos internos de Statevector.expectation_value() y DensityMatrix.expectation_value() se han reimplementado en el lenguaje de programación Rust. Esta nueva implementación es multihilo y, por defecto, para un archivo Statevector o DensityMatrix >= 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 entorno RAYON_NUM_THREADS con un valor entero. Por ejemplo, configurando RAYON_NUM_THREADS=4 só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

H=X0Z3+2Y1Y4H = X_0 Z_3 + 2 Y_1 Y_4

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 UnitarySynthesis transpiler pass tiene un nuevo argumento de palabra clave en su constructor, target. Puede utilizarse para especificar opcionalmente un objeto Target que representa el objetivo de compilación de la pasada. Cuando se especifique, sustituirá a los valores establecidos para basis_gates, coupling_map, y backend_props.

  • La clase plugin abstracta UnitarySynthesisPlugin tiene un nuevo atributo opcional que las implementaciones pueden añadir, supports_target. Si un complemento tiene este atributo establecido en True , se pasará un objeto Target en la carga útil de options en el campo target . Se espera que este objeto Target se utilice en lugar de coupling_map, gate_lengths, basis_gates y gate_errors.

  • Se ha introducido un nuevo flujo de trabajo de paso de transpilador para construir PassManager objetos para programar QuantumCircuit objetos en el transpilador. En el nuevo flujo de trabajo los pases de programación y alineación son todos AnalysisPass que sólo actualizan el conjunto de propiedades del gestor de pases, concretamente el nuevo elemento del conjunto de propiedades node_start_time, que contiene la hora de inicio absoluta de cada opnode. Una TransformationPass como PadDelay se 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 -> alignment que eran ambos pases de transformación por lo que había múltiples DAGCircuit instancias 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 en scheduling -> alignment -> padding donde la DAGCircuit actualización sólo se produce al final con el pase padding .

    Si crea objetos personalizados PassManager que impliquen la programación de circuitos tendrán que ajustar su PassManager para insertar uno de los pases de BasePadding (actualmente PadDelay o PadDynamicalDecoupling ) 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 del run() de su método personalizado PassManager.

    Por ejemplo, si antes construía su PassManager con algo como

    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)

    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 ConstrainedReschedule pass. El paso ConstrainedReschedule pass considera tanto las restricciones de alineación del hardware que se pueden definir en un BackendConfigurationpulse_alignment y acquire_alignment. Esta nueva clase sustituye a la anteriormente existente AlignMeasures ya 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ón acquire_alignment para el pase ConstrainedReschedule se puede sustituir directamente por AlignMeasures cuando se combina con un nuevo pase BasePadding .

  • Añadidos dos nuevos pases de transpilador ALAPScheduleAnalysis y ASAPScheduleAnalysis que sustituyen a los pases ALAPSchedule y ASAPSchedule como 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 de BasePadding para 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_latency de 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 └─────────┘ 0
    from 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_2 comienza antes de la puerta X condicional en el q_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 AcquireChannel y MemorySlot que 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 PadDynamicalDecoupling que sustituye al DynamicalDecoupling como 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() y plot_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() y plot_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 retworkx spring_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ón qubit_coordinates para 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() y plot_circuit_layout()son ahora capaces de funcionar con un BackendV2 . Anteriormente, estas funciones sólo funcionaban con BaseBackend o con backends basados en BackendV1 .

  • Añadido un nuevo pase de transpilador, SetIOLatency. Esta pasada toma dos argumentos clbit_write_latency y conditional_latency para 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 PadDelay se ha añadido. Este paso llena el tiempo ocioso en los cables del qubit con Delay instrucciones. 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 (como ALAPScheduleAnalysis o ASAPScheduleAnalysis) y de cualquier pase de alineación (como ConstrainedReschedule) que se ejecuten antes de PadDelay.

  • El pase de transpilador VF2Layout pass del transpilador tiene un nuevo argumento de palabra clave, target que se utiliza para proporcionar un Target objeto para el pase. Cuando se especifica, el Target será utilizado por el pase para toda la información sobre el dispositivo de destino. Si se especifica, la opción target tendrá prioridad sobre los argumentos coupling_map y properties .

  • Permitir callables como optimizadores en VQE y QAOA. Ahora, el optimizador puede ser uno de los optimizadores de Qiskit, como por ejemplo SPSA o 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 result

    La 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 como transpile() y assemble()) en un subproceso lanzado fuera de parallel_map()es posible que el despacho paralelo realizado dentro de parallel_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 a parallel_map() desde un proceso principal debería funcionar bien; o puedes llamar manualmente al módulo multiprocessing de 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, Clbit y AncillaQubit tienen 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 retworkx ha pasado de 0.10.1 a 0.11.0. Esto mejora el rendimiento del pase de transpilación ConsolidateBlocks.

  • La versión mínima compatible de symengine es ahora 0.9.0. Esto era necesario para mejorar la compatibilidad con el módulo pickle de Python que se utiliza internamente como parte del envío paralelo con parallel_map().

  • El valor por defecto de QISKIT_PARALLEL cuando se ejecuta con Python 3.9 en Linux se establece ahora en TRUE. Esto significa que al ejecutar parallel_map() o funciones que lo llamen internamente, como transpile() y assemble()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 entorno QISKIT_PARALLEL en FALSE, o estableciendo la opción parallel en False en 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 MSGate anteriormente obsoleta que se encontraba en qiskit.circuit.library ha sido eliminada. Originalmente fue obsoleto en la versión 0.16.0. En su lugar debe utilizarse la clase GMS ya que permite crear una puerta MS equivalente de 2 qubits además de MSGate para cualquier número de qubits.

  • El método mirror() de la clase Instruction ha sido eliminado. Originalmente fue obsoleto en la versión 0.15.0. En su lugar debe utilizar Instruction.reverse_ops().

  • El método num_ancilla_qubits() de la directiva qiskit.circuit.library.PiecewiseLinearPauliRotations y qiskit.circuit.library.WeightedAdder ha sido eliminado. Originalmente fue obsoleto en la versión 0.16.0. En su lugar, deben utilizarse los métodos PiecewiseLinearPauliRotations.num_ancillas() y WeightedAdder.num_ancillas() .

  • El argumento reverse del constructor de la clase PolynomialPauliRotations ha sido eliminado. Originalmente fue obsoleto en la versión 0.15.0. En su lugar, debe utilizar el método QuantumCircuit.reverse_bits() para invertir el circuito PolynomialPauliRotations circuito si es necesario.

  • El argumento angle , anteriormente obsoleto, en los constructores de los módulos C3SXGate y C3XGate ha 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étodo C3XGate.power() .

  • Compatibilidad con el uso de objetos np.ndarray como parte del atributo params de un objeto Gate se 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 de Gate y permitir explícitamente una entrada np.ndarray sobrecargando el método validate_parameter() método

  • Se ha añadido un nuevo extra csp-layout-pass al objetivo de instalación de pip install qiskit-terra, y también se incluye en el extra all . 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 la CSPLayout transpiler 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 comando pip install ) en el objetivo qiskit-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 AmplitudeEstimator hereda ahora de la clase ABC de la biblioteca estándar Python. Esto requiere que cualquier subclase implemente el método estimate() cuando antes no era necesario. Esto se hizo porque la intención original de la clase era ser siempre una clase hija de ABC, ya que la clase estimate() es necesario para el funcionamiento de un objeto AmplitudeEstimator objeto. Sin embargo, si antes definía una subclase AmplitudeEstimator que no implementaba estimate() se producirá un error.

  • El error generado por HoareOptimizer si la dependencia opcional z3 no está disponible ha cambiado de TranspilerError a MissingOptionalLibraryError (que es a la vez un QiskitError y ImportError). 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 objeto Result objeto de entrada, ahora marginará el campo memory de los datos del experimento si se establece en la entrada Result. Anteriormente, el campo memory de la entrada no estaba marginado. Este cambio se ha realizado porque el comportamiento anterior provocaba que el campo counts no coincidiera con el campo memory después de que se llamara a marginal_counts() fuera llamado. Si se desea el comportamiento anterior, puede restaurarse estableciendo marginalize_memory=None como argumento de marginal_counts() que no marginará el campo memory .

  • El pase del transpilador StochasticSwap transpiler 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() con optimization_level 0, 1 (el valor por defecto), o 2 con un valor establecido para seed_transpiler usted 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 StochasticSwap que 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 name de la clase PauliEvolutionGate se 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 un PauliEvolutionGate. 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.label atributo. Si se dibuja un circuito con una PauliEvolutionGate la puerta seguirá mostrando la misma información, qué puertas se están evolucionando.

  • Los métodos anteriormente obsoletos:

    • qiskit.algorithms.VQE.get_optimal_cost
    • qiskit.algorithms.VQE.get_optimal_circuit
    • qiskit.algorithms.VQE.get_optimal_vector
    • qiskit.algorithms.VQE.optimal_params
    • qiskit.algorithms.HamiltonianPhaseEstimationResult.most_likely_phase
    • qiskit.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.VariationalAlgorithm se define ahora como una clase base abstracta (ABC) que requerirá que las clases que hereden de ella definan un método getter y setter VariationalAlgorithm.initial_point .

  • El kwarg pass_manager para la función transpile() se ha eliminado. Originalmente fue obsoleto en la versión 0.13.0. La forma preferida de transpilar un circuito con un objeto personalizado PassManager personalizado es utilizar el método run() del objeto PassManager objeto.

  • 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 directamente Schedule o ScheduleBlock especificando un objeto Parameter objeto al argumento parametrizar.

  • El módulo qiskit.circuit.library.probability_distributions ha 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 son UniformDistribution, NormalDistribution, y LogNormalDistribution. 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.FakeMumbaiV2 ha sido renombrada a FakeMumbaiFractionalCX para diferenciarla del BackendV2 para el dispositivo IBM de Bombay, qiskit.test.mock.backends.FakeMumbaiV2. Si anteriormente confiaba en la clase FakeMumbaiV2 para obtener un backend falso que tuviera aplicaciones fraccionarias de CXGate definidas en su objetivo, deberá utilizar la clase FakeMumbaiFractionalCX , ya que FakeMumbaiV2 ya no tendrá esas definiciones de puerta adicionales en su clase Target.

  • El resolver utilizado por QuantumCircuit.append() (y, en consecuencia, todos los métodos que añaden una instrucción a un método QuantumCircuit) 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 construir QuantumCircuit instancias 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 public QuantumCircuit.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_passmanagers para todos los niveles de optimización 2 y 3 generados por level_2_pass_manager() y level_3_pass_manager() se han modificado para que ejecuten el VF2Layout por defecto antes del pase de diseño. El pase VF2Layout comprobará 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 de TrivialLayout y CSPLayout para intentar encontrar una disposición perfecta. Esto resultará en un comportamiento potencialmente diferente cuando transpile() 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 (donde circuit.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 especificando layout_method="trivial" al llamar a transpile().

  • El gestor de pases preestablecido para el nivel de optimización 1 (cuando se llama a transpile() con optimization_level=1 o cuando no se establece ningún argumento optimization_level ) generado por level_1_pass_manager() para que VF2Layout para comprobar rápidamente si se puede encontrar un diseño perfecto antes de ejecutar el comando DenseLayout. 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 ejecutar VF2Layout y si es un mapeo perfecto se utilizará la salida de VF2Layout se utilizará.

Notas sobre características en desuso

  • El argumento max_credits de execute()y todas las configuraciones de Qobj (p. ej. QasmQobjConfig y PulseQobjConfig), 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 a execute() como

    job = 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 order en el constructor de la clase SuzukiTrotter está obsoleto y dejará de funcionar en futuras versiones. Las fórmulas del producto SuzukiTrotter sólo se definen cuando el orden es par, ya que las fórmulas del producto Suzuki son simétricas.

  • Los kwargs qregs, cregs, layout, y global_phase para las clases MatplotlibDrawer, TextDrawing, y QCircuitImage , y el kwarg calibrations para la clase MatplotlibDrawer , 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() y circuit_to_instruction() (y sus métodos de circuito asociados QuantumCircuit.to_gate() y QuantumCircuit.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 CXGate y CPhaseGate así como entre CXGate y CRZGate.

  • Se ha corregido un problema por el que la ejecución del operador == entre dos SparsePauliOp provocaba 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 mensaje ValueError .

  • Corregido el soporte en transpile() para pasar un objeto InstructionScheduleMap al objeto subyacente PassManager basado en el método Target para BackendV2 based backends. Anteriormente, la función transpile() no realizaba este procesamiento y los pases del transpilador que aún no admiten el trabajo con un objeto Target todavía no tendrían acceso a las calibraciones de pulso predeterminadas para las instrucciones de un BackendV2 backend.

  • La dirección AmplitudeAmplifier está ahora correctamente disponible desde la raíz qiskit.algorithms directamente. Antes no se incluía en las clases reexportadas del módulo raíz y sólo era accesible desde qiskit.algorithms.amplitude_amplifiers. Corregido #7751.

  • Se ha solucionado un problema con el backend mpl para la función de cajón de circuitos circuit_drawer() y el método QuantumCircuit.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 correcto QuantumCircuit. 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 cadena diagonal . 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 el DensityMatrix del estado de entrada con todas las dimensiones restantes en lugar de lanzar un error. Corregido #7613

  • Se ha solucionado un problema con el backend text para la función de cajón de circuitos circuit_drawer() y el método QuantumCircuit.draw() cuando las compuertas que utilizan texto lateral, como las compuertas CPhaseGate y RZZGate con condiciones clásicas establecidas no se mostraban correctamente. Corregido #7532.

  • Se ha solucionado un problema con la función circuit_drawer() y el método draw() de QuantumCircuit. Al utilizar la opción reverse_bits con las opciones mpl, latex o text , 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 argumento qubits que 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 de Pauli para el argumento oper tenía una fase no trivial. Corregido #7441.

  • Una expresión opflow que contenga la identidad de Pauli opflow.I ya no produce un IGate cuando 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 PauliGate ya no inserta un IGate para Paulis con la etiqueta "I".

  • PauliSumOp las pruebas de igualdad ahora tratan el caso en que uno de los elementos comparados es un único PauliOp. Por ejemplo, 0 * X + I == I ahora se evalúa como True, mientras que antes de esta versión era False.

  • Se ha solucionado un problema con los botones ALAPSchedule y ASAPSchedule cuando 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 ParameterExpression parámetros de instrucción en el RZXCalibrationBuilder transpilador. Anteriormente, si un parámetro de instrucción incluía un límite ParameterExpression el pase no podía manejarlo correctamente.

  • Detenido el analizador sintáctico en QuantumCircuit.from_qasm_str() y from_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

¿Le ha resultado útil esta página?
Informe de un error, de una errata o solicite contenido en GitHub.