Skip to main content
IBM Quantum Platform

Notas de la versión de Qiskit SDK 1.3


1.3.3

Preludio

Qiskit 1.3.3 es una versión de corrección de errores menores para la serie 1.3.

Corrección de errores

  • Se ha corregido un error por el que las etiquetas de barrera se colocaban incorrectamente al utilizar el parámetro reverse_bits = True en el método QuantumCircuit.draw() método. El error provocaba que las etiquetas de las operaciones de barrera estuvieran desalineadas, lo que podía crear confusión en las visualizaciones de circuitos. Corregido #13609.

  • Aplicación de un pequeño factor de regularización contra matrices hermitianas mal condicionadas en representaciones de superoperadores.

  • Las comparaciones de Delay de instrucciones, incluidas las que se realizan dentro de circuitos, requieren ahora que tanto las unidades como el valor de duración sean iguales. Correcciones #13812.

  • Se ha corregido un error en el CommutationChecker que podía fallar al comprobar la relación de conmutación de una rotación Pauli de dos qubits con una puerta que no está en la caché de conmutación. Por ejemplo:

    import numpy as np
    from qiskit.circuit.library import RXXGate, RGate
    from qiskit.circuit.commutation_library import SessionCommutationChecker as scc
    
    res = scc.commute(RGate(2, 2), [1], [], RXXGate(np.pi / 2), [0, 1], [])

    Este comportamiento ya está resuelto y la relación de conmutación se calcula correctamente. Corregido #13742.

  • Se ha corregido un error por el que QuantumCircuit.qubit_stop_time() y QuantumCircuit.qubit_duration() devolvían un tiempo (duración) incorrecto. El problema se producía cuando algunos qubits tenían instrucciones pero otros estaban inactivos. Corrige #8729.

  • Se ha corregido un error en el RemoveIdentityEquivalent por el que se eliminaban del circuito las puertas cercanas a la identidad hasta una fase global, pero no se actualizaba la fase global del circuito. En particular RemoveIdentityEquivalent ahora elimina las puertas GlobalPhaseGate no parametrizadas. Corrección #13778.

  • Se ha corregido un error en random_clifford() que impedía el muestreo del grupo Clifford completo. Correcciones #13606.

  • Cuando SabreLayout se utiliza para realizar simultáneamente el trazado y el enrutamiento (como es el caso de las opciones por defecto de transpile() y generate_preset_pass_manager()) en un Target o CouplingMap con conectividad disjunta, y el circuito de entrada encaja en un solo componente del mapa de acoplamiento, la permutación de enrutamiento será ahora rastreada correctamente.

    Anteriormente, cualquier qubit del mapa de acoplamiento que no estuviera conectado, ni siquiera indirectamente, a un qubit utilizado por el circuito enrutado no se incluiría en la permutación de enrutamiento final. Esto podría causar un comportamiento sorprendente a gran distancia del punto de fallo, incluso si la compilación pareciera tener éxito, como llamadas a TranspileLayout.final_index_layout() elevando KeyError.

    Este fallo no afectaba a los backends que estaban totalmente conectados, como es el caso de la mayoría. Correcciones #13732.


1.3.2

Preludio

Qiskit 1.3.2 es una versión de corrección de errores menores para la serie 1.3.

Notas sobre la actualización de Synthesis

  • Los plugins de síntesis de alto nivel para LinearFunction ya no producen un error cuando se pasa un objeto distinto de LinearFunction en el método run . En su lugar, ahora devuelven None, lo que es coherente con otros plugins. Si confía en que se produzca este error, puede realizar manualmente una comprobación de instancia.

Corrección de errores

  • Anteriormente, el CommutationChecker almacenaba en caché las relaciones de conmutación de Instructions con float-only params como clave para consultar la relación. Esto podría dar lugar a resultados incorrectos si la definición de la instrucción dependiera de información adicional más allá del atributo params como, por ejemplo, en el caso de la instrucción PauliEvolutionGate. Este comportamiento ya está corregido, y el comprobador de conmutaciones sólo almacena en caché las conmutaciones de las puertas estándar nativas de Qiskit. Para las puertas personalizadas, este cambio puede suponer un coste de rendimiento; sin embargo, garantiza resultados correctos al evitar el almacenamiento en caché inseguro.

  • Se ha corregido un error en CommutationCheckerpor el que se comprobaban las relaciones de conmutación de una instrucción con valores no numéricos en el atributo params (como en el caso de PauliGate) podía dar lugar a un error. Corregido #13570.

  • El sitio CommutationChecker no manejaba correctamente las conmutaciones de CRXGate, CRYGate y CRZGate para ángulos de rotación de la forma (4k+2)π(4k + 2)\pi, con kZk \in \mathbb Z. En estos casos, se asumía incorrectamente que estas puertas conmutaban con cualquier puerta. Este comportamiento ya está corregido, y estas puertas conmutan correctamente con cualquier puerta sólo cuando el ángulo de rotación es múltiplo de 4π4\pi.

  • Se ha corregido un error que provocaba que las siguientes funciones de la biblioteca de circuitos produjeran errores cuando se invocaban con num_qubits=1: efficient_su2(), real_amplitudes(), excitation_preserving() y pauli_two_design() (para un solo qubit, estos circuitos no contienen ninguna puerta de 2 qubits). Corregido #13480.

  • Se ha corregido un error por el que cualquier instrucción denominada "mcmt" se pasaba incorrectamente a la rutina de síntesis de alto nivel para una instrucción de tipo MCMTGatelo que provocaba un fallo o un resultado no válido. Este problema podría ocurrir, por ejemplo, al manipular el MCMT circuito, llamado "mcmt", y convertirlo implícitamente en una instrucción (por ejemplo, al agregarlo a otro circuito). Corregido #13563.

  • Se ha corregido un error por el que la síntesis de fórmulas de producto por defecto para PauliEvolutionGate no trataba correctamente todos los términos de identidad en el operador. El término de identidad total debería introducir una fase global igual a -evolution_time, pero estaba desviado por un factor de 2 y podría romperse para tiempos parametrizados. Corregido #13625. Corregido #13675. Corregido #13644.

  • Corregida una inconsistencia en el circuito generado por la síntesis de evolución de Pauli usando SuzukiTrotter o LieTrotter (el método por defecto). Para los tiempos de evolución parametrizados, los circuitos resultantes contenían parámetros con una parte compleja cero espuria, que afectaba a la salida de ParameterExpression.sympify(). La salida ahora contiene correctamente sólo valores reales. Corregido #13642.

  • Se ha corregido un error que provocaba que PauliList.insert() con qubit=True produjera un atributo de fase con la forma incorrecta cuando el objeto original era de longitud 1. Corregido #13623.

  • Se ha corregido un error en qasm3.Exporter que provocaba el bloqueo del exportador al manipular una puerta unitaria debido a un procesamiento incorrecto de su campo params . Corregido #13362.

  • Se ha corregido un error en el método Target.instruction_supported() por el que los objetivos con self.num_qubits==None siempre devolvían False independientemente del conjunto de bases admitido.

  • Se ha corregido un error en el UnitarySynthesis transpiler pass, por el que los bloques de UnitaryGates en 3 qubits o más no se sintetizaban correctamente. Esto provocaba, por ejemplo, que el circuito se sobrescribiera con el último bloque procesado o que se produjeran pánicos internos al encontrar mediciones después de dicho bloque. Corregido #13586.

  • Se ha corregido un error en el UnitarySynthesis transpiler pass por el que non-2-qubit gates se incluía en la base disponible de 2 qubits, provocando que TwoQubitWeylDecomposition entrara en pánico debido al desajuste de dimensiones.

  • Se ha corregido un error por el que al inicializar SparsePauliOp con un gran número de términos Pauli-Y (típicamente 100\geq 100 ) y sin coeffs explícito daba como resultado un coeficiente cercano a 1 pero con un error en coma flotante. El coeficiente es ahora correctamente 1 por defecto. Corregido #13522.


1.3.1

Preludio

Qiskit 1.3.1 es una versión de corrección de errores menores para la serie 1.3.

Notas sobre la actualización de circuitos

  • El método de control genérico de las puertas evita ahora intentar traducir las puertas a una base compatible cuando la puerta ya es compatible. Esto puede cambiar ligeramente la síntesis de la puerta controlada, pero no debería aumentar el número de puertas de dos qubits.

Corrección de errores


1.3.0

Preludio

La versión 1.3.0 de Qiskit aporta importantes mejoras de rendimiento y calidad al transpilador. Se han introducido muchas novedades, correcciones y mejoras en esta nueva versión de Qiskit, las más destacadas son:

  • Las estructuras de datos centrales para la transpilación en Qiskit se han portado a Rust internamente. Esto incluye componentes como DAGCircuit, Target, EquivalenceLibraryy otros. Las API públicas de todas estas estructuras de datos permanecen inalteradas, pero el rendimiento tras las reescrituras ha mejorado.

  • La mayoría de los pases del transpilador utilizados por el gestor de pases predefinidos se han portado a Rust, lo que se traduce en una mejora media del tiempo de ejecución global de 6x en comparación con Qiskit 1.2.4 al ejecutar las pruebas de benchpress. Algunos de los pases especialmente impactantes que se beneficiaron enormemente de las reescrituras fueron el BasisTranslator, CommutationAnalysis, ConsolidateBlocksy UnitarySynthesis. Puede consultar las notas de la versión de funciones para obtener una lista completa de los pases portados.

  • Mejoras en la biblioteca de circuitos que aumentan la calidad de compilación y la velocidad de construcción de circuitos. Las operaciones se distinguen ahora en:

    • Operaciones estructurales, que tienen una descomposición única, y se representan como funciones que devuelven un QuantumCircuit (por ejemplo: real_amplitudes()). La mayoría de estas funciones se construyen en Rust, lo que resulta en un tiempo de ejecución de construcción de circuitos significativamente más rápido.
    • Las operaciones abstractas, que pueden implementarse utilizando diferentes descomposiciones, se representan como Gate o Instruction (por ejemplo: PauliEvolutionGate). Esto permite construir un circuito cuántico abstracto y dejar que el compilador elija la descomposición óptima.

    El uso de una descripción abstracta del circuito es especialmente potente en combinación con las mejoras del HighLevelSynthesis transpiler pass, que ahora puede tener en cuenta los qubits auxiliares ociosos para encontrar la mejor descomposición disponible para una puerta determinada.

  • La versión mínima soportada de Python es ahora 3.9 ya que Python 3.8 llegó al final de su vida útil en 2024-10. En esta versión también se ha añadido compatibilidad oficial con Python 3.13.

Características de los circuitos

  • Se ha mejorado la funcionalidad de CommutationChecker para incluir soporte para las siguientes puertas parametrizadas con parámetros libres: RXXGate, RYYGate, RZZGate, RZXGate, RXGate, RYGate, RZGate, PhaseGate, U1Gate, CRXGate, CRYGate, CRZGate, CPhaseGate. Antes sólo se admitían con parámetros vinculados.

  • Añadida una nueva función quantum_volume() para generar un volumen cuántico QuantumCircuit como se define en A. Cross et al. Validación de ordenadores cuánticos mediante circuitos modelo aleatorios, Phys. Rev. A 100, 032328 (2019). Esta nueva función difiere de la clase QuantumVolume en que devuelve un objeto QuantumCircuit en lugar de construir un objeto subclase. La segunda es que esta nueva función es multihilo y está implementada en rust por lo que genera el circuito de salida ~10x más rápido que la QuantumVolume clase

  • Se ha mejorado el rendimiento en tiempo de ejecución de la construcción de la clase QuantumVolume con el argumento classical_permutation fijado en True. Internamente ahora llama a la función quantum_volume() que está escrita en Rust y es ~10x más rápida al generar un circuito de volumen cuántico.

  • Añadida una nueva función de manipulación de circuitos pauli_twirl_2q_gates() que puede utilizarse para aplicar el giro de Pauli a un circuito dado. Esto sólo funciona para girar un conjunto fijo de puertas de dos qubits, actualmente CXGate, ECRGate, CZGate, iSwapGate. Por ejemplo:

    from qiskit.circuit import QuantumCircuit, pauli_twirl_2q_gates
    
    qc = QuantumCircuit(2)
    qc.cx(0, 1)
    twirled_circuit = pauli_twirl_2q_gates(qc, seed=123456)
    twirled_circuit.draw("mpl")
    _images/release_notes-1.png
  • Se han añadido puertas aritméticas binarias para la suma in situ de dos registros nn -qubit, es decir abaa+b|a\rangle |b\rangle \mapsto |a\rangle |a+b\rangle. El ModularAdderGate implementa la suma módulo 2n2^n, el HalfAdderGate incluye un qubit de salida, y el FullAdderGate incluye tanto un qubit de entrada como uno de salida. Consulte la documentación correspondiente para más detalles y ejemplos.

    A diferencia de los circuitos de biblioteca existentes, como CDKMRippleCarryAdderel manejo de la puerta abstracta permite al compilador (o al usuario) seleccionar la síntesis de puerta óptima, en función del contexto del circuito.

  • Se ha añadido el MultiplierGate para la multiplicación de dos registros nn -qubit, es decir ab0abab|a\rangle |b\rangle |0\rangle \mapsto |a\rangle |b\rangle |a \cdot b\rangle. Consulte la documentación de la clase para más detalles y ejemplos.

  • Los circuitos cuánticos de lógica booleana en qiskit.circuit.library tienen ahora representaciones equivalentes como objetos Gate objetos que permiten su uso con HighLevelSynthesis transpiler pass y la infraestructura de plugins.

  • Se han añadido implementaciones especializadas de __eq__() para todas las puertas de circuito de la biblioteca estándar. La mayoría de las puertas estándar ya estaban especializadas en este método, pero unas pocas no, y podían provocar ralentizaciones importantes en lugares inesperados.

  • Añadido evolved_operator_ansatz(), hamiltonian_variational_ansatz()y qaoa_ansatz() a la biblioteca de circuitos para implementar circuitos variacionales basados en evoluciones de operadores. evolved_operator_ansatz() y qaoa_ansatz() son funcionalmente equivalentes a EvolvedOperatorAnsatz y QAOAAnsatzpero, por lo general, son más eficaces.

    El sitio hamiltonian_variational_ansatz() está diseñado para tomar un único Hamiltoniano y dividirlo automáticamente en términos conmutativos para implementar un ansatz variacional Hamiltoniano. Esto ya se podía conseguir manualmente utilizando el botón EvolvedOperatorAnsatzpero ahora es más cómodo de usar.

  • Añadido grover_operator() para construir un circuito operador de Grover, utilizado en el algoritmo de Grover y en la estimación/amplificación de amplitud, por ejemplo. Esta función es similar a GroverOperatorpero no requiere que elijas la implementación de la puerta X multicontrolada, sino que deja que el compilador determine la descomposición óptima. Además, no envuelve el circuito en una puerta opaca y es más rápido porque se necesitan menos descomposiciones para la transpilación.

    from qiskit.circuit import QuantumCircuit
    from qiskit.circuit.library import grover_operator
    
    oracle = QuantumCircuit(2)
    oracle.z(0)  # good state = first qubit is |1>
    grover_op = grover_operator(oracle, insert_barriers=True)
    grover_op.draw('mpl')
    _images/release_notes-2.png
  • Un nuevo atributo de datos, qiskit.circuit.CONTROL_FLOW_OP_NAMESpara encontrar y comprobar fácilmente si una operación Instruction es una operación de flujo de control por su nombre.

  • La biblioteca de equivalencias estándar (SessionEquivalenceLibrary) ahora tiene reglas que pueden convertir directamente entre la biblioteca estándar de Qiskit 2q interacciones continuas de tipo Ising (por ejemplo. CPhaseGate, RZZGate, RZXGateetc.) utilizando relaciones de equivalencia locales. Antes, varias de estas conversiones pasaban por una forma 2-CX, lo que daba lugar a una generación de circuitos menos eficiente.

    Nota

    En general, el BasisTranslator no garantiza que encuentre la "mejor" relación de equivalencia para un determinado Targetpero siempre encontrará una equivalencia si existe. Dependemos de pases más caros de resíntesis y optimización de puertas en el transpilador para mejorar el resultado. Actualmente, estos pases no son tan eficaces para los conjuntos de bases con una interacción de dos qubits parametrizada de forma continua como lo son para las interacciones discretas de dos qubits supercontrolados.

  • Se ha añadido un nuevo argumento "apply_synthesis" a Decomposeque permite al pase de transpilador aplicar síntesis de alto nivel para descomponer objetos que sólo están definidos por una rutina de síntesis. Por ejemplo:

    from qiskit import QuantumCircuit
    from qiskit.quantum_info import Clifford
    from qiskit.transpiler.passes import Decompose
    
    cliff = Clifford(HGate())
    circuit = QuantumCircuit(1)
    circuit.append(cliff, [0])
    
    # Clifford has no .definition, it is only defined by synthesis
    nothing_happened = Decompose()(circuit)
    
    # this internally runs the HighLevelSynthesis pass to decompose the Clifford
    decomposed = Decompose(apply_synthesis=True)(circuit)
  • Añadida la función iqp() función para construir circuitos de tiempo polinómico cuántico instantáneo (IQP). Además de la clase IQP la función también permite construir circuitos IQP aleatorios:

    from qiskit.circuit.library import random_iqp
    
    random_iqp = random_iqp(num_qubits=4)
    random_iqp.draw('mpl')
    _images/release_notes-3.png
  • Se ha añadido el MCMTGate para representar una operación multicontrol multiobjetivo como una puerta. Esta representación del circuito MCMT permite al compilador seleccionar la mejor implementación disponible en función del número y el estado de los qubits auxiliares presentes en el circuito.

    La implementación deseada puede elegirse especificando el plugin de síntesis de alto nivel:

    from qiskit import QuantumCircuit, transpile
    from qiskit.circuit.library import MCMTGate, HGate
    from qiskit.transpiler.passes import HLSConfig  # used for the synthesis config
    
    mcmt = MCMTGate(HGate(), num_ctrl_qubits=5, num_target_qubits=3)
    
    circuit = QuantumCircuit(20)
    circuit.append(mcmt, range(mcmt.num_qubits))
    
    config = HLSConfig(mcmt=["vchain"])  # alternatively use the "noaux" method
    synthesized = transpile(circuit, hls_config=config)

    Además, el MCMTGate también admite estados de control personalizados (es decir, abiertos) de los qubits de control.

  • Como parte de la modernización de la biblioteca de circuitos, cada uno de los siguientes circuitos cuánticos se representa también como un Gate o puede construirse mediante un método de síntesis:

  • La clase CommutationChecker ha sido reescrita en Rust. Esta clase conserva la misma funcionalidad y API pública que antes, pero ahora es significativamente más rápida en la mayoría de los casos.

  • PauliFeatureMap y ZZFeatureMap permiten ahora especificar el entrelazamiento como un diccionario en el que las claves representan el número de qubits, y los valores son listas de tuplas enteras que definen qué qubits están entrelazados entre sí. Esto permite una mayor flexibilidad en la construcción de mapas de características adaptados a algoritmos cuánticos específicos. Ejemplo de uso:

    from qiskit.circuit.library import PauliFeatureMap
    entanglement = {
      1: [(0,), (2,)],
      2: [(0, 1), (1, 2)],
      3: [(0, 1, 2)],
    }
    qc = PauliFeatureMap(3, reps=2, paulis=['Z', 'ZZ', 'ZZZ'], entanglement=entanglement, insert_barriers=True)
    qc.decompose().draw('mpl')
  • El método count_ops() en QuantumCircuit ha sido reescrito en Rust. Ahora funciona entre 3 y 9 veces más rápido.

  • Añadidas funciones de biblioteca de circuitos pauli_feature_map(), z_feature_map(), zz_feature_map() para construir circuitos de mapas de características de Pauli. Estas funciones son aproximadamente 8x más rápidas que los objetos actuales de la biblioteca de circuitos, PauliFeatureMap, ZFeatureMapy ZZFeatureMapy las sustituirán en el futuro.

    Las funciones se pueden utilizar como sustitución directa:

    from qiskit.circuit.library import pauli_feature_map, PauliFeatureMap
    
    fm = pauli_feature_map(20, paulis=["z", "xx", "yyy"])
    also_fm = PauliFeatureMap(20, paulis=["z", "xx", "yyy"]).decompose()

Características primitivas

  • Se ha añadido soporte para datos de nivel 1 a BackendSamplerV2así como la posibilidad de pasar opciones al método run() del método envuelto BackendV2. Las opciones de ejecución pueden especificarse utilizando una entrada "run_options" dentro del diccionario options pasado a BackendSamplerV2. La entrada "run_options" debe ser un diccionario que asigne nombres de argumentos a valores que se pasarán al método run() del backend. Cuando se establece "meas_level = 1 " en las opciones de ejecución, los resultados del backend se tratarán como resultados de nivel 1 en lugar de matrices de bits (el formato de nivel 2).

  • Estimator y StatevectorEstimator devolver valores de expectativas de forma estocástica si el circuito de entrada incluye un reinicio para algunos subsistemas. Antes el resultado no era reproducible, pero ahora puede reproducirse si se fija una semilla aleatoria. Por ejemplo:

    from qiskit.primitives import StatevectorEstimator
    
    estimator = StatevectorEstimator(seed=123)

    o:

    from qiskit.primitives import Estimator
    
    estimator = Estimator(options={"seed":123})

OpenQASM Características

Características de QPY

  • Añadido un nuevo formato QPY versión 13 que añade una representación nativa Qiskit de ParameterExpression objetos.

Características de la información cuántica

  • El rendimiento de SparsePauliOp.from_operator() se ha optimizado a partir de los métodos de mejora de algoritmos introducidos en Qiskit 1.0. Ahora es aproximadamente cinco veces más rápido que antes para matrices totalmente densas, tardando aproximadamente 40ms en descomponer un operador 10q que incluya todos los términos de Pauli.

  • Se ha añadido un nuevo argumento assume_unitary a qiskit.quantum_info.Operator.power(). Cuando True, utilizamos un método más rápido basado en la descomposición de Schur para elevar un Operator a una potencia fraccionaria.

  • Se ha añadido SparsePauliOp.to_sparse_list() para convertir un operador en un formato de lista dispersa. Esto funciona de forma inversa a SparsePauliOp.from_sparse_list(). Por ejemplo:

    from qiskit.quantum_info import SparsePauliOp
    
    op = SparsePauliOp(["XIII", "IZZI"], coeffs=[1, 2])
    sparse = op.to_sparse_list()  # [("X", [3], 1), ("ZZ", [1, 2], 2)]
    
    other = SparsePauliOp.from_sparse_list(sparse, op.num_qubits)
    print(other == op)  # True
  • El rendimiento de Pauli.to_label() ha mejorado significativamente para Paulis grandes.

  • El método Operator.power() tiene un nuevo parámetro branch_cut_rotation. Esto puede utilizarse para desplazar el punto de corte de la rama de la raíz, lo que puede afectar a qué matriz se elige como raíz principal. Por defecto, se establece en una pequeña rotación positiva para que las raíces de los operadores con un valor propio real negativo (como los operadores de Pauli) sean más estables frente a las diferencias de precisión numérica.

  • Se ha añadido una nueva clase observable. SparseObservable representa los observables como una suma de términos, similar a SparsePauliOppero con dos diferencias fundamentales:

    1. Cada término completo se almacena como (efectivamente) una serie de pares (qubit, bit_term) , sin almacenar qubits que sufran la identidad para ese término. Esto mejora significativamente el uso de memoria de observables como la suma ponderada de Paulis iciZi\sum_i c_i Z_i.
    2. El alfabeto de términos de un solo qubit está sobrecompletado para el espacio de operadores; puede representar operadores de Pauli (como SparsePauliOp), pero también proyectores sobre los estados propios de los operadores de Pauli, como 00\lvert 0\rangle\langle 0\rangle. Dichos proyectores pueden medirse en hardware con la misma eficiencia que su correspondiente operador de Pauli, pero SparsePauliOp requeriría un número exponencial de términos para representar 00n{\lvert0\rangle\langle0\rvert}^{\otimes n} sobre nn qubits, mientras que SparseObservable sólo necesita un único término.

    Puede construir y manipular SparseObservable utilizando una interfaz familiar para los usuarios de SparsePauliOp:

    from qiskit.quantum_info import SparseObservable
    
    obs = SparseObservable.from_sparse_list([
      ("XZY", (2, 1, 0), 1.5j),
      ("+-", (100, 99), 0.5j),
      ("01", (50, 49), 0.5),
    ])

    SparseObservable no se admite actualmente como formato de entrada para las primitivas (qiskit.primitives), pero esperamos ampliar estas interfaces para incluirlos en el futuro.

Características de síntesis

  • Funciones de síntesis añadidas synth_mcx_gray_code() y synth_mcx_noaux_v24() que sintetizan compuertas X multicontroladas. Estas funciones no requieren qubits ancilla adicionales.

  • Funciones de síntesis añadidas synth_c3x() y synth_c4x() que sintetizan puertas X de 3 y 4 controles respectivamente.

  • Añadir una función de síntesis synth_mcx_n_dirty_i15() que sintetiza una compuerta X multicontrolada con controles kk utilizando k2k - 2 qubits auxiliares sucios produciendo un circuito con un máximo de 8k68 * k - 6 compuertas CX, por Iten et. al. (arXiv:1501.06911).

  • Añadir una función de síntesis synth_mcx_n_clean_m15() que sintetiza una compuerta X multicontrolada con kk controles utilizando k2k - 2 qubits auxiliares limpios produciendo un circuito con un máximo de 6k66 * k - 6 compuertas CX, por Maslov ( arXiv:1508.03273 ).

  • Añadir una función de síntesis synth_mcx_1_clean_b95() que sintetiza una compuerta X multicontrolada con controles kk utilizando un único qubit auxiliar limpio produciendo un circuito con un máximo de 16k816 * k - 8 compuertas CX, por Barenco et al. ( arXiv:quant-ph/9503016 ).

  • Añadido adder_qft_d00(), adder_ripple_c04()y adder_ripple_v95() para sintetizar las puertas del sumador, ModularAdderGate, HalfAdderGatey FullAdderGate.

  • Añadido multiplier_cumulative_h18() y multiplier_qft_r17() para sintetizar el MultiplierGate.

  • Añadido synth_mcmt_vchain() para sintetizar la puerta multiobjetivo multi-control con un número lineal de puertas Toffoli y k-1 qubits auxiliares para k qubits de control, junto con el plugin de síntesis de alto nivel MCMTSynthesisVChain.

  • Se ha añadido una estructura de plugin de síntesis de alto nivel para el módulo MCMTGateincluyendo el MCMTSynthesisNoAux (sin qubits auxiliares), el ya mencionado MCMTSynthesisVChain (usando num_control - 1 qubits auxiliares), y el MCMTSynthesisDefault para que el compilador elija la descomposición óptima.

  • La función random_clifford() fue portado a Rust, mejorando el tiempo de ejecución en un factor de 3.

  • Añadido ProductFormula.expand()que permite ver la expansión de una fórmula de producto en un formato Pauli disperso. Por ejemplo, podemos consultar el formato de una expansión Trotter de segundo orden de un Hamiltoniano como:

    from qiskit.quantum_info import SparsePauliOp
    from qiskit.circuit.library import PauliEvolutionGate
    from qiskit.synthesis.evolution import SuzukiTrotter
    
    hamiltonian = SparsePauliOp(["IX", "XI", "ZZ"], coeffs=[-1, -1, 1])
    evo = PauliEvolutionGate(hamiltonian, time=3.14)
    trotter = SuzukiTrotter(order=2)
    print(trotter.expand(evo))

    que imprimirá

    [('X', [0], -3.14), ('X', [1], -3.14), ('ZZ', [0, 1], 6.28),
    ('X', [1], -3.14), ('X', [0], -3.14)]
  • Añadida la estructura del plugin PauliEvolutionGate. El plugin por defecto, PauliEvolutionSynthesisDefaultconstruye el circuito como antes, pero más rápido, ya que internamente utiliza Rust. Cuanto mayor sea el circuito (por ejemplo. por el tamaño del hamiltoniano, el número de pasos temporales o el orden Suzuki-Trotter), mayor será la aceleración. Por ejemplo, un Hamiltoniano de Heisenberg de 100 qubits con 10 pasos de tiempo y una fórmula de Trotter de 4º orden se construye ahora ~9.4x más rápido. El nuevo plugin, PauliEvolutionSynthesisRustiqutiliza el algoritmo de síntesis descrito en el artículo " Faster and shorter synthesis of Hamiltonian simulation circuits" de (de) Brugière y Martiel " y está implementado en Rustiq. Por ejemplo:

    from qiskit.circuit import QuantumCircuit
    from qiskit.quantum_info import SparsePauliOp
    from qiskit.circuit.library import PauliEvolutionGate
    from qiskit.compiler import transpile
    from qiskit.transpiler.passes import HLSConfig
    
    op = SparsePauliOp(["XXX", "YYY", "IZZ"])
    qc = QuantumCircuit(4)
    qc.append(PauliEvolutionGate(op), [0, 1, 3])
    config = HLSConfig(PauliEvolution=[("rustiq", {"upto_phase": False})])
    tqc = transpile(qc, basis_gates=["cx", "u"], hls_config=config)
    tqc.draw(output='mpl')
    _images/release_notes-4.png

    Este fragmento de código utiliza el plugin Rustiq para sintetizar PauliEvolutionGate objetos en el circuito cuántico qc. El plugin se llama con la opción adicional upto_phase = False, lo que permite obtener circuitos más pequeños a costa de no conservar posiblemente la fase global. Para obtener la lista completa de opciones compatibles, consulte la documentación de PauliEvolutionSynthesisRustiq.

  • Puerto synth_cz_depth_line_mr() a Rust. Esta función sintetiza un circuito CZ para la conectividad lineal del vecino más próximo (LNN), basado en el método de Maslov y Roetteler. En una matriz binaria de 350x350, la implementación de Rust produce un aumento de velocidad de aproximadamente 30x.

  • Port synth_permutation_reverse_lnn_kms() a Rust, que sintetiza una permutación inversa para la arquitectura LNN utilizando el método Kutin, Moulton, Smithline.

  • Añadido un nuevo argumento preserve_order a ProductFormulaque permite reordenar los términos de Pauli en el Hamiltoniano antes de la expansión de la fórmula del producto, para comprimir la profundidad final del circuito. Fijando esto en False, un término de la forma

Z0Z1+X1X2+Y2Y3Z_0 Z_1 + X_1 X_2 + Y_2 Y_3

se reordenarán en

Z0Z1+Y2Y3+X1X2Z_0 Z_1 + Y_2 Y_3 + X_1 X_2

lo que hará que las rotaciones RZZ y RYY se apliquen en paralelo, en lugar de las tres rotaciones secuenciales de la primera parte.

Esta opción puede configurarse a través de la interfaz del plugin:

from qiskit import QuantumCircuit, transpile
from qiskit.circuit.library import PauliEvolutionGate
from qiskit.quantum_info import SparsePauliOp
from qiskit.synthesis.evolution import SuzukiTrotter
from qiskit.transpiler.passes import HLSConfig

op = SparsePauliOp(["XXII", "IYYI", "IIZZ"])
time, reps = 0.1, 1

synthesis = SuzukiTrotter(order=2, reps=reps)
hls_config = HLSConfig(PauliEvolution=[("default", {"preserve_order": False})])

circuit = QuantumCircuit(op.num_qubits)
circuit.append(PauliEvolutionGate(op, time), circuit.qubits)

tqc = transpile(circuit, basis_gates=["u", "cx"], hls_config=hls_config)
tqc.draw('mpl')
_images/release_notes-5.png

Características del transpilador

  • Añade el argumento matrix_based al CollectCliffords transpiler pass. Si el nuevo parámetro matrix_based=True, el CollectCliffords transpilador puede recoger puertas unitarias que son puertas Clifford para ciertos parámetros, por ejemplo RZGate puertas con ángulos múltiplos de π/2\pi / 2.

  • El RemoveIdentityEquivalent transpilador se ejecuta ahora como parte de los gestores de pases preestablecidos en los niveles de optimización 2 y 3. El pase se ejecuta durante las etapas init y optimization , porque las optimizaciones que aplica son válidas en ambas etapas y el pase es rápido de ejecutar.

  • Añadidos múltiples plugins de síntesis de alto nivel para sintetizar un MCXGate:

    Así como:

    • MCXSynthesisDefaultpara elegir el método de síntesis más eficiente en función del número de qubits ancilla limpios y sucios disponibles.

    Como ejemplo, considere la transpilación del siguiente circuito:

    from qiskit.circuit import QuantumCircuit
    from qiskit.compiler import transpile
    
    qc = QuantumCircuit(7)
    qc.x(0)
    qc.mcx([0, 1, 2, 3], [4])
    qc.mcx([0, 1, 2, 3, 4], [5])
    qc.mcx([0, 1, 2, 3, 4, 5], [6])
    
    transpile(qc).draw('mpl', fold=-1)
    _images/release_notes-6.png

    Para la primera puerta MCX, los qubits 5 y 6 pueden utilizarse como ancillas limpias, y se elegirá el mejor método de síntesis disponible synth_mcx_n_clean_m15 . Para la segunda puerta MCX, el qubit 6 puede ser utilizado como una ancilla limpia, el método synth_mcx_n_clean_m15 ya no se aplica, por lo que el método synth_mcx_1_clean_b95 será elegido. Para la tercera puerta MCX, no hay qubits ancilla, y se elegirá el método synth_mcx_noaux_v24 .

  • El transpilador SabreLayout transpiler pass se ha actualizado para ejecutar dos o tres pruebas de diseño adicionales por defecto, independientemente del valor del argumento de la palabra clave layout_trials . Se incluye un diseño trivial y su inverso para todos los backends, al igual que el DenseLayout que se añadió en 1.2.0. Además, se añaden los anillos más grandes en un gráfico de conectividad de hexágonos pesados de backend IBM si los backends son de 127, 133 o 156 qubits. Esto puede proporcionar un buen punto de partida para algunos circuitos en estos backends de uso común, mientras que para todos los demás es sólo una "prueba aleatoria" adicional.

  • La página DAGCircuit se ha reimplementado en Rust. Esta reescritura de la clase Python debería ser totalmente compatible con la API de la anterior implementación de Python. Mientras que la clase fue implementada previamente usando rustworkx, para la cual la estructura de grafo de datos subyacente existe en Rust, la implementación de la clase y todos los datos se vivieron en Python. Esta nueva versión de DAGCircuit almacena representaciones nativas de Rust para todos sus datos y es más eficiente en memoria gracias a la representación comprimida de qubits y clbits diseñada para instrucciones en reposo. También permite que los pases del transpilador manipulen completamente un DAGCircuit desde Rust, lo que permite mejorar el rendimiento.

  • Se ha añadido un nuevo argumento qubits_initially_zero a qiskit.compiler.transpile(), generate_preset_pass_manager()y a PassManagerConfig. Si se establece en el valor predeterminado de True, se supone que los qubits se encuentran inicialmente en el estado 0|0\rangle, lo que permite potencialmente oportunidades de optimización adicionales para pases individuales del transpilador. En particular, el HighLevelSynthesis transpiler pass elegirá una mejor descomposición para cada MCXGate de un circuito cuando se disponga de un qubit auxiliar inactivo en el estado 0|0\rangle.

    Sin embargo, hay casos en los que qubits_initially_zero debe establecerse en False, como cuando se transpilan para backends que no inicializan correctamente los qubits, o cuando se llaman manualmente pases de transpilador en subcircuitos de un circuito cuántico mayor.

  • El constructor para el HighLevelSynthesis transpiler pass acepta ahora un argumento adicional: qubits_initially_zero. Si se establece en True, el pase asume que los qubits están inicialmente en el estado 0|0\rangle. Además, el pase realiza un seguimiento de los qubits auxiliares limpios y sucios a lo largo de la ejecución, y pasa esta información a los plugins utilizando los kwargs num_clean_ancillas y num_dirty_ancillas.

  • Mejora del tratamiento de los qubits ancilla en el HighLevelSynthesis transpilador. Por ejemplo, un circuito puede tener puertas personalizadas cuyas definiciones incluyan MCXGates. Ahora los algoritmos de síntesis para las puertas internas MCXGates pueden utilizar los qubits ancilla disponibles en el circuito global pero fuera de las definiciones de las puertas personalizadas.

  • Se ha añadido un nuevo método DAGCircuit.control_flow_op_nodes() que proporciona una vía rápida para obtener todos los DAGOpNode en un DAGCircuit que contienen a ControlFlowOp. Esto era posible antes de utilizar el método DAGCircuit.op_nodes() y pasando la clase ControlFlowOp como filtro, pero esta nueva función realizará la operación más rápidamente.

  • La mayoría de los pases del transpilador utilizados en los gestores de pases predefinidos devueltos por generate_preset_pass_manager() y utilizados internamente por transpile() fueron portados a Rust. Esto ha mejorado significativamente el rendimiento en tiempo de ejecución de cada pasada, lo que se ha traducido en una notable mejora de la eficacia operativa global del transpilador. La lista de pases portados a Rust en esta versión son:

  • Añadido un nuevo pase de transpilador RemoveIdentityEquivalent que se utiliza para eliminar las puertas que son equivalentes a una identidad hasta cierta tolerancia. Por ejemplo, si tuvieras un circuito como

    _images/release_notes-7.png

    ejecutar el pase eliminaría el CPhaseGate:

    from qiskit.circuit import QuantumCircuit
    from qiskit.transpiler.passes import RemoveIdentityEquivalent
    
    qc = QuantumCircuit(2)
    qc.cp(1e-20, 0, 1)
    
    removal_pass = RemoveIdentityEquivalent()
    result = removal_pass(qc)
    result.draw("mpl")
    _images/release_notes-8.png
  • El pase ConsolidateBlocks pass ejecutará ahora el equivalente del Collect2qBlocks pass internamente si no se ejecutó en un gestor de pass antes del pass. Anteriormente, Collect2qBlocks o Collect1qRuns tenía que ejecutarse antes ConsolidateBlocks para que ConsolidateBlocks hacer algo. Al realizar la recogida internamente, se reduce la sobrecarga del pase. Si Collect2qBlocks o Collect1qRuns se ejecutan antes que ConsolidateBlocks, se utilizan las ejecuciones recogidas por esos pases del conjunto de propiedades y no se produce ningún cambio en el comportamiento del pase.

  • El RemoveDiagonalGatesBeforeMeasure se ha mejorado para incluir más puertas diagonales: PhaseGate, CPhaseGate, CSGate, CSdgGate y CCZGate. Además, el código del RemoveDiagonalGatesBeforeMeasure fue portado a Rust, y ahora es x20 más rápido para un circuito de 20 qubits.

Funciones de visualización

  • La función de visualización timeline_drawer() función de visualización tiene un nuevo argumento target, utilizado para especificar un Target objeto para la visualización. Por defecto, la función utiliza el Instruction.duration para obtener la duración de una instrucción determinada, pero si se especifica el objetivo se aprovecharán los detalles de temporización dentro del objetivo.

Problemas conocidos

  • Cuando se utilizan los formatos QPY 10, 11 ó 12 con circuitos que contienen ParameterExpressions, si la versión del paquete symengine instalada en el entorno que generó la carga útil (qpy.dump()) no coincide con la versión de symengine instalada en el entorno donde se carga la carga útil (qpy.load()), se producirá un error. Si se encuentra con este error, instale la versión symengine del mensaje de error antes de llamar a qpy.load(). Las versiones de formato QPY 13 o posteriores (o anteriores a la 10) no tendrán este problema. Por lo tanto, si está serializando ParameterExpression objetos como parte de su circuito o cualquier ScheduleBlock objetos, se recomienda que utilice la versión 13 para evitar este problema en el futuro.

Notas de actualización

  • Las siguientes clases utilizan ahora la operación X\sqrt{X} para diagonalizar el operador Pauli-Y: PauliEvolutionGate, EvolvedOperatorAnsatzy PauliFeatureMap. Anteriormente, estas clases utilizaban HSH S o RX(π/2)R_X(-\pi/2) como transformación de base. El uso de la operación X\sqrt{X}, representada por el símbolo SXGate es más eficiente ya que utiliza una única puerta implementada como singleton.

    Si te basabas en el uso anterior de la puerta, te recomendamos construir los circuitos con Qiskit 1.2 y exportarlos con qpy.dump()o escribir un TransformationPassque realice la traducción a la puerta de cambio de base deseada.

  • La versión mínima compatible de Python es ahora 3.9, que ha pasado de la versión mínima anterior de 3.8. Este cambio ha sido necesario porque el proyecto cPython ya no es compatible con Python 3.8.

Notas sobre la actualización de circuitos

  • La clase QuantumVolume generará circuitos con diferentes matrices unitarias y permutaciones para un valor semilla dado de la versión anterior de Qiskit. Esto se debe a la utilización de un nuevo generador interno de números aleatorios para la generación de circuitos que generará el circuito más rápidamente. Si necesitas un circuito exacto con la misma semilla puedes usar la versión anterior de Qiskit y generar el circuito con el argumento flatten=True y exportar el circuito con qpy.dump() y luego cargarlo con esta versión.

Notas sobre la actualización de primitivas

  • Cuando se utiliza BackendSamplerV2los metadatos del circuito ya no se borran antes de pasar los circuitos al método run() de la instancia envuelta BackendV2 envuelta. Si anteriormente confiaba en este comportamiento, puede borrar manualmente los metadatos antes de llamar a BackendSamplerV2.run() llamando a circuit.metadata.clear()

Notas sobre la actualización de QPY

  • La función qpy.dump() emite ahora la versión de formato 13 por defecto. Esto significa que las cargas útiles generadas con esta función por defecto sólo son compatibles con Qiskit 1.3.0 o posterior. Si la carga útil debe ser cargada por una versión anterior de Qiskit, utilice la bandera version en qpy.dump() para emitir la versión apropiada. Consulte la sección Compatibilidad con QPY para obtener más información.

Notas sobre la actualización del transpilador

  • DAGNode (y sus subclases DAGInNode, DAGOutNodey DAGOpNode) ya no devuelven referencias al mismo objeto subyacente desde los métodos DAGCircuit métodos. Nunca antes se había garantizado que todos los nodos devueltos compartieran una referencia al mismo objeto. Sin embargo, con la migración de DAGCircuit a Rust, se genera una nueva instancia de DAGNode sobre la marcha cuando se devuelve un nodo a Python. Estos objetos se evaluarán como iguales utilizando == o comprobaciones similares que se basen en __eq__ , pero ya no se identificarán como el mismo objeto.

  • Las instancias DAGOpNode devueltas por el método DAGCircuit ya no son referencias compartidas a los datos subyacentes almacenados en el DAG. En la versión anterior era posible hacer algo como:

    for node in dag.op_nodes():
        node.op = new_op

    sin embargo, este tipo de mutación siempre ha sido poco sólida, ya que podría romper la caché interna del DAG y provocar la corrupción de la estructura de datos. En su lugar, debe utilizar la API proporcionada por DAGCircuit para mutaciones como DAGCircuit.substitute_node() o DAGCircuit.substitute_node_with_dag(). Por ejemplo, el bloque de código anterior pasaría a ser

    for node in dag.op_nodes():
      dag.substitute_node(node, new_op)

    Esto es similar a una nota de actualización de 1.2.0 donde esto se observó en para la mutación de la DAGOpNode.op y no del atributo DAGOpNode mismo. Sin embargo, en 1.3 esto se extiende a todo el objeto, no sólo a su atributo interno op . En general, este tipo de mutación siempre ha sido poco sólida y no se ha apoyado, pero antes podría haber funcionado potencialmente en algunos casos.

  • En transpile() asume ahora que los qubits están inicialmente en el estado 0|0\rangle. Para evitar esta suposición, se puede establecer el argumento qubits_initially_zero en False.

Notas sobre características en desuso

  • El módulo qiskit.pulse y todas sus funciones asociadas han quedado obsoletas y se eliminarán en Qiskit 2.0.0. Esto se debe a que el principal proveedor de backend con soporte de pulsos es IBM y el acceso a nivel de pulsos actualmente sólo es compatible con un subconjunto de backends de IBM no es compatible con sus arquitecturas más recientes. De manera similar, han anunciado que el acceso a nivel de pulso se eliminará en 2025. Sin que el proveedor más grande siga utilizando la función que admite el acceso a nivel de pulso, la importancia de la función para Qiskit se reduce significativamente y se compara con la sobrecarga de mantenimiento continuo del paquete por el que se está eliminando.

    La desaprobación incluye todo el código de pulse en qiskit.pulse así como la funcionalidad dependiente o relacionada con pulse, como la visualización de pulse, la serialización y el soporte de calibración personalizada. Para obtener más información, consulte las secciones de obsoletos más abajo.

    El paquete Pulse en su conjunto, junto con los componentes directamente relacionados en Qiskit, se trasladará al repositorio Qiskit Dynamics para facilitar aún más la simulación de pulsos y control de bajo nivel. Qiskit 1.x seguirá dando soporte al qiskit.pulse hasta el final de su vida útil.

Circuitos obsoletos

  • Se ha suprimido el atributo Instruction.condition y el método Instruction.c_if() método. Se eliminarán en Qiskit 2.0, junto con cualquier uso en el modelo de datos de Qiskit. Esta funcionalidad ha sido sustituida por la clase IfElseOp que puede utilizarse para describir una condición clásica en un circuito. Por ejemplo, un circuito que utilice Instruction.c_if() como

    from qiskit.circuit import QuantumCircuit
    
    qc = QuantumCircuit(2, 2)
    qc.h(0)
    qc.x(0).c_if(0, 1)
    qc.z(1.c_if(1, 0)
    qc.measure(0, 0)
    qc.measure(1, 1)

    Se puede volver a escribir de esta manera:

    qc = QuantumCircuit(2, 2)
    qc.h(0)
    with qc.if_test((qc.clbits[0], True)):
        qc.x(0)
    with qc.if_test((qc.clbits[1], False)):
        qc.z(1)
    qc.measure(0, 0)
    qc.measure(1, 1)

    El ahora obsoleto ConvertConditionsToIfOps para automatizar esta conversión en los circuitos existentes.


  • Como parte de la obsolescencia del paquete Qiskit Pulse, las siguientes dependencias también quedan obsoletas:

  • En QuantumCircuit.unit y QuantumCircuit.duration han quedado obsoletos y se eliminarán en Qiskit 2.0.0. Estos atributos se utilizaron para rastrear la duración estimada y la unidad de esa duración para ejecutar en el circuito. Sin embargo, los valores de estos atributos eran siempre limitados, ya que sólo se rellenaban correctamente si el transpilador se ejecutaba con la configuración correcta. La duración también era sólo una suposición basada en el camino más largo en la suma de la duración de DAGCircuit y nunca tendría en cuenta correctamente el flujo de control o los condicionales del circuito.

  • En DAGCircuit.unit y DAGCircuit.duration han quedado obsoletos y se eliminarán en Qiskit 2.0.0. Estos atributos se utilizaron para rastrear la duración estimada y la unidad de esa duración para ejecutar en el circuito. Sin embargo, los valores de estos atributos eran siempre limitados, ya que sólo se rellenaban correctamente si el transpilador se ejecutaba con la configuración correcta. La duración también era sólo una suposición basada en el camino más largo en la suma de la duración de DAGCircuit y nunca tendría en cuenta correctamente el flujo de control o los condicionales del circuito.

  • En Instruction.duration y Instruction.unit han quedado obsoletos y se eliminarán en Qiskit 2.0.0. Esto incluye establecer los argumentos unit o duration para cualquier qiskit.circuit.Instruction o subclase. Estos atributos se utilizaron para adjuntar una duración de ejecución personalizada y una unidad para esa duración a una instrucción individual. Sin embargo, la fuente de verdad de la duración de una puerta es el BackendV2 Target que contiene la duración de cada instrucción soportada en el backend. La duración de una instrucción no es algo que normalmente pueda ajustar el usuario y es una propiedad inmutable del backend. Si antes utilizaba esta función para experimentar con diferentes duraciones de puertas, puede mutar el campo InstructionProperties.duration en una instrucción Target para establecer una duración personalizada para una instrucción en un backend (la unidad siempre está en segundos en el campo Target).

Proveedores obsoletos

  • El método BasicSimulator.configuration() está obsoleto y se eliminará en 2.0.0. Este método devuelve una instancia de providers.models.BackendConfiguration heredada que forma parte del modelo obsoleto BackendV1 . Este modelo se ha sustituido por BackendV2en el que las restricciones se almacenan directamente en la instancia de backend o en el archivo subyacente Target (backend.target).

    Esta es una guía rápida para acceder a los atributos más comunes de BackendConfiguration en el modelo BackendV2 modelo:

    BackendV1 model (deprecated) ------------> BackendV2 model
    ----------------------------               ---------------
    backend.configuration().backend_name       backend.name
    backend.configuration().backend_version    backend.backend_version
    backend.configuration().n_qubits           backend.num_qubits
    backend.configuration().num_qubits         backend.num_qubits
    backend.configuration().basis_gates        backend.target.operation_names (*)
    backend.configuration().coupling_map       backend.target.build_coupling_map()
    backend.configuration().local              No representation
    backend.configuration().simulator          No representation
    backend.configuration().conditional        No representation
    backend.configuration().open_pulse         No representation     
    backend.configuration().memory             No representation      
    backend.configuration().max_shots          No representation      

    (*) Tenga en cuenta que Backend.target.operation_names incluye basis_gates e instrucciones adicionales nogate, en algunas implementaciones puede ser necesario filtrar la salida.

    Consulte esta guía para obtener más información sobre la migración al modelo BackendV2 modelo.


  • Como parte de la obsolescencia del paquete Qiskit Pulse, todas las funciones relacionadas con Pulse en qiskit.providers.BackendV2 la clase están quedando obsoletas. Esto incluye los siguientes métodos:

    En consecuencia, los métodos de canalización correspondientes en el qiskit.providers.BackendV2Converter y qiskit.providers.fake_provider.GenericBackendV2 también quedan obsoletos.

    Además, los argumentos pulse_channels y calibrate_instructions del método BackendV2 quedan obsoletos.

  • El argumento defaults está obsoleto en la función qiskit.providers.convert_to_target() función.

QPY Obsolescencias

Deprecaciones del transpilador

  • Obsoleto StochasticSwap que ha sido sustituido por SabreSwap. Si la clase se llama desde la función transpile, el cambio sería, por ejemplo:

    from qiskit import transpile
    from qiskit.circuit import QuantumCircuit
    from qiskit.transpiler import CouplingMap
    from qiskit.providers.fake_provider import GenericBackendV2
    
    
    qc = QuantumCircuit(4)
    qc.h(0)
    qc.cx(0, range(1, 4))
    qc.measure_all()
    
    cmap = CouplingMap.from_heavy_hex(3)
    backend = GenericBackendV2(num_qubits=cmap.size(), coupling_map=cmap)
    
    tqc = transpile(
        qc,
        routing_method="stochastic",
        layout_method="dense",
        seed_transpiler=12342,
        target=backend.target
    )

    a:

    tqc = transpile(
        qc,
        routing_method="sabre",
        layout_method="sabre",
        seed_transpiler=12342,
        target=backend.target
    )

    Mientras que para un gestor de pases, el cambio sería:

    passmanager = PassManager(StochasticSwap(coupling, 20, 13))
    new_qc = passmanager.run(qc)

    a:

    passmanager = PassManager(SabreSwap(backend.target, "basic"))
    new_qc = passmanager.run(qc)
  • El pass transpiler ConvertConditionsToIfOps ha quedado obsoleto y se eliminará en Qiskit 2.0.0. Esta clase ha quedado obsoleta porque el modelo de datos subyacente al que convierte este pase ha quedado obsoleto Instruction.condition del que convierte este pase ha quedado obsoleto y se eliminará en 2.0.0.

  • Proporcionar puertas personalizadas a través del argumento basis_gates está obsoleto tanto para transpile() y generate_preset_pass_manager(). Esta funcionalidad se eliminará en Qiskit 2.0. El modelo Target y se pueden proporcionar a través del argumento target . Se puede construir una Target desde cero o utilizar el método Target.from_configuration() con el argumento custom_name_mapping . Por ejemplo:

    from qiskit.circuit.library import XGate
    from qiskit.transpiler.target import Target
    
    basis_gates = ["my_x", "cx"]
    custom_name_mapping = {"my_x": XGate()}
    target = Target.from_configuration(
        basis_gates=basis_gates, num_qubits=2, custom_name_mapping=custom_name_mapping
    )

  • Como parte de la obsolescencia del paquete Qiskit Pulse, los aspectos relacionados con el pulso en la qiskit.transpiler.Target clase están quedando obsoletos. Esto incluye:


    Además, también se están dejando de utilizar las siguientes pasadas del transpilador:

  • El argumento inst_map en generate_preset_pass_manager(), from_configuration(), PassManagerConfig y generate_scheduling() está obsoleto.

  • El argumento calibration en los métodos InstructionProperties() en los métodos inicializadores.

  • Los siguientes transpile() y generate_preset_pass_manager() quedan obsoletos en favor de la definición de un argumento personalizado Target: instruction_durations, timing_constraints, y backend_properties. Estos argumentos pueden utilizarse para construir un objetivo con Target.from_configuration():

    Target.from_configuration(
         ...
         backend_properties = backend_properties,
         instruction_durations = instruction_durations,
         timing_constraints = timing_constraints
    )
  • El método PassManagerConfig.from_backend() dejará de admitir entradas de tipo BackendV1 en el parámetro backend en una futura versión no anterior a 2.0. BackendV1 está obsoleto y las implementaciones deben pasar a BackendV2.

Herramientas Características en desuso

Corrección de errores

  • Corregida una regresión de rendimiento en QuantumCircuit.assign_parameters() introducida en Qiskit 1.2.0 al llamar al método en un bucle cerrado, que provocaba que sólo un pequeño número de parámetros de un circuito muy paramétrico se ligaran en cada iteración. Si es posible, sigue siendo más eficaz llamar a assign_parameters() sólo una vez, con todas las asignaciones al mismo tiempo, ya que esto reduce la proporción de tiempo dedicado a la normalización de la entrada y la sobrecarga de comprobación de errores.

  • Para BasicSimulatorla entrada basis_gates de la instancia de configuración devuelta por el método configuration() es ahora una lista en lugar de una instancia dict_keys , lo que coincide con el tipo esperado y permite copiar en profundidad la instancia de configuración.

  • Se ha solucionado un problema con DAGCircuit.apply_operation_back() y DAGCircuit.apply_operation_front() por el que si se introducía un objeto Clbit como entrada para el argumento qargs , se aceptaba silenciosamente. Esto se ha corregido para que la falta de correspondencia de tipos se identifique correctamente y se genere una excepción.

  • Se ha corregido un decorador que faltaba en C3SXGate que hacía que fallara si Gate.to_matrix() era llamado. La matriz de la puerta ahora se devuelve como se esperaba.

  • Se ha corregido un error en QuantumCircuit.assign_parameters()que se producía al asignar parámetros a compuertas estándar cuya definición ya se había activado. En este caso, los nuevos valores no se propagaban correctamente a las instancias de la puerta. Aunque el circuito en sí seguía compilándose como se esperaba, al inspeccionar las operaciones individuales seguía apareciendo el parámetro antiguo.

    Por ejemplo:

    from qiskit.circuit.library import EfficientSU2
    
    circuit = EfficientSU2(2, flatten=True)
    circuit.assign_parameters([1.25] * circuit.num_parameters, inplace=True)
    print(circuit.data[0].operation.params)  # would print θ[0] instead of 1.25

    Corregido #13478.

  • Corregido un error con el "circular" y "sca" enredo para NLocal y sus derivados. En el caso de los bloques de entrelazamiento de más de 2 qubits, antes faltaban algunas conexiones en el entrelazamiento circular. Por ejemplo, para 4 qubits y un tamaño de bloque de 3 el código utilizado anteriormente:

    [(2, 3, 0), (0, 1, 2), (1, 2, 3)]

    pero ahora está añadiendo correctamente las conexiones (3, 0, 1) , es decir:

    [(2, 3, 0), (3, 0, 1), (0, 1, 2), (1, 2, 3)]

    Así, los enredos "circular" y "sca" utilizan bloques de enredo num_qubits por capa.

  • Añade más puertas Clifford al CollectCliffords transpiler pass. En particular, hemos añadido las puertas ECRGate, DCXGate, iSwapGate, SXGate y SXdgGate a este paso del transpilador.

  • Se ha corregido un error en QuantumCircuit.decompose() por el que los objetos que podían sintetizarse con HighLevelSynthesis se sintetizaban primero y luego se descomponían inmediatamente (es decir, se descomponían dos veces en lugar de una). Esto afectó a puertas como MCXGate o Cliffordentre otras.

  • Se ha corregido un error en QuantumCircuit.decompose()por el que los objetos de alto nivel sin definición no se descomponían si se establecían explícitamente mediante el argumento "gates_to_decompose" . Por ejemplo, antes lo siguiente no realizaba una descomposición, pero ahora funciona como se espera:

    from qiskit import QuantumCircuit
    from qiskit.quantum_info import Clifford
    from qiskit.transpiler.passes import Decompose
    
    cliff = Clifford(HGate())
    circuit = QuantumCircuit(1)
    circuit.append(cliff, [0])
    
    decomposed = Decompose(gates_to_decompose=["clifford"])(circuit)
  • Anteriormente, el HighLevelSynthesis transpiler pass sintetizaba una instrucción para la que existía un plugin de síntesis, independientemente de si la instrucción ya era compatible con el destino o formaba parte de la instrucción pasada explícitamente basis_gates. Ahora se ha corregido este comportamiento, de modo que ya no se sintetizan estas instrucciones ya soportadas.

  • El paso de transpilación InverseCancellation recurrirá ahora a ControlFlowOp operaciones presentes en un QuantumCircuit. Anteriormente, el pase ignoraba los pares de puertas inversas dentro de los bloques de flujo de control que podrían haberse cancelado. Consulte el nº 13437 para más detalles.

  • Corrección de un error en Isometry debido a una aserción innecesaria, que provocaba un error en UnitaryGate.control() cuando UnitaryGate tenía más de dos qubits.

  • El atributo QuantumCircuit.parameters estará vacío cuando se utilice QuantumCircuit.copy_empty_like() en un circuito paramétrico. Anteriormente, una caché interna se copiaba sin invalidarse. Corrección #12617.

  • QuantumCircuit.depth() manejará ahora correctamente las operaciones que no tengan operandos, tales como GlobalPhaseGate.

  • QuantumCircuit.depth() contará ahora las variables y clbits utilizados en las expresiones en tiempo real como parte del cálculo de profundidad.

  • Arreglar el SolovayKitaev al cargar aproximaciones básicas a partir de un archivo existente en .npy . Anteriormente, cargar una aproximación almacenada que permitía reducciones adicionales (por ejemplo, debido a cancelaciones de puertas) podía provocar un fallo en tiempo de ejecución. Además, la diferencia de fase global del producto de compuerta U(2) y la representación SO(3) se perdió durante un procedimiento de guardar-recargar. Arregla Qiskit/qiskit#12576.

  • Se ha corregido un error cuando SparsePauliOp.paulis se establece como un PauliList con fase distinta de cero, por el que las llamadas posteriores a varios métodos SparsePauliOp producían resultados incorrectos. Ahora, cuando SparsePauliOp.paulis se fija en un PauliList con fase distinta de cero, la fase se absorbe en SparsePauliOp.coeffsy la fase de la entrada PauliList se pone a cero.

  • Se ha corregido un error en qiskit.visualization.pulse_v2.interface.draw que no dibujaba los programas de pulsos cuando se llamaba a la función dibujar con un BackendV2 argumento. Dado que el backend V2 no informa de las frecuencias de los canales hardware, el dibujo generado mostrará 'no freq' debajo de cada etiqueta de canal.

  • Se ha solucionado un problema con dag_drawer() y DAGCircuit.draw() cuando se intentaba visualizar una instancia DAGCircuit que contenía Var cables, por lo que el visualizador lanzaba una excepción. Este comportamiento se ha corregido y se generará la visualización esperada.

  • El pase VF2Layout pass lanzaría una excepción cuando se le proporcionara una Target sin restricciones de conectividad. Este sería el caso de los objetivos de Aer 0.13. El problema se ha solucionado.

  • Corrige un error al llamar al método Gate.repeat(). Consulte el nº 11990 para más detalles.

  • Se ha corregido un error que provocaba que Statevector.expectation_value() diera resultados incorrectos para el operador de identidad cuando el vector de estado no estaba normalizado.

  • El constructor GenericBackendV2 estaba permitiendo crear backends malformados porque aceptaba puertas base que no podían ser asignadas en el tamaño de backend especificado. Es decir, un backend con un solo qubit no debería aceptar una base con puertas de dos qubits.

  • ParameterExpression se actualizó para que las instancias totalmente vinculadas que se comparan con instancias de los tipos numéricos incorporados de Python (como float y int) también tengan valores hash que coincidan con los de las otras instancias. Este cambio garantiza que estos tipos puedan utilizarse indistintamente como claves de diccionario. Ver #12488.

  • El analizador OpenQASM 2 (qiskit.qasm2) ahora puede manejar condicionales con enteros que no caben en un entero de 64 bits. Corregido #12773.

  • Las compuertas personalizadas (aquellas derivadas de una sentencia gate ) en programas importados de OpenQASM 2 tendrán ahora una Gate.to_matrix() implementación. Antes no tenían definición de matriz, lo que significaba que los viajes de ida y vuelta a través de OpenQASM 2 podían perder innecesariamente la capacidad de derivar la matriz de la puerta. Nótese, sin embargo, que la matriz se calcula encontrando recursivamente las matrices de las definiciones de las puertas internas, como hace Operator lo que puede ser menos eficaz que antes de la ida y vuelta.

  • Anteriormente, DAGCircuit.replace_block_with_op() permitía colocar una operación n-qubit en un bloque de m qubits, dejando el DAG en un estado inválido. Este comportamiento se ha corregido y el intento generará un mensaje DAGCircuitError.

  • Fijo Operator.power() cuando se llama con potencias no enteras en una matriz cuya forma Schur no es diagonal (por ejemplo, la mayoría de las matrices no unitarias).

  • Operator.power() devolverá ahora de forma más fiable el valor principal esperado de una matriz potencia fraccionaria de una matriz unitaria con un valor propio 1-1. Esto es delicado en general, porque los efectos de redondeo en coma flotante pueden hacer que una matriz tenga un valor propio en el lado negativo del corte de rama (incluso si su relación matemática exacta no lo haría), y la imprecisión en varias llamadas BLAS puede encontrar falsamente el lado equivocado del corte de rama.

    Operator.power() ahora desplaza la ubicación de corte de rama para potencias de matriz a una pequeña rotación compleja lejos de 1-1. Esto no resuelve el problema, sólo lo desplaza a un lugar donde es mucho menos probable que sea notable para los tipos de operadores que suelen aparecer. Utiliza el nuevo parámetro branch_cut_rotation para tener más control sobre esto.

    Ver #13305.

  • Corregido un no-determinismo por proceso en SparsePauliOp.to_matrix(). El orden exacto de las operaciones de coma flotante en la suma variaba antes por proceso, pero ahora será idéntico entre distintas invocaciones del mismo script. Ver #13413.

  • Target.has_calibration() se ha actualizado para que no lance una excepción para una instrucción que se ha añadido al objetivo con None para sus propiedades de instrucción. Correcciones #12525.

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