Skip to main content
IBM Quantum Platform

Notas de la versión de Qiskit 0.40


0.40.0

Esta versión deja oficialmente obsoleto el proyecto de proveedor IBMQ de Qiskit como parte del metapaquete Qiskit. Esto significa que, en una futura versión, pip install qiskit ya no incluirá automáticamente qiskit-ibmq-provider. Si actualmente está instalando o listando qiskit como una dependencia para obtener qiskit-ibmq-provider, debe actualizar para incluir explícitamente qiskit-ibmq-provider también. Esto se está haciendo a medida que el proyecto Qiskit avanza hacia un modelo en el que el paquete qiskit sólo contiene la funcionalidad básica común para construir y compilar circuitos cuánticos, programas y aplicaciones. Los paquetes que se basen en ese núcleo o vinculen Qiskit a hardware o simuladores podrán instalarse como paquetes independientes.

Terra 0.23.0

Preludio

Qiskit Terra 0.23.0 es una importante versión que incluye multitud de nuevas funciones y correcciones de errores. Los aspectos más destacados de esta versión son:

Esta versión también deja de ser compatible con Python 3.7. Ahora se emitirá un DeprecationWarning si ejecutas Qiskit con Python 3.7. La compatibilidad con Python 3.7 se eliminará como parte de la versión 0.25.0 (actualmente prevista para julio de 2023), momento en el que necesitará Python 3.8 o una versión más reciente para utilizar Qiskit.

Nuevas funciones

  • Los pulsos en qiskit.pulse.library

    puede inicializarse con el nuevo parámetro angle, de forma que podrían proporcionarse dos parámetros flotantes: amp y angle. La inicialización con el complejo amp sigue siendo posible.

  • La clase AdaptVQE tiene un nuevo atributo, eigenvalue_historyque se utiliza para rastrear la energía más baja alcanzada por iteración de AdaptVQE. Por ejemplo:

    from qiskit.algorithms.minimum_eigensolvers import VQE
    from qiskit.algorithms.minimum_eigensolvers.adapt_vqe import AdaptVQE
    from qiskit.algorithms.optimizers import SLSQP
    from qiskit.circuit.library import EvolvedOperatorAnsatz
    from qiskit.opflow import PauliSumOp
    from qiskit.primitives import Estimator
    from qiskit.quantum_info import SparsePauliOp
    from qiskit.utils import algorithm_globals
    
    excitation_pool = [
        PauliSumOp(
            SparsePauliOp(["IIIY", "IIZY"], coeffs=[0.5 + 0.0j, -0.5 + 0.0j]), coeff=1.0
        ),
        PauliSumOp(
            SparsePauliOp(["ZYII", "IYZI"], coeffs=[-0.5 + 0.0j, 0.5 + 0.0j]), coeff=1.0
        ),
        PauliSumOp(
            SparsePauliOp(
                ["ZXZY", "IXIY", "IYIX", "ZYZX", "IYZX", "ZYIX", "ZXIY", "IXZY"],
                coeffs=[
                    -0.125 + 0.0j,
                    0.125 + 0.0j,
                    -0.125 + 0.0j,
                    0.125 + 0.0j,
                    0.125 + 0.0j,
                    -0.125 + 0.0j,
                    0.125 + 0.0j,
                    -0.125 + 0.0j,
                ],
            ),
            coeff=1.0,
        ),
    ]
    ansatz = EvolvedOperatorAnsatz(excitation_pool, initial_state=self.initial_state)
    optimizer = SLSQP()
    h2_op = PauliSumOp.from_list(
        [
            ("IIII", -0.8105479805373266),
            ("ZZII", -0.2257534922240251),
            ("IIZI", +0.12091263261776641),
            ("ZIZI", +0.12091263261776641),
            ("IZZI", +0.17218393261915543),
            ("IIIZ", +0.17218393261915546),
            ("IZIZ", +0.1661454325638243),
            ("ZZIZ", +0.1661454325638243),
            ("IIZZ", -0.2257534922240251),
            ("IZZZ", +0.16892753870087926),
            ("ZZZZ", +0.17464343068300464),
            ("IXIX", +0.04523279994605788),
            ("ZXIX", +0.04523279994605788),
            ("IXZX", -0.04523279994605788),
            ("ZXZX", -0.04523279994605788),
        ]
    )
    
    algorithm_globals.random_seed = 42
    calc = AdaptVQE(VQE(Estimator(), ansatz, self.optimizer))
    res = calc.compute_minimum_eigenvalue(operator=h2_op)
    
    print(calc.eigenvalue_history)

    el valor devuelto de calc.history debería ser aproximadamente [-1.85727503] ya que hay una única iteración.

  • Se ha mejorado el registro en tiempo de ejecución cuando se ejecuta el AdaptVQE se ha mejorado. Al ejecutar la clase ahora, se emitirán mensajes de registro de nivel DEBUG y INFO mientras se ejecuta la clase.

  • Añadido un nuevo pase de transpilador, CollectAndCollapse, para recoger y consolidar bloques de nodos en un circuito. Este pase está diseñado para ser una clase base general para la recopilación y consolidación de bloques combinados. Para ser completamente general, el trabajo de recoger y colapsar los bloques se realiza a través de funciones proporcionadas durante la instanciación del pase. Por ejemplo, el CollectLinearFunctions se ha actualizado para heredar de CollectAndCollapse y recoge bloques de CXGate y SwapGate y sustituye cada bloque por una puerta LinearFunction. El CollectCliffords que ahora también se basa en CollectAndCollapse, recoge bloques de puertas "Clifford" y sustituye cada bloque por un Clifford.

    La interfaz también admite la opción do_commutative_analysis, que permite explotar la conmutatividad entre puertas para reunir bloques de nodos más grandes. Por ejemplo, recogiendo bloques de puertas CX en el siguiente circuito:

    qc = QuantumCircuit(2)
    qc.cx(0, 1)
    qc.z(0)
    qc.cx(1, 0)

    el uso de do_commutative_analysis permite consolidar las dos puertas CX, ya que la primera puerta CX y la puerta Z se conmutan.

  • Añadida una nueva clase BlockCollector que implementa varias estrategias de recolección, y una nueva clase BlockCollapser que implementa varias estrategias de colapso. En la actualidad BlockCollector incluye la estrategia de recopilar con avidez todas las compuertas que se adhieren a una función de filtro dada (por ejemplo, recopilar todas las compuertas Clifford), y BlockCollapser incluye la estrategia de consolidar todas las compuertas de un bloque en un único objeto (o ejemplo, un bloque de compuertas Clifford puede consolidarse en un único Clifford).

  • Se ha añadido un nuevo CollectCliffords transpilador que recoge bloques de puertas Clifford y los consolida en objetos qiskit.quantum_info.Clifford objetos. Este pase hereda de CollectAndCollapse y, en particular, admite la opción do_commutative_analysis. También admite dos opciones adicionales split_blocks y min_block_size. Consulte las notas de la versión de CollectAndCollapse y CollectLinearFunctions para más detalles.

  • El CollectLinearFunctions transpiler pass tiene varios argumentos nuevos en su constructor:

    • do_commutative_analysispermite explotar la conmutatividad entre puertas para reunir bloques de nodos más grandes.

    • split_blockspermite dividir los bloques recogidos en subbloques sobre subconjuntos disjuntos de qubits. Por ejemplo, en el siguiente circuito:

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

      el bloque único de compuertas CX sobre qubits {0, 1, 2, 3} puede dividirse en dos subbloques disjuntos, uno sobre qubits {0, 2} y otro sobre qubits {1, 3}.

    • min_block_size: permite especificar el tamaño mínimo del bloque que se va a consolidar, los bloques con menos puertas no se modificarán. Por ejemplo, en el siguiente circuito:

      qc = QuantumCircuit(4)
      qc.cx(1, 2)
      qc.cx(2, 1)

      las dos puertas CX se consolidarán cuando min_block_size sea 1 ó 2, y permanecerán inalteradas cuando min_block_size sea 3 o mayor.

  • Añadido un algoritmo de síntesis de profundidad eficiente synth_cnot_depth_line_kms() para circuitos lineales reversibles LinearFunction sobre la arquitectura lineal del vecino más próximo, siguiendo el artículo: https://arxiv.org/abs/quant-ph/0701194.

  • El método DAGCircuit.replace_block_with_op() devolverá el nuevo bloque DAGOpNode que se crea cuando se sustituye el bloque. Antes, llamar a este método no devolvía nada.

  • Añadido un algoritmo de síntesis de profundidad eficiente synth_permutation_depth_lnn_kms() para Permutation sobre la arquitectura lineal de vecino más próximo, siguiendo el artículo: https://arxiv.org/abs/quant-ph/0701194

  • Se ha añadido una nueva clase PermutationGate para representar la lógica de permutación como un elemento de circuito. A diferencia del elemento Permutation que tenía una definición estática, esta nueva clase evita sintetizar un circuito de permutación cuando se declara. Esto retrasa la síntesis real al transpilador. También permite utilizar varios algoritmos diferentes para sintetizar permutaciones, que están disponibles como plugins de permutación de síntesis de alto nivel.

    Otra característica clave del PermutationGate es que implementa la interfaz __array__ para devolver eficientemente una matriz unitaria para una permutación.

  • Añadidos varios plugins de síntesis de alto nivel para sintetizar permutaciones:

    • BasicSynthesisPermutationse aplica a arquitecturas totalmente conectadas y se basa en la clasificación. Este es el algoritmo utilizado anteriormente para construir circuitos cuánticos para permutaciones.
    • ACGSynthesisPermutationse aplica a arquitecturas totalmente conectadas, pero se basa en el método de Alon, Chung y Graham. Sintetiza cualquier permutación en profundidad 2 (medida en términos de SWAPs).
    • KMSSynthesisPermutation: se aplica a las arquitecturas lineales de vecino más próximo y corresponde al método Kutin, Moulton, Smithline recientemente añadido.

    Por ejemplo:

    from qiskit.circuit import QuantumCircuit
    from qiskit.circuit.library import PermutationGate
    from qiskit.transpiler import PassManager
    from qiskit.transpiler.passes.synthesis.high_level_synthesis import HLSConfig, HighLevelSynthesis
    from qiskit.transpiler.passes.synthesis.plugin import HighLevelSynthesisPluginManager
    
    # Create a permutation and add it to a quantum circuit
    perm = PermutationGate([4, 6, 3, 7, 1, 2, 0, 5])
    qc = QuantumCircuit(8)
    qc.append(perm, range(8))
    
    # Print available plugin names for synthesizing permutations
    # Returns ['acg', 'basic', 'default', 'kms']
    print(HighLevelSynthesisPluginManager().method_names("permutation"))
    
    # Default plugin for permutations
    # Returns a quantum circuit with size 6 and depth 3
    qct = PassManager(HighLevelSynthesis()).run(qc)
    print(f"Default: {qct.size() = }, {qct.depth() = }")
    
    # KMSSynthesisPermutation plugin for permutations
    # Returns a quantum circuit with size 18 and depth 6
    # but adhering to the linear nearest-neighbor architecture.
    qct = PassManager(HighLevelSynthesis(HLSConfig(permutation=[("kms", {})]))).run(qc)
    print(f"kms: {qct.size() = }, {qct.depth() = }")
    
    # BasicSynthesisPermutation plugin for permutations
    # Returns a quantum circuit with size 6 and depth 3
    qct = PassManager(HighLevelSynthesis(HLSConfig(permutation=[("basic", {})]))).run(qc)
    print(f"basic: {qct.size() = }, {qct.depth() = }")
    
    # ACGSynthesisPermutation plugin for permutations
    # Returns a quantum circuit with size 6 and depth 2
    qct = PassManager(HighLevelSynthesis(HLSConfig(permutation=[("acg", {})]))).run(qc)
    print(f"acg: {qct.size() = }, {qct.depth() = }")
  • Añadidas nuevas clases para los algoritmos Quantum Fisher Information (QFI) y Quantum Geometric Tensor (QGT) utilizando primitives, qiskit.algorithms.gradients.QFI y qiskit.algorithms.gradients.LinCombQGTal módulo de gradientes: qiskit.algorithms.gradients. Por ejemplo:

    from qiskit.circuit import QuantumCircuit, Parameter
    from qiskit.algorithms.gradients import LinCombQGT, QFI
    
    estimator = Estimator()
    a, b = Parameter("a"), Parameter("b")
    qc = QuantumCircuit(1)
    qc.h(0)
    qc.rz(a, 0)
    qc.rx(b, 0)
    
    parameter_value = [[np.pi / 4, 0]]
    
    qgt = LinCombQGT(estimator)
    qgt_result = qgt.run([qc], parameter_value).result()
    
    qfi = QFI(qgt)
    qfi_result = qfi.run([qc], parameter_value).result()
  • Se ha añadido un nuevo argumento de palabra clave, derivative_type, al constructor de la función LinCombEstimatorGradient. Este argumento toma un enum DerivativeType que permite especificar calcular sólo las partes reales o imaginarias del gradiente.

  • Añadida una nueva opción circuit_reverse_bits al archivo de configuración del usuario. Esto permite a los usuarios establecer un booleano para su comportamiento preferido por defecto del argumento reverse_bits de los dibujantes de circuitos QuantumCircuit.draw() y circuit_drawer(). Por ejemplo, añadiendo una sección al archivo de configuración del usuario en la ubicación predeterminada ~/.qiskit/settings.conf con:

    [default]
    circuit_reverse_bits = True

    cambiará el valor por defecto para mostrar los bits en orden inverso.

  • Añadida una nueva clase Z2Symmetries a qiskit.quantum_info que se utiliza para identificar cualquier Z2Z_2 simetrías de una entrada SparsePauliOp.

  • Añadida una nueva directiva de pulso TimeBlockade. Esta directiva se comporta de forma casi idéntica a la instrucción delay, pero se eliminará antes de la ejecución. Esta directiva está pensada para ser utilizada internamente dentro del constructor de pulsos y ayuda a ScheduleBlock a representar instrucciones con intervalos de tiempo absolutos. Esto permite al constructor de impulsos convertir Schedule en ScheduleBlock, en lugar de envolver con Call instrucciones.

  • Añadidos algoritmos con primitivas para la Evolución Cuántica Variable del Tiempo que implementan la interfaz para la Evolución Cuántica del Tiempo. La clase qiskit.algorithms.VarQRTE se utiliza para la evolución real y la clase qiskit.algorithms.VarQITE clase se utiliza para la evolución del tiempo cuántico imaginario según un principio variacional pasado.

    Cada algoritmo acepta un principio variacional que implementa la ImaginaryVariationalPrinciple interfaz abstracta. Se incluyen las siguientes implementaciones:

    Por ejemplo:

    from qiskit.algorithms import TimeEvolutionProblem, VarQITE
    from qiskit.algorithms.time_evolvers.variational import ImaginaryMcLachlanPrinciple
    from qiskit.circuit.library import EfficientSU2
    from qiskit.quantum_info import SparsePauliOp
    import numpy as np
    
    observable = SparsePauliOp.from_list(
        [
            ("II", 0.2252),
            ("ZZ", 0.5716),
            ("IZ", 0.3435),
            ("ZI", -0.4347),
            ("YY", 0.091),
            ("XX", 0.091),
        ]
    )
    
    ansatz = EfficientSU2(observable.num_qubits, reps=1)
    init_param_values = np.zeros(len(ansatz.parameters))
    for i in range(len(ansatz.parameters)):
        init_param_values[i] = np.pi / 2
    var_principle = ImaginaryMcLachlanPrinciple()
    time = 1
    evolution_problem = TimeEvolutionProblem(observable, time)
    var_qite = VarQITE(ansatz, var_principle, init_param_values)
    evolution_result = var_qite.evolve(evolution_problem)
  • Añadidas reglas para convertir XXPlusYYGate y XXMinusYYGate a otras puertas en SessionEquivalenceLibrary. Esto permite ejecutar transpile() apuntando a un backend o Target que utilice estas puertas.

  • Añadidos dos nuevos backends falsos FakePrague y FakeSherbrooke al módulo qiskit.providers.fake_provider módulo. FakePrague proporciona un backend con una instantánea de las propiedades del backend IBM Garceta de Praga R1 y FakeSherbrooke proporciona un backend con una instantánea de las propiedades del backend IBM Águila de Sherbrooke R3.

  • Se ha añadido un nuevo argumento de palabra clave, allow_unknown_parameters, a los parámetros ParameterExpression.bind() y ParameterExpression.subs() y. Este nuevo argumento permite pasar un diccionario con parámetros desconocidos a estos métodos sin que se produzca un error. Anteriormente, esto siempre generaba un error sin que hubiera forma de desactivar ese comportamiento.

  • El argumento BaseEstimator.run() del método observables acepta ahora un tipo de entrada str o una secuencia de str además de los otros tipos ya aceptados. Cuando se utiliza, el formato de la cadena de entrada debe coincidir con la representación de cadena Pauli aceptada por el constructor de objetos Pauli objetos.

  • Se ha añadido un nuevo método constructor QuantumCircuit.from_instructions() que permite crear un QuantumCircuit a partir de un iterable de instrucciones. Por ejemplo:

    from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
    from qiskit.circuit.quantumcircuitdata import CircuitInstruction
    from qiskit.circuit import Measure
    from qiskit.circuit.library import HGate, CXGate
    
    
    qr = QuantumRegister(2)
    cr = ClassicalRegister(2)
    instructions = [
        CircuitInstruction(HGate(), [qr[0]], []),
        CircuitInstruction(CXGate(), [qr[0], qr[1]], []),
        CircuitInstruction(Measure(), [qr[0]], [cr[0]]),
        CircuitInstruction(Measure(), [qr[1]], [cr[1]]),
    ]
    circuit = QuantumCircuit.from_instructions(instructions)
    circuit.draw("mpl")
    _images/legacy_release_notes-3.png
  • La clase Clifford toma ahora un argumento opcional de la palabra clave copy en su constructor. Si se establece en False, entonces un StabilizerTable proporcionado como entrada no se copiará, sino que se utilizará directamente. Esto puede tener ventajas de rendimiento, si los datos de la tabla no van a mutar nunca por ningún otro medio.

  • El rendimiento de Clifford.compose() ha mejorado mucho para todos los números de qubits. Para operadores de 20 qubits, el aumento de velocidad es del orden de 100 veces.

  • Añadida una nueva función de síntesis synth_clifford_layers()para sintetizar un Clifford en capas. El algoritmo se basa en S. Bravyi, D. Maslov, Los circuitos sin Hadamard exponen la estructura del grupo de Clifford, arxiv:2003.09412. Esto descompone el Clifford en 8 capas de puertas, incluyendo dos capas de puertas CZ y una capa de puertas CX. Por ejemplo, un circuito Clifford de 5 qubits se descompone en las siguientes capas:

         ┌─────┐┌─────┐┌────────┐┌─────┐┌─────┐┌─────┐┌─────┐┌────────┐
    q_0:0    ├┤0    ├┤0       ├┤0    ├┤0    ├┤0    ├┤0    ├┤0
         │     ││     ││        ││     ││     ││     ││     ││        │
    q_1:1    ├┤1    ├┤1       ├┤1    ├┤1    ├┤1    ├┤1    ├┤1
         │     ││     ││        ││     ││     ││     ││     ││        │
    q_2:2 S2 ├┤2 CZ ├┤2 CX_dg ├┤2 H2 ├┤2 S1 ├┤2 CZ ├┤2 H1 ├┤2 Pauli ├
         │     ││     ││        ││     ││     ││     ││     ││        │
    q_3:3    ├┤3    ├┤3       ├┤3    ├┤3    ├┤3    ├┤3    ├┤3
         │     ││     ││        ││     ││     ││     ││     ││        │
    q_4:4    ├┤4    ├┤4       ├┤4    ├┤4    ├┤4    ├┤4    ├┤4
         └─────┘└─────┘└────────┘└─────┘└─────┘└─────┘└─────┘└────────┘

    Este método permitirá descomponer un Clifford en profundidad de 2 qubits 7n+27n+2 para la conectividad del vecino más próximo lineal (LNN).

  • Los tipos de retorno de los métodos power() de varias clases de compuertas de la biblioteca estándar se han actualizado para devolver objetos de compuerta más específicos que dan como resultado una salida con menos pérdidas y más eficiente. Por ejemplo, ejecutar power() devuelve ahora una instancia IGate en lugar de UnitaryGate como se hacía anteriormente.

    La lista completa de los tipos de salida que se han mejorado son:

  • El EquivalenceLibrary se representa ahora internamente como un PyDiGraph, este objeto gráfico subyacente puede ser accedido desde el nuevo atributo graph atributo. Este atributo está pensado para su uso interno en Qiskit y, por lo tanto, debe copiarse siempre antes de ser modificado por el usuario para evitar posibles corrupciones del gráfico de equivalencia interno.

  • El método constructor Operator.from_circuit() invertirá ahora la permutación de salida causada por la etapa de enrutamiento/mapa de intercambio del transpilador. Por defecto, si un circuito transpilado tiene puertas Swap insertadas, la matriz de salida tendrá esa permutación invertida, por lo que la matriz devuelta será equivalente al circuito original no transpilado. Si desea desactivar este comportamiento por defecto, el argumento de la palabra clave ignore_set_layout puede establecerse en True para hacerlo (además del comportamiento anterior de ignorar el diseño inicial de la transpilación). Si desea establecer manualmente una disposición final, puede utilizar el nuevo argumento de palabra clave final_layout para pasar un objeto Layout para la permutación de salida.

  • Se ha añadido soporte al GateDirection transpiler pass para manejar el simétrico RXXGate, RYYGatey RZZGate simétricas. El pase ahora manejará correctamente estas puertas y simplemente invertirá el orden de qargs en su lugar sin ninguna otra modificación.

  • Se ha añadido soporte para utilizar el operador de exponenciación Python, **, con objetos Gate ahora es compatible. Equivale a ejecutar el método Gate.power() en el objeto.

    Por ejemplo:

    from qiskit.circuit.library import XGate
    
    sx = XGate() ** 0.5
  • Añadida nueva forma de pulso GaussianSquareDrag al qiskit.pulse.library módulo. Esta forma de pulso es similar a GaussianSquare pero utiliza la forma Drag durante su ascenso y descenso. La corrección de la forma del pulso DRAG puede suprimir parte del espectro de frecuencia de la subida y bajada del pulso, lo que puede ayudar a evitar excitar qubits espectadores cuando están cerca en frecuencia de la frecuencia de accionamiento del pulso.

  • Se ha añadido un nuevo argumento de palabra clave, method, a los constructores de los módulos FiniteDiffEstimatorGradient y FiniteDiffSamplerGradient . El argumento method acepta una cadena para indicar el método de cálculo a utilizar para el gradiente. Existen tres métodos: "central", "forward" y "backward". La definición de los métodos son:

    Método
    Cálculo
    "central"f(x+e)f(xe)2e\frac{f(x+e)-f(x-e)}{2e}
    "forward"f(x+e)f(x)e\frac{f(x+e) - f(x)}{e}
    "backward"f(x)f(xe)e\frac{f(x)-f(x-e)}{e}

    donde ee es el épsilon de desplazamiento.

  • Todas las clases de gradiente en qiskit.algorithms.gradients ahora conservan las operaciones no parametrizadas en lugar de intentar desenrollarlas. Esto permite evaluar gradientes en puertas opacas personalizadas que las primitivas individuales pueden manejar y mantiene un mayor nivel de abstracción para la síntesis optimizada y la compilación después de que se hayan construido los circuitos de gradiente.

  • Se ha añadido un TranslateParameterizedGates para asignar sólo puertas parametrizadas en un circuito a una base especificada, pero dejar las puertas no parametrizadas intactas. La pasada primero intenta desenrollar y finalmente traduce si una puerta parametrizada no puede desenrollarse más.

  • El CollectCliffords se ha ampliado para recoger y combinar bloques de "puertas clifford" en objetos de tipo Clifford donde las "puertas clifford" ahora también pueden incluir objetos de tipo LinearFunction, Cliffordy PauliGate. Por ejemplo:

    from qiskit.circuit import QuantumCircuit
    from qiskit.circuit.library import LinearFunction, PauliGate
    from qiskit.quantum_info.operators import Clifford
    from qiskit.transpiler.passes import CollectCliffords
    from qiskit.transpiler import PassManager
    
    # Create a Clifford
    cliff_circuit = QuantumCircuit(2)
    cliff_circuit.cx(0, 1)
    cliff_circuit.h(0)
    cliff = Clifford(cliff_circuit)
    
    # Create a linear function
    lf = LinearFunction([[0, 1], [1, 0]])
    
    # Create a pauli gate
    pauli_gate = PauliGate("XYZ")
    
    # Create a quantum circuit with the above and also simple clifford gates.
    qc = QuantumCircuit(4)
    qc.cz(0, 1)
    qc.append(cliff, [0, 1])
    qc.h(0)
    qc.append(lf, [0, 2])
    qc.append(pauli_gate, [0, 2, 1])
    qc.x(2)
    
    # Run CollectCliffords transpiler pass
    qct = PassManager(CollectCliffords()).run(qc)

    Todas las puertas se recogerán y combinarán en una única Clifford. Así, el circuito final consta de un único Clifford objeto.

  • CouplingMap es ahora implícitamente iterable, siendo la iteración idéntica a iterar a través de la salida de CouplingMap.get_edges(). En otras palabras,

    from qiskit.transpiler import CouplingMap
    coupling = CouplingMap.from_line(3)
    list(coupling) == list(coupling.get_edges())

    funcionará ahora como se espera, al igual que otras iteraciones. Esto es puramente una conveniencia sintáctica.

  • Añadida una nueva función synth_cnot_count_full_pmh() que se utiliza para sintetizar circuitos lineales reversibles para arquitecturas todo-a-todo utilizando el método de Patel, Markov y Hayes. Esta función es idéntica a la disponible en qiskit.transpiler.synthesis.cnot_synth() , pero tiene un nombre más descriptivo y se sitúa de forma más lógica en el árbol de paquetes. Esta nueva función sustituye a la anterior, que probablemente quedará obsoleta en una futura versión.

  • InstructionScheduleMap se ha actualizado para almacenar los datos de calibración del backend en el formato de PulseQobj JSON e invoca la conversión cuando se accede a los datos por primera vez, es decir, conversión perezosa. Esta actualización de la lógica interna mejora drásticamente el rendimiento del backend de carga, especialmente con muchas entradas de calibración.

  • Se ha añadido el nuevo módulo qiskit.pulse.calibration_entries . Contiene varias clases de envoltura para diferentes representaciones de la programación de impulsos.

    • ScheduleDef
    • CallableDef
    • PulseQobjDef

    Estas clases implementan los métodos get_schedule() y get_signature() que devuelven el programa de pulsos y los nombres de los parámetros a asignar, respectivamente. Estas clases son gestionadas internamente por el InstructionScheduleMap o backend Targety, por tanto, no aparecerán en un programa de usuario típico.

  • Introducida una nueva subclase ScalableSymbolicPulse, como subclase de SymbolicPulse. La nueva subclase se comporta igual que SymbolicPulseexcepto que asume que la envolvente del pulso incluye un pre-factor de amplitud compleja de la forma ampei×angle\text{amp} * e^{i \times \text{angle}}. Esta forma de envolvente coincide con muchos pulsos comunes, incluyendo todos los pulsos de la librería Qiskit Pulse (que también fueron convertidos a la representación amp, angle en esta versión).

    La nueva subclase elimina la naturaleza no única de la representación amp, angle , y compara correctamente los pulsos según su amplitud compleja.

  • Se ha añadido un nuevo argumento de palabra clave, dtype, al método PauliSumOp.from_list() método. Cuando se especifica este argumento se puede utilizar para especificar el dtype de la matriz numpy asignada para el SparsePauliOp utilizado internamente por el PauliSumOp.

  • Se ha añadido soporte para importar programas de OpenQASM 3 a Qiskit. Se puede acceder más fácilmente utilizando las funciones qasm3.loads() y qasm3.load()para cargar un programa directamente a partir de una cadena e indirectamente a partir de un nombre de archivo, respectivamente. Por ejemplo, ahora se puede hacer:

    from qiskit import qasm3
    
    circuit = qasm3.loads("""
      OPENQASM 3.0;
      include "stdgates.inc";
    
      qubit q;
      qubit[5] qr;
      bit c;
      bit[5] cr;
    
      h q;
      c = measure q;
    
      if (c) {
        h qr[0];
        cx qr[0], qr[1];
        cx qr[0], qr[2];
        cx qr[0], qr[3];
        cx qr[0], qr[4];
      } else {
        h qr[4];
        cx qr[4], qr[3];
        cx qr[4], qr[2];
        cx qr[4], qr[1];
        cx qr[4], qr[0];
      }
      cr = measure qr;
    """)

    Esto cargará el programa en una QuantumCircuit instancia en la variable circuit.

    No todas las características de OpenQASM 3 son compatibles al principio, porque Qiskit todavía no tiene una forma de representar el procesamiento clásico avanzado de datos. Las capacidades del importador aumentarán junto con las del resto de Qiskit. El conjunto inicial de características del importador es aproximadamente el mismo que el del exportador (qasm3.dump() y qasm3.dumps()).

    Ten en cuenta que la compatibilidad de Qiskit con OpenQASM 3 no pretende proporcionar una representación totalmente sin pérdidas de QuantumCircuits. Para ello, considere la posibilidad de utilizar qiskit.qpy.

  • Las clases de gradiente basadas en primitives-basadas en las clases de gradiente definidas por el BaseEstimatorGradient y BaseSamplerGradient se han actualizado para simplificar la ampliación de la interfaz base. Hay tres nuevos métodos internos anulables, _preprocess(), _postprocess(), y _run_unique(). _preprocess() permite a una subclase personalizar los circuitos y parámetros del gradiente de entrada, _postprocess permite personalizar el resultado de salida, y _run_unique permite calcular el gradiente de un circuito con parámetros únicos.

  • El transpilador SabreLayout transpiler pass ha mejorado mucho su rendimiento, ya que ha sido reescrito en Rust. Como parte de esta reescritura, el pase ha pasado de ser un pase de análisis a un pase de transformación que ejecutará tanto el diseño como el enrutamiento. Esto se hizo no sólo para mejorar el rendimiento en tiempo de ejecución, sino también para mejorar la calidad de los resultados. La funcionalidad anterior del pase como pase de análisis puede conservarse configurando manualmente el argumento routing_pass o utilizando el nuevo argumento skip_routing .

  • El SabreLayout transpiler pass tiene un nuevo argumento constructor layout_trials. Este argumento se utiliza para controlar con cuántas semillas del generador de números aleatorios se intentará ejecutar SabreLayout con. Cuando se configura, el algoritmo de diseño SABRE se ejecuta layout_trials número de veces y se selecciona el resultado de mejor calidad (medido en el menor número de puertas de intercambio añadidas). Estos ensayos de semillas se ejecutan en paralelo utilizando multihilo para minimizar la posible sobrecarga de rendimiento de ejecutar el diseño varias veces. Por defecto, si no se especifica, el SabreLayout pass utilizará por defecto el número de CPUs físicas disponibles en el sistema local.

  • Añadidas dos nuevas clases SciPyRealEvolver y SciPyImaginaryEvolver que implementan métodos de integración para la evolución temporal de un estado cuántico. El valor y la desviación típica de los observables, así como los momentos en que se evalúan, pueden consultarse como TimeEvolutionResult.observables y TimeEvolutionResult.times. Por ejemplo:

    from qiskit.algorithms.time_evolvers.time_evolution_problem import TimeEvolutionProblem
    from qiskit.quantum_info import SparsePauliOp
    from qiskit.quantum_info.states.statevector import Statevector
    from qiskit.algorithms import SciPyImaginaryEvolver
    
    initial_state = Statevector.from_label("+++++")
    hamiltonian = SparsePauliOp("ZZZZZ")
    evolution_problem = TimeEvolutionProblem(hamiltonian, 100, initial_state, {"Energy":hamiltonian})
    classic_evolver = SciPyImaginaryEvolver(num_timesteps=300)
    result = classic_evolver.evolve(evolution_problem)
    print(result.observables)
  • Añadido el SolovayKitaev para ejecutar el algoritmo Solovay-Kitaev para aproximar unitarios de un solo qubit utilizando un conjunto de puertas discretas. En combinación con el traductor de bases, esto permite convertir cualquier circuito unitario en un conjunto universal de puertas discretas, que podría implementarse con tolerancia a fallos.

    Este pase puede utilizarse, por ejemplo, después de compilar en las puertas U y CX:

    from qiskit import transpile
    from qiskit.circuit.library import QFT
    from qiskit.transpiler.passes.synthesis import SolovayKitaev
    
    qft = QFT(3)
    
    # optimize to general 1-qubit unitaries and CX
    transpiled = transpile(qft, basis_gates=["u", "cx"], optimization_level=1)
    
    skd = SolovayKitaev()  # uses T Tdg and H as default basis
    discretized = skd(transpiled)
    
    print(discretized.count_ops())

    La descomposición también se puede utilizar con el plugin de síntesis unitaria, como el método "sk" en el UnitarySynthesis transpiler pass:

    from qiskit import QuantumCircuit
    from qiskit.quantum_info import Operator
    from qiskit.transpiler.passes import UnitarySynthesis
    
    circuit = QuantumCircuit(1)
    circuit.rx(0.8, 0)
    unitary = Operator(circuit).data
    
    unitary_circ = QuantumCircuit(1)
    unitary_circ.unitary(unitary, [0])
    
    synth = UnitarySynthesis(basis_gates=["h", "s"], method="sk")
    out = synth(unitary_circ)
    
    out.draw('mpl')
    _images/legacy_release_notes-4.png
  • La generación de circuitos aleatorios con qiskit.circuit.random.random_circuit() es ahora significativamente más rápida para circuitos grandes.

  • La generación de circuitos aleatorios con qiskit.circuit.random.random_circuit() generará ahora todas las puertas "estándar" de la librería de circuitos de Qiskit (qiskit.circuit.library). Esto incluye dos puertas 4-qubit C3SXGate y RC3XGatey los valores permitidos de max_operands se han ampliado en consecuencia.

  • El Optimize1qGatesDecomposition transpiler pass tiene un nuevo argumento de palabra clave, target, en su constructor. Este argumento puede utilizarse para especificar un Target que representa el objetivo de compilación. Si se utiliza, sustituye al argumento basis para determinar si una instrucción del circuito está presente en el backend de destino.

  • El UnrollCustomDefinitions transpiler pass tiene un nuevo argumento de palabra clave, target, en su constructor. Este argumento puede utilizarse para especificar un Target que representa el objetivo de compilación. Si se utiliza, sustituye al argumento basis_gates para determinar si una instrucción del circuito está presente en el backend de destino.

  • Se ha añadido la clase ReverseEstimatorGradient para una evaluación clásica y rápida de gradientes de valor de expectativa basados en la retropropagación o en gradientes de modo inverso. Esta clase utiliza vectores de estado y, por tanto, proporciona gradientes exactos, pero se escala exponencialmente en el tamaño del sistema. Está diseñado para el cálculo rápido de referencias de sistemas de menor tamaño. Puede utilizarse, por ejemplo, como:

    from qiskit.circuit.library import EfficientSU2
    from qiskit.quantum_info import SparsePauliOp
    from qiskit.algorithms.gradients import ReverseEstimatorGradient
    
    observable = SparsePauliOp.from_sparse_list([("ZZ", [0, 1], 1)], num_qubits=10)
    circuit = EfficientSU2(num_qubits=10)
    values = [i / 100 for i in range(circuit.num_parameters)]
    gradient = ReverseEstimatorGradient()
    
    result = gradient.run([circuit], [observable], [values]).result()
  • Añadido un nuevo argumento de palabra clave, use_dag al constructor de la clase OneQubitEulerDecomposer clase. Si use_dag está configurado como True , la salida del descomponedor será un objeto DAGCircuit en lugar de un objeto QuantumCircuit objeto. Esto es útil para los pases de transpilador que utilizan OneQubitEulerDecomposer (como Optimize1qGatesDecomposition), ya que al trabajar directamente con DAGCircuit evita la sobrecarga de convertir entre QuantumCircuit y DAGCircuit.

  • Se ha añadido la posibilidad de que los pases de análisis establezcan pesos heurísticos personalizados para el VF2Layout y VF2PostLayout transpiladores. Si un pase de análisis establece la clave vf2_avg_error_map en el conjunto de propiedades, su valor se utiliza para las ponderaciones de error en lugar de las tasas de error del backend de Target (o BackendProperties para BackendV1). El valor debe ser una instancia de ErrorMap , donde cada valor representa la tasa de error media para todas las operaciones de 1 o 2 qubits en esos qubits. Si un valor es NaN, la arista correspondiente se trata como una arista ideal (o qubit para las operaciones 1q ). Por ejemplo, un mapa de error creado como:

    from qiskit.transpiler.passes.layout.vf2_utils import ErrorMap
    
    error_map = ErrorMap(3)
    error_map.add_error((0, 0), 0.0024)
    error_map.add_error((0, 1), 0.01)
    error_map.add_error((1, 1), 0.0032)

    describe un objetivo de 2 qubits, donde la tasa media de error 1q es 0.0024 en el qubit 0 y 0.0032 en el qubit 1, la tasa media de error 2q para las puertas que operan en (0, 1) es 0.01, y (1, 0) no está soportado por el objetivo. Se utilizará para la puntuación si se establece para la clave vf2_avg_error_map en el conjunto de propiedades cuando VF2Layout y VF2PostLayout se ejecutan. Por ejemplo:

    from qiskit.transpiler import AnalysisPass, PassManager, Target
    from qiskit.transpiler.passes import VF2Layout
    from qiskit.transpiler.passes.layout.vf2_utils import ErrorMap
    from qiskit.circuit.library import CZGate, UGate
    from qiskit.circuit import Parameter
    
    class CustomVF2Scoring(AnalysisPass):
      """Set custom score for vf2."""
    
      def run(self, dag):
        error_map = ErrorMap(3)
        error_map.add_error((0, 0), 0.0024)
        error_map.add_error((0, 1), 0.01)
        error_map.add_error((1, 1), 0.0032)
        self.property_set["vf2_avg_error_map"] = error_map
    
    
    target = Target(num_qubits=2)
    target.add_instruction(
        UGate(Parameter('theta'), Parameter('phi'), Parameter('lam')),
        {(0,): None, (1,): None}
    )
    target.add_instruction(
        CZGate(), {(0, 1): None}
    )
    
    vf2_pass = VF2Layout(target=target, seed=1234568942)
    pm = PassManager([CustomVF2Scoring(), vf2_pass])

    Eso funcionará VF2Layout con la puntuación personalizada de error_map para un 2 qubit Target que no contiene ninguna tasa de error.

Notas de actualización

  • Al inicializar cualquiera de las clases de pulso en qiskit.pulse.library:

    proporcionar un argumento complejo amp con un angle finito dará como resultado PulseError ahora. Por ejemplo, en lugar de llamar a Gaussian(duration=100,sigma=20,amp=0.5j) ahora se debería utilizar Gaussian(duration=100,sigma=20,amp=0.5,angle=np.pi/2) . La envolvente de impulsos que antes se definía como amp * ... se define a su vez como amp * exp(1j * angle) * .... Este cambio se hizo para soportar mejor los experimentos Qiskit en los que la amplitud y el ángulo de los pulsos se calibran en experimentos separados.

  • Para Python 3.7 singledispatchmethod es ahora una dependencia. Se ha añadido para poder aprovechar el mecanismo de envío de métodos de la biblioteca estándar de las nuevas versiones de Python. Si está en Python >= 3.8 no se requiere ninguna dependencia adicional.

  • El anteriormente obsoleto MSBasisDecomposer transpiler pass disponible a través del módulo qiskit.transpiler.passes ha sido eliminado. Originalmente fue obsoleto como parte de la versión de Qiskit Terra 0.16.0 (10-16-2020). En cambio, el BasisTranslator para traducir un circuito a una base adecuada con un valor de RXXGate

  • EquivalenceLibrary que se inicialicen con el atributo base dejarán de tener una referencia compartida con el objeto EquivalenceLibrary pasado. En versiones anteriores, si se mutaba base después de haber sido utilizado para crear una nueva instancia, ambas instancias reflejarían el cambio EquivalenceLibrary ambas instancias reflejarían ese cambio. Esto ya no es así y las actualizaciones de base ya no se reflejarán en el nuevo EquivalenceLibrary. Por ejemplo, si ha creado una biblioteca de equivalencias con:

    import math
    
    from qiskit.circuit import QuantumCircuit
    from qiskit.circuit.library import XGate
    from qiskit.circuit.equivalence import EquivalenceLibrary
    
    original_lib = EquivalenceLibrary()
    qc = QuantumCircuit(1)
    qc.rx(math.pi, 0)
    original_lib.add_equivalence(XGate(), qc)
    new_lib = EquivalenceLibrary(base=original_lib)

    si modificó original_lib con:

    import from qiskit.circuit.library import SXGate
    
    qc = QuantumCircuit(1)
    qc.rx(math.pi / 2, 0)
    original_lib.add_equivalence(SXGate(), qc)

    en versiones anteriores, new_lib también incluía la definición de SXGate después de añadirla a original_lib, pero en esta versión ya no será así. Este cambio se hizo debido al cambio en la estructura interna de datos para ser un gráfico, lo que mejoró el rendimiento de la EquivalenceLibrary clase, especialmente cuando hay múltiples ejecuciones del BasisTranslator pase del transpilador.

  • El argumento initial_state para el constructor de la clase NLocal clase junto con la asignación directa al atrributo NLocal.initial_state debe ser un QuantumCircuit ahora. Ya no es posible utilizar otros tipos para este argumento y atributo. La compatibilidad con otros tipos quedó obsoleta como parte de la versión de Qiskit Terra 0.18.0 (julio de 2021).

  • Los cajones de matrices LaTeX (por ejemplo, array_to_latex, Statevector.draw('latex')) utilizan ahora la misma función sympy que el cajón ket-convention. Esto significa que puede que algunos números se muestren de forma diferente a las versiones anteriores, pero proporcionará una experiencia más coherente. Por ejemplo, puede identificar nuevos factores o racionalizar denominadores donde antes no lo hacía. El valor por defecto precision se ha cambiado de 5 a 10.

  • La versión del formato QPY emitida por dump() se ha aumentado a la versión 6. Esta nueva versión del formato es incompatible con las versiones anteriores y producirá un error al intentar cargarlo con un deserializador que no sea capaz de manejar la versión 6 de QPY. Este cambio era necesario para soportar la introducción de ScalableSymbolicPulse , que se gestionaba añadiendo un atributo class_name_size a la cabecera de los objetos volcados SymbolicPulse volcados.

  • El método __hash__ para la SymbolicPulse fue eliminado. Esto se hizo para reflejar la naturaleza mutable (a través de la asignación de parámetros) de esta clase que podría dar lugar a errores cuando se utiliza SymbolicPulse en situaciones en las que se requería un objeto hashable. Esto significa que el método incorporado hash() y el uso de SymbolicPulse como claves en diccionarios o miembros de conjuntos ya no funcionarán.

  • Los nombres de Register (que incluyen instancias de QuantumRegister y ClassicalRegigster) ya no están limitados a ser identificadores válidos de OpenQASM 2. Esto se hace porque la restricción es demasiado estricta a medida que Qiskit se desvincula más de OpenQASM 2, e incluso la especificación OpenQASM 3 no es tan restrictiva. Si confiaba en que los registros tuvieran nombres de identificador válidos en OpenQASM 2, tendrá que empezar a escapar los nombres. Una versión simplista de esto podría hacerse, por ejemplo:

    import re
    import string
    
    def escape(name: str) -> str:
      out = re.sub(r"\W", "_", name, flags=re.ASCII)
      if not out or out[0] not in string.ascii_lowercase:
        return "reg_" + out
      return out
  • Los métodos QuantumCircuitu1 , u2, u3, y sus variantes controladas cu1, cu3 y mcu1 se han eliminado tras su desaprobación en Qiskit Terra 0.16.0. Con ello se pretendía eliminar los nombres de las puertas, que solían ser específicos de IBM, en favor de los métodos más generales p(), u(), cp() y cu(). Las clases de puerta U1Gate, U2Gate y U3Gate siguen estando disponibles para su uso con QuantumCircuit.append()por lo que los backends pueden seguir soportando bases con estas puertas explícitamente dadas.

  • Los métodos QuantumCircuitcombine y extend se han eliminado tras su desaparición en Qiskit Terra 0.17.0. Esto se hizo porque estas funciones eran simplemente versiones menos potentes de QuantumCircuit.compose()que deberían utilizarse en su lugar.

    La supresión de extend significa también que los operadores + y += ya no están definidos para los operadores QuantumCircuit. En su lugar, puede utilizar los operadores & y &= respectivamente, que utilizan QuantumCircuit.compose().

  • Se han eliminado las funciones anteriormente obsoletas: qiskit.circuit.measure.measure() y qiskit.circuit.reset.reset() . Estas funciones quedaron obsoletas en la versión de Qiskit Terra 0.19.0 (diciembre de 2021). En su lugar, debe utilizar las etiquetas QuantumCircuit.measure() y QuantumCircuit.reset() del objeto QuantumCircuit al que desea añadir un Measure o Reset al objeto.

  • Los métodos ParameterView anteriormente obsoletos que se heredaban de set se han eliminado de ParameterView, el tipo devuelto por QuantumCircuit.parameters. Los métodos específicos que se han eliminado son:

    • add()
    • difference()
    • difference_update()
    • discard()
    • intersection()
    • intersection_update()
    • issubset()
    • issuperset()
    • symmetric_difference()
    • symmetric_difference_update()
    • union()
    • update()

    junto con el apoyo a los operadores de Python :

    • ixor: ^=
    • isub: -=
    • ior: |=

    Estos fueron obsoletos en la versión de Qiskit Terra 0.17.0 (Abril, 2021). El tipo ParameterView es ahora un tipo de vista de secuencia general y ya no admite estas operaciones set .

  • Los métodos de conversión NetworkX para los métodos DAGCircuit y DAGDependency : DAGCircuit.to_networkx(), DAGCircuit.from_networkx(), y DAGDependency.to_networkx() han sido eliminados. Estos métodos fueron originalmente obsoletos como parte de la versión de Qiskit Terra 0.21.0 (Junio, 2022). Qiskit ha estado utilizando rustworkx como su biblioteca de gráficos desde la versión qiskit-terra 0.12.0 y desde entonces la función de convertidor NetworkX han sido un proceso con pérdidas. Se añadieron originalmente para que los usuarios pudieran aprovechar la biblioteca de algoritmos NetworkX’s para aprovechar funcionalidades no presentes en DAGCircuit y/o rustworkx. Sin embargo, desde entonces tanto DAGCircuit y rustworkx han madurado y ofrecen más funcionalidad y el DAGCircuit está estrechamente acoplado a rustworkx para su funcionamiento y tener estos métodos convertidores proporcionaba una funcionalidad limitada y por lo tanto han sido eliminados.

  • tweedledum se ha eliminado como requisito básico de Qiskit Terra. La funcionalidad proporcionada (qiskit.circuit.classicalfunction) sigue estando disponible, si tweedledum se instala manualmente, como por:

    pip install tweedledum

    Este cambio se hizo porque el desarrollo de tweedledum se ha ralentizado hasta el punto de no seguir el ritmo de las nuevas versiones de Python y OS, y estaba bloqueando a algunos usuarios de Qiskit la instalación de Qiskit.

  • Los verificadores opcionales perezosos HAS_MATPLOTLIB, HAS_PIL, HAS_PYLATEX y HAS_PDFTOCAIRO ya no se exponen desde qiskit.visualizational haber sido obsoletos en Qiskit Terra 0.21. La ubicación canónica de estos (y muchos otros comprobadores perezosos) es qiskit.utils.optionalsy los cuatro objetos pueden encontrarse allí.

  • Se ha eliminado el argumento gate , anteriormente obsoleto, del constructor del Decompose junto con su atributo correspondiente Decompose.gate . El argumento y el atributo quedaron obsoletos como parte de la versión de Qiskit Terra 0.19.0 (diciembre de 2021). En su lugar, debe utilizarse el argumento gates_to_decompose para el constructor junto con el atributo Decompose.gates_to_decompose . El argumento y atributo gates_to_decompose debería funcionar igual, pero tiene un nombre más explícito y también permite especificar listas de puertas en lugar de admitir una sola puerta.

  • El argumento anteriormente obsoleto label para el constructor de la función MCMT y MCMTVChain ha sido eliminado. Fue obsoleto a partir de la versión de Qiskit Terra 0.19.0 (diciembre de 2021). El uso del argumento label en estas clases tenía un comportamiento indefinido ya que son subclases de QuantumCircuit en lugar de Instruction. El resultado sería que la etiqueta asignada generalmente se ignoraría. Si necesita asignar un label a una instancia de MCMT o MCMTVChain debe convertirlos en una Gate con to_gate() y luego asignar la etiqueta deseada al atributo label atributo. Por ejemplo:

    from qiskit.circuit.library import MCMT, XGate
    
    mcmt_circuit = MCMT(XGate(), 3, 2)
    mcmt_gate = mcmt_circuit.to_gate()
    mcmt_gate.label = "Custom MCMT X"
  • La dependencia retworkx para Qiskit ha sido eliminada y sustituida por la biblioteca rustworkx . Se trata de los mismos paquetes, pero rustworkx es el nuevo nombre de retworkx , que fue rebautizado como parte de su versión combinada 0.12.0. Si antes utilizabas retworkx 0.12.0 con Qiskit, entonces ya has instalado rustworkx (retworkx 0.12.0 era sólo un calce de redirección para compatibilidad con versiones anteriores). Este cambio se ha realizado para migrar al nuevo nombre del paquete, que será el único admitido en el futuro.

  • El comportamiento por defecto del SabreLayout pass del compilador ha cambiado. El pase ya no es un AnalysisPass y por defecto calculará el layout inicial, lo aplicará al circuito, y también ejecutará SabreSwap internamente y aplicará el mapeado swap y establecerá la propiedad final_layout con la permutación causada por las inserciones swap. Esto significa para los usuarios que ejecutan SabreLayout como parte de un sistema personalizado PassManager tendrán que ajustar el gestor de pases para tener esto en cuenta (a menos que estuvieran configurando el argumento routing_pass para SabreLayout). Este cambio se ha realizado con el fin de mejorar la calidad de los resultados SabreLayout para calcular qué semilla proporciona los mejores resultados es necesario realizar el trazado y el enrutamiento conjuntamente. Hay tres formas de ajustar el uso en el gestor de pases personalizados. La primera es evitar el uso de la incrustación en el gestor de pases predefinidos. Si anteriormente estaba ejecutando algo como:

    from qiskit.transpiler import PassManager
    from qiskit.transpiler.preset_passmanagers import common
    from qiskit.transpiler.passes.SabreLayout
    
    pm = PassManager()
    pm.append(SabreLayout(coupling_map)
    pm += common.generate_embed_passmanager(coupling_map)

    para calcular el trazado y luego aplicarlo (que normalmente iba seguido del enrutamiento) se puede ajustar el uso para que simplemente sea:

    from qiskit.transpiler import PassManager
    from qiskit.transpiler.preset_passmanagers import common
    from qiskit.transpiler.passes.SabreLayout
    
    pm = PassManager()
    pm.append(SabreLayout(coupling_map)

    como SabreLayout aplicará el diseño y ya no necesitará la etapa de incrustación. Alternativamente, puede especificar el argumento routing_pass que revertirá SabreLayout a su comportamiento anterior. Por ejemplo, si desea ejecutar SabreLayout tal y como se ejecutaba en versiones anteriores puedes hacer algo como

    from qiskit.transpiler.passes import SabreSwap, SabreLayout
    routing_pass = SabreSwap(
        coupling_map, "decay", seed=seed, fake_run=True
    )
    layout_pass = SabreLayout(coupling_map, routing_pass=routing_pass, seed=seed)

    que tendrá SabreLayout ejecutado como un pase de análisis y sólo establecerá el conjunto de propiedades layout . El enfoque final es aprovechar el argumento skip_routing en SabreLayout, cuando este argumento se establece en True omitirá la aplicación del diseño encontrado y la inserción de las puertas de intercambio de enrutamiento. Sin embargo, hacer esto tiene una penalización en tiempo de ejecución ya que SabreLayout seguirá calculando el enrutamiento y simplemente no utiliza estos datos. Los dos primeros enfoques descritos no llevan asociados gastos generales adicionales.

  • Los diseños calculados por el pase SabreLayout pass (cuando se ejecuta sin el argumento routing_pass ) con un valor de semilla fijo pueden cambiar con respecto a versiones anteriores. Esto es causado por un nuevo generador de números aleatorios que se utiliza como parte de la reescritura de la SabreLayout en Rust, lo que ha mejorado significativamente el rendimiento. Si confías en tener una salida consistente puedes ejecutar el pase en una versión anterior de Qiskit y aprovechar qiskit.qpy para guardar el circuito y luego cargarlo utilizando la versión actual. También puede establecer explícitamente el argumento routing_pass en una instancia de SabreSwap para reflejar el comportamiento anterior de SabreLayout:

    from qiskit.transpiler.passes import SabreSwap, SabreLayout
    
    
    routing_pass = SabreSwap(
        coupling_map, "decay", seed=seed, fake_run=True
    )
    layout_pass = SabreLayout(coupling_map, routing_pass=routing_pass, seed=seed)

    que reflejará el comportamiento del pase en la versión anterior. Tenga en cuenta que si en versiones anteriores utilizaba el argumento swap_trials en SabreLayout en versiones anteriores al ajustar el uso a esta forma, deberá establecer el argumento trials en el constructor SabreSwap si desea conservar la salida anterior con una semilla fija.

  • El circuito exacto devuelto por qiskit.circuit.random.random_circuit para una semilla dada ha cambiado. Esto se debe a mejoras de eficiencia en la generación interna de números aleatorios para la función.

  • El requisito de versión para el paquete de funciones opcionales qiskit-toqm, instalable a través de pip install qiskit-terra[toqm], se ha actualizado de la versión 0.0.4 a 0.1.0. Para utilizar el método de enrutamiento toqm con transpile() ahora debe utilizar qiskit-toqm versión 0.1.0 o más reciente. Las versiones anteriores ya no son detectables por el transpilador.

  • La salida QuasiDistribution del método Sampler.run se ha actualizado para filtrar los estados con probabilidad cero. Ahora, si falta un estado válido en la salida del diccionario, se puede suponer que tiene una probabilidad 0. Anteriormente, todos los resultados posibles para un número determinado de bits (por ejemplo, para un resultado de 3 bits 000, 001, 010, 011, 100, 101, 110, y 111) aunque la probabilidad de un estado determinado fuera 0. Este cambio se realizó para reducir el tamaño de la salida, ya que para un mayor número de bits el tamaño de la salida podía ser bastante grande. Además, el filtrado de los resultados de probabilidad cero hace que la salida sea coherente con otras implementaciones de BaseSampler.

  • Se ha actualizado el comportamiento del generador de impulsos cuando se llama a Schedule ha sido actualizado. Los horarios llamados se convierten internamente en ScheduleBlock y ahora se aplica siempre el mecanismo de referencia en lugar de añadir los horarios envueltos por la instrucción Call instrucción. Tenga en cuenta que el bloque convertido no tiene por qué recuperar el contexto de alineación original. Se trata simplemente de una secuencia alineada ASAP de instrucciones de pulso con intervalos de tiempo absolutos. Se trata de una actualización de la representación interna de los programas de pulsos llamados y, por tanto, no hay cambios en la API. No obstante, la Call instrucción y Schedule ya no aparecen en el programa de pulso del constructor. Este cambio garantiza que los bloques de programación generados sean siempre compatibles con QPY. Si filtra las instrucciones de programación de salida por Callpuede acceder a ScheduleBlock.references en su lugar para recuperar el programa llamado.

  • RZXCalibrationBuilder y RZXCalibrationBuilderNoEcho transpiler pass se han actualizado para generar ScheduleBlock. Este cambio garantiza que los circuitos transpilados sean siempre compatibles con QPY. Si está utilizando directamente rescale_cr_inst()de otro programa o de una subclase del pase para reescalar el pulso de resonancia cruzada del dispositivo, ahora este método se ha convertido en una macro del constructor de pulsos, y necesita utilizar este método dentro del contexto del constructor de pulsos para adoptar la nueva versión. La llamada al método inyecta una instrucción de reproducción al programa de pulso contextual, en lugar de devolver una Play instrucción con el pulso estirado.

Notas sobre características en desuso

  • El soporte para ejecutar Qiskit con Python 3.7 ha sido obsoleto y será eliminado en la versión qiskit-terra 0.25.0. Esto significa que a partir de la versión 0.25.0 deberá actualizar la versión Python que esté utilizando a Python 3.8 o superior.

  • La clase LinearFunctionsSynthesis está obsoleta y se eliminará en una futura versión. Ha sido sustituida por la clase más general HighLevelSynthesis que debe utilizarse en su lugar. Por ejemplo, puede instanciar una instancia de HighLevelSynthesis que se comportará de la misma manera que LinearFunctionSynthesis con:

    from qiskit.transpiler.passes import HighLevelSynthesis
    from qiskit.transpiler.passes.synthesis.high_level_synthesis import HLSConfig
    
    HighLevelSynthesis(
        HLSConfig(
            linear_function=[("default", {})],
            use_default_on_unspecified=False,
        )
    )
  • El soporte para pasar listas de valores de argumentos a la función transpile() está obsoleta y se eliminará en la versión 0.25.0. Esto se hace para facilitar en gran medida la reducción de la sobrecarga de ejecución paralela para transpilar varios circuitos a la vez. Si está utilizando esta funcionalidad actualmente, puede llamar a transpile() varias veces. Por ejemplo, si antes hacías algo como:

    from qiskit.transpiler import CouplingMap
    from qiskit import QuantumCircuit
    from qiskit import transpile
    
    qc = QuantumCircuit(2)
    qc.h(0)
    qc.cx(0, 1)
    qc.measure_all()
    cmaps = [CouplingMap.from_heavy_hex(d) for d in range(3, 15, 2)]
    results = transpile([qc] * 6, coupling_map=cmaps)

    en su lugar debe ejecutar algo como:

    from itertools import cycle
    from qiskit.transpiler import CouplingMap
    from qiskit import QuantumCircuit
    from qiskit import transpile
    
    qc = QuantumCircuit(2)
    qc.h(0)
    qc.cx(0, 1)
    qc.measure_all()
    cmaps = [CouplingMap.from_heavy_hex(d) for d in range(3, 15, 2)]
    
    results = []
    for qc, cmap in zip(cycle([qc]), cmaps):
        results.append(transpile(qc, coupling_map=cmap))

    También puede aprovechar parallel_map() o multiprocessing de la biblioteca estándar Python si desea ejecutar esto en paralelo.

  • La versión heredada del cajón de pulsos presente en qiskit.visualization.pulse ha quedado obsoleta y se eliminará en una futura versión. Esto incluye las clases ScheduleDrawer y :class`WaveformDrawer`. Este módulo ha sido sustituido por el cajón qiskit.visualization.pulse_v2 y la API de usuario típica pulse_drawer() y PulseBlock.draw() ya están actualizadas internamente para utilizar qiskit.visualization.pulse_v2.

  • El método pulse.Instruction.draw() ha quedado obsoleto y se eliminará en una futura versión. La necesidad de este método ha sido sustituida por el cajón qiskit.visualization.pulse_v2 que no requiere que los objetos Instrucion tengan su propio método de dibujo. Si necesitas dibujar una instrucción de pulso debes aprovechar el botón pulse_drawer() en su lugar.

  • La importación qiskit.circuit.qpy_serialization está obsoleta, ya que QPY ha sido promocionado al nivel superior. Debería importar los mismos objetos de qiskit.qpy en su lugar. El antiguo camino se eliminará en un futuro de Qiskit Terra.

  • El objeto qiskit.IBMQ está obsoleto. Este objeto alias redirige perezosamente el acceso a los atributos a qiskit.providers.ibmq.IBMQ. Dado que el paquete qiskit-ibmq-provider ha sido sustituido por el paquete qiskit-ibm-provider , que mantiene su propio espacio de nombres, el mantenimiento de este alias ya no es relevante con el nuevo paquete. Si dependía del alias qiskit.IBMQ , debería actualizar su uso para utilizar directamente qiskit.providers.ibmq.IBMQ en su lugar (y también considerar la migración a qiskit-ibm-provider, consulte la guía de migración para obtener más detalles).

  • Varios métodos públicos de los conversores pulse Qobj han quedado obsoletos y en una futura versión ya no se podrán llamar directamente. La lista de métodos es:

    En InstructionToQobjConverter,

    • convert_acquire()
    • convert_bundled_acquires()
    • convert_set_frequency()
    • convert_shift_frequency()
    • convert_set_phase()
    • convert_shift_phase()
    • convert_delay()
    • convert_play()
    • convert_snapshot()

    En QobjToInstructionConverter,

    • convert_acquire()
    • convert_set_phase()
    • convert_shift_phase()
    • convert_set_frequency()
    • convert_shift_frequency()
    • convert_delay()
    • bind_pulse()
    • convert_parametric()
    • convert_snapshot()

    En lugar de llamar directamente a cualquiera de estos métodos, se seleccionarán implícitamente cuando se llame directamente a una instancia del conversor. Por ejemplo:

    converter = QobjToInstructionConverter()
    converter(pulse_qobj)
  • Las funciones qiskit.visualization.state_visualization.num_to_latex_ket() y qiskit.visualization.state_visualization.num_to_latex_terms() han quedado obsoletas y se eliminarán en una futura versión. Esta función era utilizada principalmente a nivel interno por la salida LaTeX de Statevector.draw() y DensityMatrix.draw() que ya no utilizan esta función y en su lugar utilizan sympy. Si estabas usando estas funciones deberías cosinder usar las funciones nsimplify() latex() de Sympy.

  • El método Register.qasm() está obsoleto y se eliminará en una futura versión. Este método se encuentra en las subclases QuantumRegister y ClassicalRegister. La desaprobación se debe a que el método qasm() promueve una falsa visión del responsable de la conversión segura a OpenQASM 2; un único objeto por sí solo no tiene el contexto para proporcionar una conversión segura, como por ejemplo si su nombre choca después de escaparlo para producir un identificador válido.

  • La expresión regular class-variable Register.name_format está obsoleta y se eliminará en una futura versión. Ahora se permite que los nombres de los registros sean cualquier cadena válida de Python, por lo que la expresión regular ya no tiene utilidad.

  • Las funciones qiskit.quantum_info.synthesis.decompose_clifford() y qiskit.quantum_info.synthesis.decompose_cnot_dihedral() están obsoletas y se eliminarán en una futura versión. Se sustituyen por las dos funciones qiskit.synthesis.synth_clifford_full() y qiskit.synthesis.synth_cnotdihedral_full() respectivamente.

Corrección de errores

  • Se ha corregido un problema en el método PauliOp.adjoint() por el que devolvía el valor correcto para Paulis con coeficientes complejos, por ejemplo: PauliOp(Pauli("iX")). Corregido #9433.

  • Se ha corregido un problema con los algoritmos de estimación de amplitud en el módulo qiskit.algorithms.amplitude_estimators (véase amplitude_estimators) para el uso con primitivas construidas a partir de la primitiva abstracta BaseSampler (como Sampler y BackendSampler). Anteriormente, los resultados de las mediciones se ampliaban a más bits de los realmente medidos, lo que en el caso de los oráculos con más de un qubit conducía a posibles errores en la detección de los estados cuánticos "buenos" para los oráculos.

  • Se ha solucionado un problema por el que los métodos QuantumCircuit.add_calibrations() y DAGCircuit.add_calibrations() no coincidían en su comportamiento de la lógica de formato de parámetros. Anteriormente DAGCircuit.add_calibrations() intentaba convertir cada parámetro en float, QuantumCircuit.add_calibrations() utilizaba los parámetros dados tal cual. Esto podría causar un error cuando se ejecuta transpile() en un QuantumCircuit con puertas de impulsos, ya que los parámetros de las calibraciones podrían mantenerse como objetos de ParameterExpresion .

  • Se ha corregido un problema de deserialización en el archivo (qiskit.qpy) load() donde los circuitos que contienen puertas de clase MCXGate, MCXGrayCode, MCXRecursivey MCXVChain no se deserializarían. Corregido #9390.

  • Se ha corregido un problema en TensoredOp.to_matrix() donde el coeficiente global del operador se multiplicaba a la matriz final más de una vez. Ahora, el coeficiente global se aplica correctamente, independientemente del número de operadores o estados tensados. Corregido #9398.

  • La salida del método run() de la clase BackendSampler establece ahora los atributos shots y stddev_upper_bound de la clase devuelta QuasiDistribution. Anteriormente faltaban estos atributos, lo que impedía algunos postprocesamientos con la salida. Corregido #9311

  • El método de exportación OpenQASM 2 QuantumCircuit.qasm() emitirá por defecto números de coma flotante de mayor precisión para los parámetros de la puerta. Además, se utiliza un límite más estricto ( 1e121e-12 en lugar de 1e61e-6 ) para comprobar si un parámetro dado está cerca de una fracción/potencia de π\pi. Corregido #7166.

  • Soporte fijo en el módulo primitives para ejecutar QuantumCircuit con instrucciones de flujo de control (p. ej. IfElseOp). Anteriormente, las clases base BaseSampler y BaseEstimator no podían normalizar correctamente este tipo de circuitos. Sin embargo, la ejecución de estos circuitos depende de la implementación concreta de la primitiva que soporta las instrucciones de flujo de control. Esto sólo fija el soporte para permitir que una implementación particular de BaseSampler o BaseEstimator utilice instrucciones de flujo de control.

  • Se ha corregido un problema con el método PauliOp.matmul() que devolvía resultados incorrectos con iI. Corregido #8680.

  • Se ha corregido un problema con la clase Compilador Cuántico Aproximado (AQC) que provocaba que devolviera un circuito incorrecto cuando el unitario de entrada tenía un determinante de -1. Corregido #9327

  • Se ha corregido un problema con el método QuantumCircuit.compose() que rechazaba incorrectamente especificadores qubit o clbit válidos. Esto se ha corregido para que el método acepte ahora el mismo conjunto de especificadores qubit y clbit que otros métodos QuantumCircuit como append(). Corregido #8691.

  • Se ha corregido un problema con el método QuantumCircuit.compose() que asignaba incorrectamente registros en condiciones en el circuito dado a registros completos en la base. Anteriormente, el mapeo era muy impreciso; los bits utilizados dentro de cada condición no estaban sujetos al mapeo y, en su lugar, se intentaba encontrar un registro correspondiente de forma imprecisa. Esto también podría dar lugar a una condición en un registro más pequeño que se expande para estar en un registro más grande, que no es una transformación válida. Ahora, una condición sobre un solo bit o un registro se compondrá para estar precisamente sobre los bits definidos por el argumento clbits . Se añadirá un nuevo registro de aliasing al circuito base para facilitarlo, si es necesario. Corregido #6583.

  • Se ha corregido un problema con la función transpile() cuando se ejecutaba con optimization_level establecido en 1, 2, o 3 y no se especificaba ningún argumento backend, basis_gates, o target . Si el circuito de entrada tuviera pasadas de compuertas de un solo qubit que pudieran simplificarse, el circuito de salida no estaría lo más optimizado posible, ya que esas pasadas de compuertas de un solo qubit no se habrían eliminado. Esto podría haberse corregido anteriormente especificando los argumentos backend, basis_gates, o target en la llamada transpile() pero ahora la salida será lo más simplificada posible sin conocer las puertas de destino permitidas. Corregido #9217

  • Se ha corregido un problema con la función transpile() cuando se ejecutaba con optimization_level=3 y no se especificaba ningún argumento backend, basis_gates o target . Si el circuito de entrada contuviera algún bloque de 2 qubits equivalente a una matriz identidad, el circuito de salida no estaría lo más optimizado posible y seguiría conteniendo ese bloque identidad. Esto podría haberse corregido anteriormente especificando los argumentos backend, basis_gates, o target en la llamada transpile() pero ahora la salida será lo más simplificada posible sin conocer las puertas de destino permitidas. Corregido #9217

  • Se ha corregido un problema con LinCombSamplerGradient que podía generar un error cuando se ejecutaba con la clase Sampler de qiskit-aer.

  • Se ha corregido un problema con NumPyEigensolver y por extensión NumPyMinimumEigensolver por el que la resolución de subclases de BaseOperator distintas de Operator provocaba un error.

  • Se ha corregido un problema en la salida de metadatos de primitives donde la lista hacía copias por referencia y todos los elementos se actualizaban con el mismo valor en cada iteración.

  • Se ha solucionado un problema con QobjToInstructionConverter cuando se llama a varios backends y accidentalmente tienen el mismo nombre de pulso en la biblioteca de pulsos. Se trataba de un caso extremo que sólo podía producirse cuando se reutilizaba una instancia de convertidor en varios backends (no era un patrón de uso típico).

  • Se ha corregido un problema con la clase PVQD por el que la función de pérdida elevaba incorrectamente al cuadrado la fidelidad. Esto se ha corregido para que la función de pérdida coincida con la definición del algoritmo original.

  • Se ha corregido un error en QPY (qiskit.qpy) por el que los circuitos que contenían registros cuyos bits ocurrían en el circuito después de bits sueltos fallaban al deserializar. Ver #9094.

  • La clase TwoQubitWeylDecomposition es ahora compatible con el protocolo pickle . Anteriormente, fallaba la deserialización y aparecía el mensaje TypeError. Ver #7312.

  • Se ha corregido un problema con el método LocalReadoutMitigator.quasi_probabilities() por el que no se utilizaba el argumento shots . Ahora se utiliza para establecer el número de disparos en el objeto de retorno.

  • Corregida una regresión en la construcción de Clifford objetos de QuantumCircuits que contienen otros Clifford objetos.

  • Se ha corregido un problema con la clase TwoQubitWeylDecomposition (y sus subclases) para permitir que la biblioteca estándar Python pickle serialice estas clases. Se ha corregido parcialmente #7312

  • QuantumCircuit.qasm() ahora escapará correctamente los nombres de puertas y registros que colisionen con palabras clave reservadas de OpenQASM 2. Correcciones #5043.

  • Se ha corregido un problema en el RZXCalibrationBuilder donde la secuencia de pulsos ECR estaba desalineada. Corregido #9013.

  • Se ha solucionado un problema con el pulse_drawer() por el que, en algunos casos, la visualización de salida omitía algunos de los canales de una programación. Corregido #8981.

Aer 0.11.2

No cambia

IBM Proveedor Q 0.19.2

No cambia

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