Skip to main content
IBM Quantum Platform

Notas de la versión de Qiskit 0.39


0.39.5

Terra 0.22.4

Preludio

Qiskit Terra 0.22.4 es una versión de corrección de errores menores, que corrige algunos errores identificados en la serie 0.22.

Corrección de errores

  • Se ha corregido un error en BackendSampler que provocaba un error si su método run() se llamaba dos veces seguidas.

  • Corregidos dos errores en el ComposedOp donde el método ComposedOp.to_matrix() no proporcionaba los resultados correctos para composiciones con StateFn y para composiciones con un coeficiente global. Corregido #9283.

  • Corregido el problema en el que las primitivas Sampler y Estimatorno funcionaban cuando se les pasaba un circuito con numpy.ndarray como parámetro.

  • Se ha corregido un error en SamplingVQE por el que el argumento aggregation no tenía efecto. Ahora se puede especificar correctamente la función de agregación y, con ella, el valor de expectativa CVaR.

  • Se ha corregido un error de rendimiento por el que SamplingVQE evaluaba las energías de los estados propios de forma lenta.

  • Corregida la autoevaluación de los parámetros beta en VQDse ha añadido soporte para entradas SparsePauliOp y se ha corregido la función de evaluación de la energía para aprovechar la ejecución asíncrona de las primitivas, recuperando los resultados del trabajo sólo después de que se hayan enviado ambos trabajos.

  • Se ha solucionado un problema con los botones Statevector.probabilities_dict() y DensityMatrix.probabilities_dict() que devolvían resultados incorrectos para sistemas no qubit cuando se especificaba el argumento qargs . Corregido #9210

  • Corregido el manejo de algunos classmethods por wrap_method() en Python 3.11. Anteriormente, en Python 3.11, wrap_method envolvía la función no ligada asociada a classmethod y luego fallaba cuando se invocaba porque el objeto de clase normalmente ligado a classmethod no se pasaba a la función. A partir de Python 3.11.1, este problema afectó a QiskitTestCase, impidiendo que fuera importado por otro código de prueba. Corregido #9291.

Aer 0.11.2

No cambia

IBM Proveedor Q 0.19.2

No cambia


0.39.4

Terra 0.22.3

No cambia

Aer 0.11.2

Nuevas funciones

  • Añadido soporte para ejecutar Qiskit Aer con Python 3.11 support.

Problemas conocidos

  • Corrección de dos errores en AerStatevector. AerStatevector utiliza instrucciones mc*, que no están habilitadas en el método matrix_product_state. Este commit cambia AerStatevector para no usar MC* y usar H, X, Y, Z, U y CX. AerStatevector también falla si una instrucción se descompone en QuantumCircuit vacía. Este commit permite dicha instrucción.

Corrección de errores

  • Se ha corregido el soporte del método AerSimulator.from_backend() para instanciar una instancia de AerSimulator a partir de un objeto a BackendV2 objeto. Anteriormente, al intentar utilizar AerSimulator.from_backend() con un objeto BackendV2 aparecía el mensaje AerError diciendo que no era compatible.

  • Corrige un error por el que NoiseModel.from_backend() con un objeto BackendV2 puede generar un modelo de ruido con un exceso de QuantumError s en instrucciones no Gate mientras que, por ejemplo, sólo ReadoutError s debería ser suficiente para las medidas. Esta confirmación actualiza NoiseModel.from_backend() con un objeto BackendV2 para que devuelva el mismo modelo de ruido que el llamado con el objeto BackendV1 correspondiente. Es decir, el modelo de ruido resultante no contiene ningún QuantumError s en las medidas y puede contener sólo errores de relajación térmica en otras instrucciones no gate como los resets. Observe que aún contiene ReadoutError s en las medidas.

  • Se ha corregido un error en NoiseModel.from_backend() por el que el uso de temperature kwarg con un valor no predeterminado calculaba incorrectamente la población de estados excitados para la temperatura especificada. Anteriormente, había un factor adicional de 2 en el cálculo de la distribución de Boltzman que conducía a un valor menor incorrecto para la población del estado excitado.

  • Se ha corregido una lógica incorrecta en el compilador de flujo de control que podía permitir que instrucciones no relacionadas aparecieran "dentro" de cuerpos de flujo de control durante la ejecución, provocando resultados incorrectos. Por ejemplo, anteriormente:

    from qiskit import QuantumCircuit
    from qiskit_aer import AerSimulator
    
    backend = AerSimulator(method="statevector")
    
    circuit = QuantumCircuit(3, 3)
    circuit.measure(0, 0)
    circuit.measure(1, 1)
    
    with circuit.if_test((0, True)):
        with circuit.if_test((1, False)):
            circuit.x(2)
    
    with circuit.if_test((0, False)):
        with circuit.if_test((1, True)):
            circuit.x(2)
    
    circuit.measure(range(3), range(3))
    print(backend.run(circuit, method=method, shots=100).result())

    imprimiría {'010': 100} ya que las operaciones de flujo de control anidadas saltarían accidentalmente sobre la primera puerta X del qubit 2, que debería haberse ejecutado.

  • Corrige un error por el que NoiseModel.from_backend() imprime advertencias verbose al suministrar un backend que informa de parámetros de dispositivo no físicos como T2 > 2 * T1 debido a errores estadísticos en su estimación. Esta confirmación elimina estas advertencias porque no son procesables por los usuarios, en el sentido de que no hay más medios que truncarlas hasta los límites teóricos, como se hace en el módulo noise.device . Consulte el número 1631 para obtener más información sobre el error corregido.

  • Se trata de una corrección para el simulador de vectores de estado de la GPU. La distribución de trozos intentó asignar toda la memoria libre en la GPU, pero esto provoca un error de asignación de memoria. Así que este arreglo asigna el 80 por ciento de la memoria libre. También fija el tamaño del búfer de la matriz cuando se aplica el muestreo de ruido.

  • Se trata de una corrección de AerState que funciona con bloqueo de caché. AerState configuró mal el transpilador de Aer para el bloqueo de la caché, y entonces su algoritmo para intercambiar qubits funcionó mal. Esta corrección corrige AerState para utilizar este transpilador. Más concretamente, tras la transpilación, un mapa de qubits intercambiados se recupera al mapa original cuando se utiliza AerState. Esta corrección es necesaria para que AerStatevector pueda utilizar varias GPU.

  • Esta es la solución para AerStatevector. No ha sido posible crear una instancia de AerStatevector directamente a partir del vector de estado de terra. Esta corrección permite un vector de estado como entrada en AerStatevector’s.

  • SamplerResult.quasi_dists contienen los datos sobre el número de qubits. QuasiDistribution.binary_probabilities() devuelve cadenas de bits con la longitud correcta.

  • Previamente la semilla no se inicializa en AerStatevector y entonces los resultados muestreados son siempre los mismos. Con este commit, se inicializa una semilla para cada muestreo y se pueden variar los resultados muestreados.

IBM Proveedor Q 0.19.2

No cambia


0.39.3

Terra 0.22.3

Preludio

Qiskit Terra 0.22.3 es una versión de corrección de errores menores, que corrige algunos errores más en la serie 0.22.

Corrección de errores

  • AdaptVQE ahora indica correctamente que admite operadores auxiliares.

  • Los cajones de los circuitos (QuantumCircuit.draw() y circuit_drawer()) ya no emitirán una advertencia sobre el parámetro cregbundle cuando se utilicen los argumentos por defecto, si el contenido del circuito requiere que todos los bits se dibujen individualmente. Esto era más probable que apareciera al intentar dibujar circuitos con operaciones de flujo de control del nuevo estilo.

  • Se ha corregido un error por el que QNSPSA fallaba cuando max_evals_grouped tenía un valor superior a 1.

  • Se ha corregido un problema con el pase SabreSwap que provocaba que la salida de varias ejecuciones del pase sin el argumento seed especificado reutilizara la misma semilla generadora de números aleatorios entre ejecuciones en lugar de utilizar semillas diferentes. Anteriormente, esto provocaba que se obtuvieran resultados idénticos entre ejecuciones incluso cuando no se especificaba seed .

  • Solucionado un problema con las clases primitivas, BackendSampler y BackendEstimatorcuyas instancias no podían serializarse con pickle. En general, no se garantiza que estas clases sean serializables como BackendV2 y BackendV1 no tienen que ser serializables (y a menudo no lo son), pero las definiciones de clase de BackendSampler y BackendEstimator ya no impiden el uso de pickle.

  • El método pulse.Instruction.draw() tendrá ahora éxito, como antes. Este método está obsoleto y no está previsto sustituirlo, pero debería seguir funcionando durante el periodo de obsoleto.

Aer 0.11.1

No cambia

IBM Proveedor Q 0.19.2

No cambia


0.39.2

Terra 0.22.2

Preludio

Qiskit Terra 0.22.2 es una versión de corrección de errores menores, y marca el primer soporte oficial para Python 3.11.

Corrección de errores

  • Se ha solucionado un problema con las clases primitivas del backend BackendSampler y BackendEstimator que impedía la ejecución con una instancia BackendV1 que no tuviera un campo max_experiments definido en su campo BackendConfiguration.

  • Se ha corregido un error en el método VF2PostLayout cuando se transpilaba para backends con una definición de Targetdonde el gráfico de interacción se construía incorrectamente. Esto podría dar lugar a tiempos de ejecución excesivos debido a que el gráfico es mucho más complejo de lo necesario.

  • El analizador sintáctico de expresiones Pulse ya no debería colgarse periódicamente cuando se llama desde cuadernos Jupyter. Esto se consigue evitando un deepycopy interno de un objeto recursivo que parecía ser particularmente difícil de evaluar para la memoización.

Aer 0.11.1

No cambia

IBM Proveedor Q 0.19.2

No cambia


0.39.1

Terra 0.22.1

Preludio

Qiskit Terra 0.22.1 es una versión de corrección de errores, que aborda algunos problemas menores identificados desde la versión 0.22.0.

Notas sobre características en desuso

  • El kwarg pauli_list de pauli_basis() ha quedado obsoleto, ya que pauli_basis() ahora siempre devuelve un PauliList. Este argumento se eliminó prematuramente de Qiskit Terra 0.22.0, lo que rompió la compatibilidad para los usuarios que utilizaban pauli_list``argument. Now, the argument has been restored but will emit a ``DeprecationWarning . Si se utiliza no tiene ningún efecto porque desde Qiskit Terra 0.22.0 a PauliList siempre se devuelve.

Corrección de errores

  • Corregido el BarrierBeforeFinalMeasurements paso del transpilador cuando hay condiciones en sueltas Clbits inmediatamente antes de la capa de medición final. Anteriormente, esto fallaba alegando que el bit no estaba presente en un circuito temporal interno. Corregido #8923

  • Los comprobadores de igualdad para QuantumCircuit y DAGCircuit (con objetos del mismo tipo) tratarán ahora correctamente las condiciones sobre bits individuales. Anteriormente, esto producía falsos negativos para la igualdad, ya que los bits utilizaban comprobaciones de igualdad "exactas" en lugar de las comprobaciones "semánticas" que reciben el resto de propiedades de las instrucciones de circuito.

  • Manipulación fija de bits clásicos en StochasticSwap con el flujo de control. Anteriormente, las operaciones de flujo de control se expandían para contener todos los bits clásicos del circuito exterior y no se volvían a contraer, lo que provocaba un desajuste entre el número de clbits que la instrucción informaba necesitar y el número real que se le suministraba. Corregido #8903

  • Corregido el manejo de instrucciones definidas globalmente para la Target clase. Anteriormente, dos métodos operations_for_qargs() y operation_names_for_qargs() ignoraban/manejaban incorrectamente cualquier operación ideal definida globalmente presente en el objetivo. Por ejemplo:

    from qiskit.transpiler import Target
    from qiskit.circuit.library import CXGate
    
    target = Target(num_qubits=5)
    target.add_instruction(CXGate())
    names = target.operation_names_for_qargs((1, 2))
    ops = target.operations_for_qargs((1, 2))

    devolverá ahora {"cx"} para names y [CXGate()] para ops en lugar de generar un KeyError o un retorno vacío.

  • Se ha corregido un problema en el método Target.add_instruction() que anteriormente aceptaba un argumento con un número no válido de qubits como parte del argumento properties . Por ejemplo:

    from qiskit.transpiler import Target
    from qiskit.circuit.library import CXGate
    
    target = Target()
    target.add_instruction(CXGate(), {(0, 1, 2): None})

    Ahora se mostrará correctamente TranspilerError en lugar de causar problemas en tiempo de ejecución al interactuar con el objetivo. Corregido #8914

  • Se ha corregido un problema con la función plot_state_hinton() que daba lugar a un eje mal colocado y desplazado del gráfico real. Corregido #8446 <https://github.com/Qiskit/qiskit/issues/8446>

  • Se ha corregido la salida de la función plot_state_hinton() para que las etiquetas de estado se ordenen correctamente y la imagen coincida con la ordenación natural de la matriz. Corregido #8324

  • Solucionado un problema con las clases primitivas, BackendSampler y BackendEstimator cuando se ejecuta en backends que tienen un número limitado de circuitos en cada trabajo. No todos los backends admiten un tamaño de lote ilimitado (la mayoría de los backends de hardware no lo hacen) y anteriormente las clases primitivas del backend habrían enviado potencialmente de forma incorrecta más circuitos de los que el backend admitía. Esto se ha corregido para que BackendSampler y BackendEstimator dividirá los circuitos en varios trabajos si el backend tiene un número limitado de circuitos por trabajo.

  • Se ha solucionado un problema con la clase BackendEstimator por el que, al establecer una opción de ejecución denominada monitor en un valor que se evaluaba como True , se activaba incorrectamente un monitor de trabajo que sólo funcionaba con backends del paquete qiskit-ibmq-provider . Esto se ha eliminado para que pueda utilizar una opción de ejecución monitor si es necesario sin causar ningún problema.

  • Se ha corregido un problema con el método Target.build_coupling_map() que devolvía incorrectamente None para un objeto Target con una mezcla de instrucciones ideales disponibles globalmente e instrucciones con restricciones de qubits. Ahora bien, en estos casos el Target.build_coupling_map() devolverá un mapa de acoplamiento para la instrucción restringida (a menos que sea una operación de 2 qubits que devolverá None porque globalmente no hay restricción de conectividad). Corregido #8971

  • Se ha corregido un problema con el atributo Target.qargs que devolvía incorrectamente None para un objeto Target que contenía cualquier instrucción ideal disponible globalmente.

  • Se ha corregido la eliminación prematura del argumento de la palabra clave pauli_list de la función pauli_basis() que rompía el código existente utilizando la ruta de compatibilidad futura pauli_list=True en la actualización a Qiskit Terra 0.22.0. Este argumento de palabra clave se ha añadido de nuevo a la función y ahora está obsoleto y se eliminará en una futura versión.

  • Se ha corregido un problema en la serialización QPY (dump()) cuando una subclase ControlledGate que sobrecargaba el método _define() para proporcionar una definición personalizada para la operación. Anteriormente, este caso de operación no se serializaba correctamente porque no se tenía en cuenta el uso del método potencialmente _define() para proporcionar una definición. Correcciones #8794

  • La deserialización QPY ya no añadirá instancias Clbit instancias al circuito si hay tanto loose Clbits en el circuito y más Qubits que Clbits.

  • La deserialización de QPY ya no añadirá registros llamados q y c si el circuito de entrada sólo contenía bits sueltos.

  • Corregido el SparsePauliOp.dot() cuando se ejecuta en dos operadores con coeficientes reales. Para solucionarlo, el dtype que puede tomar SparsePauliOp se restringe a np.complex128 y object. Corregido #8992

  • Se ha corregido un problema en la función circuit_drawer() y el método QuantumCircuit.draw() por el que el único estilo incorporado para la salida de mpl que se podía utilizar era default. Si se utilizara otro estilo incorporado, como iqx, se emitiría una advertencia de que no se encuentra el estilo y el cajón volvería a utilizar el estilo default . Corregido #8991

  • Se ha solucionado un problema con la función transpile() que anteriormente fallaba con un TypeError si se pasaba un objeto personalizado Target mediante el argumento target y se especificaba una lista de varios circuitos para el argumento circuits .

  • Se ha corregido un problema con transpile() cuando se apuntaba a un Target (ya sea directamente a través del argumento target o a través de una instancia de BackendV2 del argumento backend ) que contenía una instrucción ideal Measure (una que no tiene ninguna propiedad definida). Antes se producía una excepción al intentar analizar el objetivo. Corregido #8969

  • Se ha solucionado un problema con el VF2Layout cuando se ejecutaba con un Target que tenía instrucciones a las que les faltaban tasas de error. Esto se ha corregido para que, en tales casos, la falta de una tasa de error se trate como una implementación ideal y, si no hay tasas de error presentes, sólo seleccionará el primer diseño coincidente. Corregido #8970

  • Se ha solucionado un problema con el VF2PostLayout cuando se ejecutaba con un Target que tenía instrucciones que faltaban. En estos casos, la ausencia de porcentaje de error se considerará una ejecución ideal de la operación.

  • Se ha corregido un problema con la clase VQD si se calculaban más de k=2 valores propios. Anteriormente esto fallaba debido a un desajuste de tipo interno, pero ahora se ejecuta como se espera. Corregido #8982

  • Se ha corregido un error de rendimiento por el que los nuevos algoritmos variacionales basados en primitivas minimum_eigensolvers.VQE, eigensolvers.VQD y SamplingVQE no realizaban evaluaciones de energía por lotes de forma predeterminada, lo que provocaba una ralentización significativa si se utilizaba un backend de hardware.

  • Las puertas e instrucciones de operando cero funcionarán ahora con circuit_to_gate(), QuantumCircuit.to_gate(), Gate.control()y la construcción de un Operator a partir de un QuantumCircuit que contenga instrucciones operando por cero. Este caso de borde es ocasionalmente útil en la creación de puertas de fase global como parte de instrucciones compuestas más grandes, aunque para muchos usos, QuantumCircuit.global_phase puede ser más apropiado.

  • Soluciona el problema por el que Statevector.evolve() y DensityMatrix.evolve() provocaba un error en la evolución de subsistemas anidados para subsistemas no qubits. Soluciona el problema #8897

  • Se corrige un error en Statevector.evolve() por el que la evolución del subsistema devolverá el valor incorrecto en ciertos casos en los que hay 2 o más subsistemas no evolucionados con diferentes dimensiones del subsistema. Soluciona el problema #8899

Aer 0.11.1

Corrección de errores

  • Se ha corregido un posible error de compilación al intentar utilizar CMake 3.18 o posterior y compilar qiskit-aer con soporte para GPU activado. Desde CMake 3.18 o posterior, cuando se compila con CUDA, es necesario configurar CMAKE_CUDA_ARCHITECTURES con el valor de arquitectura de la GPU de destino. Esto se ha corregido para que se utilice la configuración AER_CUDA_ARCH si no estaba configurada.

  • Corrige un error en el manejo de instrucciones con clbits en LocalNoisePass. Anteriormente, se borraban accidentalmente clbits de instrucciones (por ejemplo, medidas) a los que se aplica el ruido en el caso de method="append".

  • Se ha corregido la sobrecarga de rendimiento de la clase Sampler cuando se ejecuta con circuitos idénticos en varias ejecuciones. Esto se consiguió saltándose/almacenando en caché la transpilación de estos circuitos idénticos en ejecuciones posteriores.

  • Corregida la compatibilidad de las clases primitivas Sampler y Estimator con la versión qiskit-terra 0.22.0. En qiskit-terra 0.22.0 se introdujeron cambios en la interfaz abstracta que rompieron la compatibilidad con estas clases Sampler y Estimator pueden utilizarse ahora con qiskit-terra >= 0.22.0.

IBM Proveedor Q 0.19.2

No cambia


0.39.0

Esta versión también deja oficialmente obsoleto el proyecto Qiskit Aer como parte del metapaquete Qiskit. Esto significa que en una futura versión pip install qiskit ya no incluirá qiskit-aer. Si actualmente está instalando o listando qiskit como una dependencia para obtener Aer debe actualizar esto para listar explícitamente qiskit-aer también.

El proyecto qiskit-aer sigue activo y se mantiene en el futuro, pero para el metapaquete Qiskit (es decir, lo que se instala a través de pip install qiskit) el proyecto se está moviendo 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, y los paquetes que se basan en él o enlazan Qiskit con hardware o simuladores son paquetes separados.

Terra 0.22.0

Preludio

La versión de Qiskit Terra 0.22.0 es una versión de características principales que incluye una miríada de nuevas funciones y correcciones de errores. Los aspectos más destacados de esta versión son:

  • Añadir soporte inicial al transpilador para transpilar QuantumCircuit que contienen instrucciones de flujo de control como ForLoopOp y WhileLoopOp.
  • Escalado y rendimiento muy mejorados para la función transpile() con un gran número de qubits, especialmente cuando se utiliza optimization_level=3 .
  • Interfaz de plugin externo para transpile() que permite a los paquetes externos implementar etapas para los gestores de pases predeterminados. Encontrará más información al respecto en qiskit.transpiler.preset_passmanagers.plugin. Además, BackendV2 los backends ahora pueden establecer opcionalmente plugins personalizados por defecto para usar en las etapas de programación y traducción.
  • Implementaciones actualizadas de algoritmos en qiskit.algorithms que aprovechan las clases primitives que implementan las clases BaseSampler y BaseEstimator.

Nuevas funciones

  • Añadir soporte para representar una operación que tiene un ancho variable a la clase Target clase. Anteriormente, un objeto Target necesitaba tener una instancia de Operation definida para cada operación soportada en el objetivo. Se utilizó tanto para validar los argumentos como los parámetros de la operación. Sin embargo, para las operaciones que tienen una anchura variable esto no era posible porque cada instancia de una clase Operation sólo puede tener un número fijo de qubits. En los casos en que un backend admita operaciones de anchura variable, la instrucción puede añadirse con la clase de la operación en lugar de una instancia. En tales casos, la operación se considerará globalmente compatible con todos los qubits. Por ejemplo, si se construye un objetivo como:

    from qiskit.circuit import Parameter, Measure, IfElseOp, ForLoopOp, WhileLoopOp
    from qiskit.circuit.library import IGate, RZGate, SXGate, XGate, CXGate
    from qiskit.transpiler import Target, InstructionProperties
    
    theta = Parameter("theta")
    
    ibm_target = Target()
    i_props = {
        (0,): InstructionProperties(duration=35.5e-9, error=0.000413),
        (1,): InstructionProperties(duration=35.5e-9, error=0.000502),
        (2,): InstructionProperties(duration=35.5e-9, error=0.0004003),
        (3,): InstructionProperties(duration=35.5e-9, error=0.000614),
        (4,): InstructionProperties(duration=35.5e-9, error=0.006149),
    }
    ibm_target.add_instruction(IGate(), i_props)
    rz_props = {
        (0,): InstructionProperties(duration=0, error=0),
        (1,): InstructionProperties(duration=0, error=0),
        (2,): InstructionProperties(duration=0, error=0),
        (3,): InstructionProperties(duration=0, error=0),
        (4,): InstructionProperties(duration=0, error=0),
    }
    ibm_target.add_instruction(RZGate(theta), rz_props)
    sx_props = {
        (0,): InstructionProperties(duration=35.5e-9, error=0.000413),
        (1,): InstructionProperties(duration=35.5e-9, error=0.000502),
        (2,): InstructionProperties(duration=35.5e-9, error=0.0004003),
        (3,): InstructionProperties(duration=35.5e-9, error=0.000614),
        (4,): InstructionProperties(duration=35.5e-9, error=0.006149),
    }
    ibm_target.add_instruction(SXGate(), sx_props)
    x_props = {
        (0,): InstructionProperties(duration=35.5e-9, error=0.000413),
        (1,): InstructionProperties(duration=35.5e-9, error=0.000502),
        (2,): InstructionProperties(duration=35.5e-9, error=0.0004003),
        (3,): InstructionProperties(duration=35.5e-9, error=0.000614),
        (4,): InstructionProperties(duration=35.5e-9, error=0.006149),
    }
    ibm_target.add_instruction(XGate(), x_props)
    cx_props = {
        (3, 4): InstructionProperties(duration=270.22e-9, error=0.00713),
        (4, 3): InstructionProperties(duration=305.77e-9, error=0.00713),
        (3, 1): InstructionProperties(duration=462.22e-9, error=0.00929),
        (1, 3): InstructionProperties(duration=497.77e-9, error=0.00929),
        (1, 2): InstructionProperties(duration=227.55e-9, error=0.00659),
        (2, 1): InstructionProperties(duration=263.11e-9, error=0.00659),
        (0, 1): InstructionProperties(duration=519.11e-9, error=0.01201),
        (1, 0): InstructionProperties(duration=554.66e-9, error=0.01201),
    }
    ibm_target.add_instruction(CXGate(), cx_props)
    measure_props = {
        (0,): InstructionProperties(duration=5.813e-6, error=0.0751),
        (1,): InstructionProperties(duration=5.813e-6, error=0.0225),
        (2,): InstructionProperties(duration=5.813e-6, error=0.0146),
        (3,): InstructionProperties(duration=5.813e-6, error=0.0215),
        (4,): InstructionProperties(duration=5.813e-6, error=0.0333),
    }
    ibm_target.add_instruction(Measure(), measure_props)
    ibm_target.add_instruction(IfElseOp, name="if_else")
    ibm_target.add_instruction(ForLoopOp, name="for_loop")
    ibm_target.add_instruction(WhileLoopOp, name="while_loop")

    En IfElseOp, ForLoopOpy WhileLoopOp se admiten globalmente para cualquier número de qubits. Esto se refleja en otras llamadas de la Target API como instruction_supported():

    ibm_target.instruction_supported(operation_class=WhileLoopOp, qargs=(0, 2, 3, 4))
    ibm_target.instruction_supported('if_else', qargs=(0, 1))

    ambos devuelven True.

  • Añadidas nuevas implementaciones de primitivas BackendSampler y BackendEstimator. a qiskit.primitives. Estas nuevas implementaciones de clases primitivas envuelven una clase BackendV1 o BackendV2 como una instancia de BaseSampler o BaseEstimator respectivamente. El caso de uso previsto para estas implementaciones primitivas es tender un puente entre los proveedores que no tienen implementaciones primitivas nativas y utilizan el backend de ese proveedor con APIs que funcionan con primitivas. Por ejemplo, la clase SamplingVQE necesita una instancia BaseSampler para funcionar. Si desea ejecutar esa clase con un backend de un proveedor sin una implementación primitiva nativa, puede construir una clase BackendSampler para ello:

    from qiskit.algorithms.minimum_eigensolvers import SamplingVQE
    from qiskit.algorithms.optimizers import SLSQP
    from qiskit.circuit.library import TwoLocal
    from qiskit.primitives import BackendSampler
    from qiskit.providers.fake_provider import FakeHanoi
    from qiskit.opflow import PauliSumOp
    from qiskit.quantum_info import SparsePauliOp
    
    backend = FakeHanoi()
    sampler = BackendSampler(backend=backend)
    
    operator = PauliSumOp(SparsePauliOp(["ZZ", "IZ", "II"], coeffs=[1, -0.5, 0.12]))
    ansatz = TwoLocal(rotation_blocks=["ry", "rz"], entanglement_blocks="cz")
    optimizer = SLSQP()
    sampling_vqe = SamplingVQE(sampler, ansatz, optimizer)
    result = sampling_vqe.compute_minimum_eigenvalue(operator)
    eigenvalue = result.eigenvalue

    Si está utilizando un proveedor que tiene implementaciones primitivas nativas (como qiskit-ibm-runtime o qiskit-aer) siempre es una mejor opción utilizar esa implementación primitiva nativa en lugar de BackendEstimator o BackendSampler ya que las implementaciones nativas serán mucho más eficientes y/o harán pre y post procesamiento adicional. BackendEstimator y BackendSampler están diseñados para ser genéricos que pueden trabajar con cualquier backend que devuelve Counts en su Results lo que excluye una optimización adicional.

  • Añadida una nueva clase de algoritmo AdaptVQE a qiskit.algorithms Este algoritmo utiliza un qiskit.algorithms.minimum_eigensolvers.VQE en combinación con un conjunto de operadores de qiskit.circuit.library.EvolvedOperatorAnsatz de forma adaptativa. Por ejemplo:

    from qiskit.algorithms.minimum_eigensolvers import AdaptVQE, VQE
    from qiskit.algorithms.optimizers import SLSQP
    from qiskit.primitives import Estimator
    from qiskit.circuit.library import EvolvedOperatorAnsatz
    
    # get your Hamiltonian
    hamiltonian = ...
    
    # construct your ansatz
    ansatz = EvolvedOperatorAnsatz(...)
    
    vqe = VQE(Estimator(), ansatz, SLSQP())
    
    adapt_vqe = AdaptVQE(vqe)
    
    result = adapt_vqe.compute_minimum_eigenvalue(hamiltonian)
  • La clase BackendV2 admite ahora dos nuevos puntos de conexión opcionales que permiten a los backends inyectar pasos de compilación personalizados como parte de la clase transpile() y generate_preset_pass_manager(). Si una BackendV2 incluye los métodos get_scheduling_stage_plugin() o get_translation_stage_plugin() , el transpilador utilizará la cadena devuelta como valor por defecto para los argumentos scheduling_method y translation_method . Esto permite a los backends ejecutar pases de transpilador personalizados adicionales cuando se dirigen a ese backend aprovechando la interfaz de etapa de transpilador plugin del transpilador. Para más detalles sobre cómo utilizarlo, consulte: Pases de transpilador personalizados.

  • Se ha añadido un nuevo argumento de palabra clave, ignore_backend_supplied_default_methods, a la función transpile() que puede utilizarse para desactivar la selección personalizada de un método predeterminado por parte de un backend si el backend de destino tiene definidos get_scheduling_stage_plugin() o get_translation_stage_plugin() .

  • Se ha añadido un parámetro label al Barrier y al método barrier() que permite al usuario asignar una etiqueta a una instancia de la directiva Barrier directiva. Para visualizaciones generadas con circuit_drawer() o QuantumCircuit.draw() esta etiqueta se imprimirá en la parte superior de barrier.

    from qiskit import QuantumCircuit
    
    circuit = QuantumCircuit(2)
    circuit.h(0)
    circuit.h(1)
    circuit.barrier(label="After H")
    circuit.draw('mpl')
  • Añadir nuevas puertas CCZGate, CSGatey CSdgGate a las puertas estándar de la Biblioteca de Circuitos (qiskit.circuit.library).

  • Se ha añadido el paquete qiskit.algorithms.eigensolvers para incluir interfaces para algoritmos con primitivas. Este nuevo módulo acabará sustituyendo al anterior qiskit.algorithms.eigen_solvers. Este nuevo módulo contiene una implementación alternativa del VQD que en lugar de tomar un backend o QuantumInstance toma una instancia de BaseEstimatorincluyendo Estimator, BackendEstimatoro cualquier implementación de proveedor como las presentes en qiskit-ibm-runtime y qiskit-aer.

    Por ejemplo, para utilizar la nueva implementación con una instancia de Estimator clase

    from qiskit.algorithms.eigensolvers import VQD
    from qiskit.algorithms.optimizers import SLSQP
    from qiskit.circuit.library import TwoLocal
    from qiskit.primitives import Sampler, Estimator
    from qiskit.algorithms.state_fidelities import ComputeUncompute
    from qiskit.opflow import PauliSumOp
    from qiskit.quantum_info import SparsePauliOp
    
    h2_op = PauliSumOp(SparsePauliOp(
        ["II", "IZ", "ZI", "ZZ", "XX"],
        coeffs=[
            -1.052373245772859,
            0.39793742484318045,
            -0.39793742484318045,
            -0.01128010425623538,
            0.18093119978423156,
        ],
    ))
    
    estimator = Estimator()
    ansatz = TwoLocal(rotation_blocks=["ry", "rz"], entanglement_blocks="cz")
    optimizer = SLSQP()
    fidelity = ComputeUncompute(Sampler())
    
    vqd = VQD(estimator, fidelity, ansatz, optimizer, k=2)
    result = vqd.compute_eigenvalues(h2_op)
    eigenvalues = result.eigenvalues

    Nótese que los operadores auxiliares evaluados se obtienen ahora a través del campo aux_operators_evaluated sobre los resultados. Consistirá en una lista o dict de tuplas que contendrán los valores de expectativa de estos operadores, así como los metadatos de ejecución primitiva. aux_operator_eigenvalues ya no es un campo válido.

  • Añadidos nuevos algoritmos para calcular fidelidades/solapamientos de estado para pares de circuitos cuánticos (que pueden ser parametrizados). Además de la clase base (BaseStateFidelity) que define la interfaz, existe una implementación del método computar-descomputar que aprovecha las instancias de la clase BaseSampler primitiva: qiskit.algorithms.state_fidelities.ComputeUncompute.

    Por ejemplo:

    import numpy as np
    from qiskit.primitives import Sampler
    from qiskit.algorithms.state_fidelities import ComputeUncompute
    from qiskit.circuit.library import RealAmplitudes
    
    sampler = Sampler(...)
    fidelity = ComputeUncompute(sampler)
    circuit = RealAmplitudes(2)
    values = np.random.random(circuit.num_parameters)
    shift = np.ones_like(values) * 0.01
    
    job = fidelity.run([circuit], [circuit], [values], [values+shift])
    fidelities = job.result().fidelities
  • Se ha añadido un nuevo módulo qiskit.algorithms.gradients que contiene clases que se utilizan para calcular gradientes utilizando las interfaces primitivas definidas en qiskit.primitives. Hay 4 tipos de clases de gradiente: Diferencia Finita, Desplazamiento de Parámetros, Combinación Lineal Unitaria y SPSA con implementaciones que o bien utilizan una instancia de la interfaz BaseEstimator interfaz:

    o una instancia de la BaseSampler interfaz:

    Los gradientes basados en el estimador calculan el gradiente de los valores de las expectativas, mientras que los gradientes basados en el muestreador devuelven gradientes de los resultados de las mediciones (también denominados "gradientes de probabilidad").

    Por ejemplo:

    estimator = Estimator(...)
    gradient = ParamShiftEstimatorGradient(estimator)
    job = gradient.run(circuits, observables, parameters)
    gradients = job.result().gradients
  • La clase Grover tiene un nuevo argumento de palabra clave, sampler , que se utiliza para ejecutar el algoritmo utilizando una instancia de la interfaz BaseSampler para calcular los resultados. Este nuevo argumento sustituye al argumento quantum_instance y, en consecuencia, quantum_instance está pendiente de desaprobación y será desaprobado y posteriormente eliminado en futuras versiones.

    Ejemplo:

    from qiskit import QuantumCircuit
    from qiskit.primitives import Sampler
    from qiskit.algorithms import Grover, AmplificationProblem
    
    sampler = Sampler()
    oracle = QuantumCircuit(2)
    oracle.cz(0, 1)
    problem = AmplificationProblem(oracle, is_good_state=["11"])
    grover = Grover(sampler=sampler)
    result = grover.amplify(problem)
  • Se ha añadido una nueva opción, "formatter.control.fill_waveform" , a las hojas de estilo del cajón de pulso (pulse_v2.draw() y Schedule.draw()). Esta opción se puede utilizar para eliminar el color de la cara de los pulsos en la visualización de salida, lo que permite dibujar pulsos sólo con líneas.

    Por ejemplo:

    from qiskit.visualization.pulse_v2 import IQXStandard
    
    my_style = IQXStandard(
        **{"formatter.control.fill_waveform": False, "formatter.line_width.fill_waveform": 2}
    )
    
    my_sched.draw(style=my_style)
  • Añadido un nuevo pase transpiler, ResetAfterMeasureSimplificationque se utiliza para sustituir una operación Reset después de una operación Measure por una condicional XGate. Este pase se puede utilizar en backends donde una Reset operación se realiza haciendo una medición y luego una puerta X condicional para que esto elimine el duplicado implícito Measure de la Reset operación. Por ejemplo:

    from qiskit import QuantumCircuit
    from qiskit.transpiler.passes import ResetAfterMeasureSimplification
    
    qc = QuantumCircuit(1)
    qc.measure_all()
    qc.reset(0)
    qc.draw('mpl')
    result = ResetAfterMeasureSimplification()(qc)
    result.draw('mpl')
  • Añadido un nuevo valor soportado, "reverse_linear" para el argumento de la palabra clave entanglement al constructor de la clase NLocal clase circuito. En TwoLocal (que son subclases de NLocal), si entanglement_blocks="cx" , el uso de entanglement="reverse_linear" proporciona un circuito n-qubit equivalente a entanglement="full" pero con sólo n1n-1 CXGate en lugar de n(n1)2\frac{n(n-1)}{2}.

  • ScheduleBlock se ha actualizado para que pueda gestionar subrutinas no asignadas, es decir, para permitir la llamada perezosa a otros programas. Por ejemplo, esto permite el siguiente flujo de trabajo:

    from qiskit import pulse
    
    with pulse.build() as prog:
      pulse.reference("x", "q0")
    
    with pulse.build() as xq0:
      pulse.play(Gaussian(160, 0.1, 40), pulse.DriveChannel(0))
    
    prog.assign_references({("x", "q0"): xq0})

    Ahora un usuario puede crear prog sin conocer la implementación real de la referencia ("x", "q0"), y asignarla en un momento posterior para su ejecución. Esto mejora la modularidad de los programas de pulsos, y así se puede escribir fácilmente una plantilla de programa de pulsos que se base en otras calibraciones.

    Para realizar esta función, se ha añadido la nueva instrucción pulse (directiva del compilador) Reference se ha añadido. Esta instrucción se inyecta en el ámbito del constructor actual cuando se utiliza el comando reference() se utiliza. Todas las referencias definidas en el programa de pulsos actual pueden listarse con la propiedad references .

    Además, cada referencia se gestiona con un ámbito para facilitar la gestión de parámetros. scoped_parameters() y search_parameters() se han añadido a ScheduleBlock. Consulte la documentación de la API para obtener más detalles.

  • Añadido un nuevo método SparsePauliOp.argsort()que devuelve la composición de permutaciones en el orden de ordenación por coeficiente y ordenación por Pauli. Utilizando la palabra clave weight como argumento para el método, la salida puede ordenarse adicionalmente por el número de términos no idénticos en el Pauli, donde el conjunto de todos los Paulis de un peso dado siguen ordenados lexicográficamente.

  • Añadido un nuevo método SparsePauliOp.sort()que primero ordenará los coeficientes usando argsort() de numpy y luego ordenará por Pauli, donde la ordenación Pauli tiene prioridad. Si la ordenación Pauli es la misma, entonces se ordenará por coeficiente. Utilizando el argumento de la palabra clave weight , la salida puede ordenarse adicionalmente por el número de términos no idénticos en el Pauli, donde el conjunto de todos los Paulis de un peso dado siguen ordenados lexicográficamente.

  • Se ha añadido un nuevo argumento de palabra clave, wire_order, a la función circuit_drawer() función y QuantumCircuit.draw() que permite reordenar arbitrariamente tanto los bits cuánticos como los clásicos en la visualización de salida. Por ejemplo:

    from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
    
    qr = QuantumRegister(4, "q")
    cr = ClassicalRegister(4, "c")
    cr2 = ClassicalRegister(2, "ca")
    circuit = QuantumCircuit(qr, cr, cr2)
    circuit.h(0)
    circuit.h(3)
    circuit.x(1)
    circuit.x(3).c_if(cr, 10)
    circuit.draw('mpl', cregbundle=False, wire_order=[2, 1, 3, 0, 6, 8, 9, 5, 4, 7])
  • Se ha añadido compatibilidad con el CSGate, CSdgGate y CCZGate al constructor de la clase de operador CNOTDihedral. Los circuitos de entrada al crear un CNOTDihedral ahora admitirán circuitos que utilicen estas puertas. Por ejemplo:

    from qiskit import QuantumCircuit
    from qiskit.quantum_info import CNOTDihedral
    
    qc = QuantumCircuit(2)
    qc.t(0)
    qc.cs(0, 1)
    qc.tdg(0)
    operator = CNOTDihedral(qc)
  • Las clases del algoritmo de estimación de la amplitud:

    Ahora tienen un nuevo argumento de palabra clave, sampler en su constructor que toma una instancia de un objeto que implementa la interfaz BaseSampler interfaz incluyendo BackendSamplerSampler, o cualquier implementación de proveedores como las presentes en qiskit-ibm-runtime y qiskit-aer. Esto proporciona una alternativa al uso del argumento quantum_instance para establecer el objetivo Backend o QuantumInstance para ejecutar el algoritmo. El uso de a QuantumInstance está pendiente de ser obsoleto y lo será en una futura versión.

  • Añadida una nueva clase, BackendV2Converterque se utiliza para envolver una instancia BackendV1 en una interfaz BackendV2 interfaz. Le permite disponer de una BackendV2 instancia de cualquier BackendV1. Esto permite estandarizar los patrones de acceso en la nueva BackendV2 aunque siga soportando la interfaz BackendV1.

  • Se ha añadido una nueva función convert_to_target() que se utiliza para tomar un BackendConfigurationy opcionalmente un BackendProperties y PulseDefaults y crear un objeto Target equivalente al contenido de dichos objetos.

  • qiskit.quantum_info.BaseOperator subclases (como ScalarOp, SparsePauliOp y PauliList) pueden utilizarse ahora con la función integrada Python sum() .

  • Se ha añadido un nuevo transpilador pass, ConvertConditionsToIfOps que puede utilizarse para convertir instrucciones condicionadas de estilo antiguo en instrucciones condicionadas de estilo antiguo Instruction.c_if()-instrucciones condicionadas en IfElseOp objetos. Esto es para ayudar a facilitar la transición del tipo antiguo al nuevo para los backends. Para la mayoría de los usuarios, no hay necesidad de añadir esto a sus gestores de pases, y no está incluido en ningún gestor de pases preestablecido.

  • Refactorización del análisis de conmutatividad de puertas en una clase CommutationChecker. Esta clase le permite comprobar (basándose en la multiplicación de matrices) si dos puertas conmutan o no conmutan, y almacenar en caché los resultados (de modo que una comprobación similar en el futuro ya no requiera la multiplicación de matrices).

    Por ejemplo, ahora podemos hacer:

    from qiskit.circuit import QuantumRegister, CommutationChecker
    
    comm_checker = CommutationChecker()
    qr = QuantumRegister(4)
    
    res = comm_checker.commute(CXGate(), [qr[1], qr[0]], [], CXGate(), [qr[1], qr[2]], [])

    Como las dos puertas CX conmutan (la primera puerta CX está sobre los qubits qr[1] y qr[0], y la segunda puerta CX está sobre los qubits qr[1] y qr[2]), tendremos que res es True.

    Esta comprobación de conmutatividad es excesivamente conservadora para puertas condicionales y parametrizadas, y puede devolver False incluso cuando dichas puertas conmutan.

  • Añadido un nuevo pase de transpilador CommutativeInverseCancellation que cancela pares de puertas inversas explotando las relaciones de conmutación entre puertas. Este paso es una generalización del paso transpiler InverseCancellation ya que detecta un conjunto mayor de puertas inversas y tiene en cuenta la conmutatividad. El pase también evita algunos problemas asociados con el pase del transpilador CommutativeCancellation.

    Por ejemplo:

    from qiskit.circuit import QuantumCircuit
    from qiskit.transpiler import PassManager
    from qiskit.transpiler.passes import CommutativeInverseCancellation
    
    circuit = QuantumCircuit(2)
    circuit.z(0)
    circuit.x(1)
    circuit.cx(0, 1)
    circuit.z(0)
    circuit.x(1)
    
    passmanager = PassManager(CommutativeInverseCancellation())
    new_circuit = passmanager.run(circuit)

    anula el par de compuertas Z autoinversas y el par de compuertas X autoinversas (ya que las compuertas correspondientes conmutan con la compuerta CX), produciendo un circuito formado por una única compuerta CX.

    La comprobación inversa es excesivamente conservadora para las puertas condicionales y parametrizadas, y puede no cancelar algunas de ellas.

  • QuantumCircuit.compose() aceptará ahora un operando con bits clásicos si el circuito base no tiene ninguno. El patrón de componer un circuito con medidas sobre un circuito sólo cuántico es ahora válido. Por ejemplo:

    from qiskit import QuantumCircuit
    
    base = QuantumCircuit(3)
    terminus = QuantumCircuit(3, 3)
    terminus.measure_all()
    
    # This will now succeed, though it was previously a CircuitError.
    base.compose(terminus)
  • Los métodos DAGCircuit métodos depth() y size() tienen un nuevo argumento de palabra clave recurse para su uso con circuitos que contienen operaciones de flujo de control (como IfElseOp, WhileLoopOpy ForLoopOp). Por defecto es False y lanzará un error si hay operaciones de flujo de control, para evitar resultados mal definidos. Si se establece en True, se devuelve un valor proxy que intenta ponderar equitativamente cada bloque de flujo de control en relación con su condición, aunque la profundidad o el tamaño de una ejecución concreta sea generalmente desconocida. Consulte la documentación de cada método para saber cómo afecta a la salida cada operación de flujo de control.

  • DAGCircuit.count_ops() ganó un argumento de palabra clave recurse para recursar en bloques de flujo de control. Por defecto es True, y se devolverán todas las operaciones de todos los bloques, así como las propias operaciones de flujo de control.

  • Se ha añadido un argumento create_preds_and_succs a las funciones circuit_to_dagdependency() y dag_to_dagdependency() que convierten de QuantumCircuit y DAGCircuitrespectivamente, a DAGDependency. Cuando el valor de create_preds_and_succs es False, los predecesores y sucesores transitivos de los nodos en DAGDependency no se construyen, haciendo las conversiones más rápidas y significativamente menos intensivas en memoria. Los predecesores y sucesores directos de los nodos de DAGDependency se construyen como de costumbre.

    Por ejemplo:

    from qiskit.converters import circuit_to_dagdependency
    from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
    
    circuit_in = QuantumCircuit(2)
    circuit_in.h(qr[0])
    circuit_in.h(qr[1])
    
    dag_dependency = circuit_to_dagdependency(circuit_in, create_preds_and_succs=False)
  • Nuevos atributos añadidos Clifford.symplectic_matrix, Clifford.tableau, Clifford.z, Clifford.x, Clifford.phase, Clifford.stab, Clifford.stab_z, Clifford.stab_x, Clifford.stab_phase, Clifford.destab, Clifford.destab_z, Clifford.destab_x, Clifford.destab_phase a la Clifford clase. Pueden utilizarse en lugar de Clifford.table, que quedará obsoleto en el futuro. StabilizerTable y PauliTable están pendientes de desaprobación y serán desaprobados en la próxima versión y posteriormente eliminados.

  • El constructor Commuting2qGateRouter tiene ahora una nueva palabra clave como argumento: edge_coloring. Este argumento se utiliza para proporcionar una coloración de borde del mapa de acoplamiento para determinar el orden en que se aplican las puertas de conmutación.

  • Se ha añadido una nueva interfaz de algoritmos para crear algoritmos de evolución temporal utilizando las primitivas BaseSampler y BaseEstimator. Esta nueva interfaz consta de:

    Esta nueva interfaz es una alternativa a la interfaz de algoritmos de evolución temporal existente anteriormente y disponible definida con EvolutionProblem, EvolutionResult, RealEvolvery ImaginaryEvolver que trabajaban con un QuantumInstance en lugar de primitivas. Esta nueva interfaz sustituye a la anterior, que quedará obsoleta y se eliminará en futuras versiones.

  • Añadidas nuevas clases de backend a qiskit.providers.fake_provider:

    Estas nuevas clases implementan la interfaz BackendV2 y se crean utilizando instantáneas almacenadas de la información del backend de los sistemas IBM Quantum ibm_auckland, ibm_oslo, ibm_geneva, y ibm_perth respectivamente.

  • La clase Z2Symmetries tiene dos nuevos métodos convert_clifford() y taper_clifford(). Estos dos métodos son las dos operaciones necesarias para estrechar un operador basándose en las simetrías Z2 del objeto y antes se realizaban internamente mediante el método taper() método Sin embargo, estos métodos son ahora métodos públicos de la clase que pueden ser llamados individualmente si es necesario.

  • El rendimiento en tiempo de ejecución para la conjugación de un objeto largo PauliList por un objeto Clifford utilizando el PauliList.evolve() ha mejorado significativamente. Ahora funcionará mucho más rápido que antes.

  • Añadida una nueva clase abstracta ClassicalIOChannel al módulo qiskit.pulse.channels módulo. Esta clase se utiliza para representar canales de E/S clásicos y diferenciarlos de otras subclases de Channel. Esta nueva clase es la clase base para la clase MemorySlot, RegisterSloty SnapshotChannel y. En consecuencia, la pad() transformación de impulsos de canonización en qiskit.pulse.transforms no introducirá retrasos en ninguna instancia de ClassicalIOChannel

  • El SabreSwap transpiler pass tiene un nuevo argumento de palabra clave en su constructor, trials. El argumento trials se utiliza para especificar el número de pruebas aleatorias que se intentarán. El resultado del algoritmo SABRE puede variar enormemente en función de la semilla utilizada para el número aleatorio. SabreSwap ejecutará ahora el algoritmo con trials número de semillas aleatorias y elegirá la mejor (con el menor número de intercambios insertados). Si no se especifica trials , el pase utilizará por defecto el número de CPU físicas del sistema local.

  • El SabreLayout transpiler pass tiene un nuevo argumento de palabra clave en su constructor, swap_trials. El argumento swap_trials se utiliza para especificar cuántas pruebas de semillas aleatorias se ejecutarán en la SabreSwap pasar internamente. Corresponde al trials arugment en el SabreSwap pase. Cuando se establece, cada iteración de SabreSwap se ejecutará internamente swap_trials veces. Si no se especifica swap_trials , se utilizará por defecto el número de CPU físicas del sistema local.

  • Se ha añadido una nueva función estimate_observables() que utiliza una implementación de la interfaz BaseEstimator interfaz (por ejemplo Estimator, BackendEstimatoro cualquier implementación de proveedores como las presentes en qiskit-ibm-runtime y qiskit-aer) para calcular los valores de expectativa, sus medias y desviaciones estándar a partir de una lista o diccionario de observables. Esta función cumple una función similar a la función preexistente eval_observables() que realizaba el cálculo utilizando un objeto QuantumInstance y ha sido sustituida (y será obsoleta y posteriormente eliminada en futuras versiones) por esta nueva función.

  • Se ha añadido una nueva Operation que proporciona una interfaz abstracta y ligera para los objetos que se pueden poner en los ficheros QuantumCircuit. Esto permite almacenar objetos de "nivel superior" directamente en un circuito (por ejemplo, Clifford objetos), combinar directamente dichos objetos (por ejemplo, componer varios objetos Clifford objetos consecutivos sobre los mismos qubits), y sintetizar dichos objetos en tiempo de ejecución (por ejemplo, sintetizar Clifford de forma que se optimice la profundidad y/o se aproveche la conectividad de los dispositivos). Anteriormente, sólo las subclases de qiskit.circuit.Instruction podían incluirse en QuantumCircuitpero esta interfaz se ha vuelto difícil de manejar e incluye demasiados métodos y atributos para los objetos de uso general.

    La nueva Operation incluye name, num_qubits y num_clbits (en el futuro esto puede ajustarse ligeramente), pero lo más importante es que no incluye definition (y por tanto no vincula la síntesis al objeto), no incluye condition (esto debería formar parte de un flujo de control clásico separado), y no incluye duration y unit (ya que son propiedades de la salida del transpilador).

    A partir de ahora, Operation incluye Gate, Reset, Barrier, Measurey objetos de "nivel superior" como Clifford. Esta lista de objetos de "nivel superior" crecerá en el futuro.

  • A Clifford se añade ahora a un circuito cuántico como un Operationsin sintetizar primero un subcircuito que implemente este Clifford. La síntesis propiamente dicha se pospone a un pase de transpilación posterior HighLevelSynthesis de transpilación.

    Por ejemplo, el siguiente código:

    from qiskit import QuantumCircuit
    from qiskit.quantum_info import random_clifford
    
    qc = QuantumCircuit(3)
    cliff = random_clifford(2)
    qc.append(cliff, [0, 1])

    ya no convierte cliff en qiskit.circuit.Instructionlo que incluye sintetizar el clifford en un circuito, cuando se anexa a qc.

  • Añadido un nuevo pase de transpilador OptimizeCliffords que recoge bloques de objetos Clifford consecutivos en un circuito y sustituye cada bloque por un único objeto Clifford.

    Por ejemplo, el siguiente código:

    from qiskit import QuantumCircuit
    from qiskit.quantum_info import random_clifford
    from qiskit.transpiler.passes import OptimizeCliffords
    from qiskit.transpiler import PassManager
    
    qc = QuantumCircuit(3)
    cliff1 = random_clifford(2)
    cliff2 = random_clifford(2)
    qc.append(cliff1, [2, 1])
    qc.append(cliff2, [2, 1])
    qc_optimized = PassManager(OptimizeCliffords()).run(qc)

    almacena primero los dos Cliffords cliff1 y cliff2 en qc como objetos de "nivel superior", y luego el transpiler pass OptimizeCliffords optimiza el circuito componiendo estos dos Cliffords en un único Clifford. Tenga en cuenta que el Clifford resultante se sigue almacenando en qc como un objeto de nivel superior. Este pase aún no está incluido en ninguno de los gestores de pases predefinidos.

  • Se ha añadido un nuevo pase de transpilador HighLevelSynthesis que sintetiza objetos de nivel superior (por ejemplo, Clifford objetos).

    Por ejemplo, el siguiente código:

    from qiskit import QuantumCircuit
    from qiskit.quantum_info import random_clifford
    from qiskit.transpiler import PassManager
    from qiskit.transpiler.passes import HighLevelSynthesis
    
    qc = QuantumCircuit(3)
    qc.h(0)
    cliff = random_clifford(2)
    qc.append(cliff, [0, 1])
    
    qc_synthesized = PassManager(HighLevelSynthesis()).run(qc)

    sintetizará el Clifford de nivel superior almacenado en qc utilizando la función por defecto decompose_clifford() .

    Este nuevo pase de transpilador HighLevelSynthesis se integra en los gestores de pases predefinidos, ejecutándose justo después de UnitarySynthesis pass. Por lo tanto, transpile() sintetizará todos los Cliffords de nivel superior presentes en el circuito.

    Es importante señalar que el trabajo realizado para almacenar Clifford como objetos de "nivel superior" y transpilar estos objetos utilizando HighLevelSynthesis pass debería ser completamente transparente, y no se requieren cambios en el código.

  • SparsePauliOps pueden construirse ahora con matrices de coeficientes que son objetos generales de Python. Esto está pensado para su uso con objetos ParameterExpression otros objetos pueden funcionar, pero no tienen soporte de primera clase. Algunos métodos de SparsePauliOp (como la conversión a otras representaciones de clase) pueden no funcionar cuando se utilizan matrices object , si el destino deseado no puede representar estas matrices generales.

    Por ejemplo, un ParameterExpression SparsePauliOp podría ser construido por:

    import numpy as np
    from qiskit.circuit import Parameter
    from qiskit.quantum_info import SparsePauliOp
    
    print(SparsePauliOp(["II", "XZ"], np.array([Parameter("a"), Parameter("b")])))

    que da

    SparsePauliOp(['II', 'XZ'],
          coeffs=[ParameterExpression(1.0*a), ParameterExpression(1.0*b)])
  • Añadida una nueva función plot_distribution() para trazar distribuciones sobre cuasi-probabilidades. Esto es adecuado para Counts, QuasiDistribution y ProbDistribution. También se puede pasar el dict en bruto. Por ejemplo:

    from qiskit.visualization import plot_distribution
    
    quasi_dist = {'0': .98, '1': -.01}
    plot_distribution(quasi_dist)
  • Se ha introducido una nueva interfaz de plugin de síntesis de alto nivel que permite utilizar técnicas de síntesis alternativas incluidas en paquetes externos sin problemas con el HighLevelSynthesis transpilador. Estas técnicas de síntesis alternativas pueden especificarse para cualquier objeto de "nivel superior" de tipo Operationcomo, por ejemplo, para Clifford y LinearFunction . La interfaz de este plugin es similar a la de la síntesis unitaria. En este último caso, los detalles sobre cómo escribir un nuevo plugin aparecen en la qiskit.transpiler.passes.synthesis.plugin documentación del módulo.

  • Se ha introducido una nueva clase HLSConfig que puede utilizarse para especificar algoritmos de síntesis alternativos para objetos de "nivel superior" de tipo Operation. Para cada objeto de nivel superior de interés, un objeto HLSConfig especifica una lista de métodos de síntesis y sus argumentos. Este objeto puede pasarse a HighLevelSynthesis transpiler pass o especificado como parámetro hls_config en transpile().

    Como ejemplo, supongamos que op_a y op_b son nombres de dos objetos de nivel superior, que op_a-objetos tienen dos métodos de síntesis default que no requiere ningún parámetro adicional y other con dos parámetros enteros opcionales option_1 y option_2, que op_b-objetos tienen un único método de síntesis default, y qc es un circuito cuántico que contiene op_a y op_b objetos. El siguiente fragmento de código:

    hls_config = HLSConfig(op_b=[("other", {"option_1": 7, "option_2": 4})])
    pm = PassManager([HighLevelSynthesis(hls_config=hls_config)])
    transpiled_qc = pm.run(qc)

    muestra cómo ejecutar el método de síntesis alternativo other para los objetos op_b, mientras se utilizan los métodos default para todos los demás objetos de alto nivel, incluidos los objetos op_a.

  • Añadidos nuevos métodos para ejecutar primitivas BaseSampler.run() y BaseEstimator.run(). Estos métodos se ejecutan de forma asíncrona y devuelven JobV1 que proporcionan un controlador de las ejecuciones. A estos nuevos métodos de ejecución se les pueden pasar QuantumCircuit (y observables para BaseEstimator) que no estén registrados en el constructor. Por ejemplo:

    estimator = Estimator()
    result = estimator.run(circuits, observables, parameter_values).result()

    Esto proporciona una alternativa al modelo de ejecución anterior (que ahora está obsoleto) para las funciones BaseSampler y BaseEstimator que tomaban todas las entradas a través del constructor y llamaban al objeto primitivo con la combinación de esos parámetros de entrada para utilizarlos en la ejecución.

  • Se ha añadido la opción shots para las implementaciones de referencia de las primitivas. Los números aleatorios pueden fijarse dando a seed_primitive. Por ejemplo:

    from qiskit.primitives import Sampler
    from qiskit import QuantumCircuit
    
    bell = QuantumCircuit(2)
    bell.h(0)
    bell.cx(0, 1)
    bell.measure_all()
    
    with Sampler(circuits=[bell]) as sampler:
        result = sampler(circuits=[0], shots=1024, seed_primitive=15)
        print([q.binary_probabilities() for q in result.quasi_dists])
  • Los constructores de los módulos BaseSampler y BaseEstimator tienen un nuevo argumento opcional, options , que se utiliza para establecer los valores por defecto de las opciones expuestas a través del atributo options atributo.

  • Se ha añadido la clase PVQD al marco de evolución temporal en qiskit.algorithms. Esta clase implementa el algoritmo de Dinámica Cuántica Variacional proyectada (p-VQD) Barison et al..

    En cada paso de tiempo, este algoritmo calcula el siguiente estado con una fórmula Trotter y lo proyecta en una forma variacional. La proyección se determina maximizando la fidelidad del estado evolucionado por Trotter y el ansatz, utilizando una rutina de optimización clásica.

    import numpy as np
    
    from qiskit.algorithms.state_fidelities import ComputeUncompute
    from qiskit.algorithms.evolvers import EvolutionProblem
    from qiskit.algorithms.time_evolvers.pvqd import PVQD
    from qiskit.primitives import Estimator, Sampler
    from qiskit import BasicAer
    from qiskit.circuit.library import EfficientSU2
    from qiskit.quantum_info import Pauli, SparsePauliOp
    from qiskit.algorithms.optimizers import L_BFGS_B
    
    sampler = Sampler()
    fidelity = ComputeUncompute(sampler)
    estimator = Estimator()
    hamiltonian = 0.1 * SparsePauliOp([Pauli("ZZ"), Pauli("IX"), Pauli("XI")])
    observable = Pauli("ZZ")
    ansatz = EfficientSU2(2, reps=1)
    initial_parameters = np.zeros(ansatz.num_parameters)
    
    time = 1
    optimizer = L_BFGS_B()
    
    # setup the algorithm
    pvqd = PVQD(
        fidelity,
        ansatz,
        initial_parameters,
        estimator,
        num_timesteps=100,
        optimizer=optimizer,
    )
    
    # specify the evolution problem
    problem = EvolutionProblem(
        hamiltonian, time, aux_operators=[hamiltonian, observable]
    )
    
    # and evolve!
    result = pvqd.evolve(problem)
  • El método estático QNSPSA.get_fidelity() static admite ahora un argumento opcional sampler que se utiliza para proporcionar una implementación de la interfaz BaseSampler (como Sampler, BackendSampler, o cualquier implementación de proveedores como las presentes en qiskit-ibm-runtime y qiskit-aer) para calcular la fidelidad de un QuantumCircuit. Por ejemplo:

    from qiskit.primitives import Sampler
    from qiskit.algorithms.optimizers import QNSPSA
    
    fidelity = QNSPSA.get_fidelity(my_circuit, Sampler())
  • Añadido un nuevo argumento de palabra clave sampler a los constructores de las clases de estimación de fase:

    Este argumento se utiliza para proporcionar una implementación de la interfaz BaseSampler como Sampler, BackendSamplero cualquier implementación de proveedores como las presentes en qiskit-ibm-runtime y qiskit-aer.

    Por ejemplo:

    from qiskit.primitives import Sampler
    from qiskit.algorithms.phase_estimators import HamiltonianPhaseEstimation
    from qiskit.synthesis import MatrixExponential
    from qiskit.quantum_info import SparsePauliOp
    from qiskit.opflow import PauliSumOp
    
    
    sampler = Sampler()
    num_evaluation_qubits = 6
    phase_est = HamiltonianPhaseEstimation(
        num_evaluation_qubits=num_evaluation_qubits, sampler=sampler
    )
    
    hamiltonian = PauliSumOp(SparsePauliOp.from_list([("X", 0.5), ("Y", 0.6), ("I", 0.7)]))
    result = phase_est.estimate(
        hamiltonian=hamiltonian,
        state_preparation=None,
        evolution=MatrixExponential(),
        bound=1.05,
    )
  • El SabreSwap ha mejorado significativamente el rendimiento en tiempo de ejecución gracias a la reescritura del algoritmo en Rust.

  • Subclases de pulso simbólico Gaussian, GaussianSquare, Drag y Constant se han actualizado para instanciar SymbolicPulse en lugar de la propia subclase. Todos los objetos paramétricos de pulso en los programas de pulso deben ser instancias simbólicas de pulso, porque la subclase ya no es necesaria. Tenga en cuenta que SymbolicPulse puede identificar de forma unívoca un sobre concreto con el objeto de expresión simbólica definido en SymbolicPulse.envelope.

  • Añadida una nueva función, sampled_expectation_value()que permite calcular los valores de las expectativas de los operadores diagonales a partir de distribuciones como Counts y QuasiDistribution. Los operadores válidos para utilizar con esta función son: str, Pauli, PauliOp, PauliSumOpy SparsePauliOp.

  • A SamplingVQE optimizada para hamiltonianos diagonales y aprovecha la primitiva sampler . A QAOA clase que subclase SamplingVQE.

    Para utilizar la nueva SamplingVQE con una primitiva de referencia, se puede hacer, por ejemplo:

    from qiskit.algorithms.minimum_eigensolvers import SamplingVQE
    from qiskit.algorithms.optimizers import SLSQP
    from qiskit.circuit.library import TwoLocal
    from qiskit.primitives import Sampler
    from qiskit.opflow import PauliSumOp
    from qiskit.quantum_info import SparsePauliOp
    
    operator = PauliSumOp(SparsePauliOp(["ZZ", "IZ", "II"], coeffs=[1, -0.5, 0.12]))
    
    sampler = Sampler()
    ansatz = TwoLocal(rotation_blocks=["ry", "rz"], entanglement_blocks="cz")
    optimizer = SLSQP()
    
    sampling_vqe = SamplingVQE(sampler, ansatz, optimizer)
    result = sampling_vqe.compute_minimum_eigenvalue(operator)
    eigenvalue = result.eigenvalue

    Nótese que los operadores auxiliares evaluados se obtienen ahora a través del campo aux_operators_evaluated sobre los resultados. Consistirá en una lista o dict de tuplas que contendrán los valores de expectativa de estos operadores, así como los metadatos de ejecución primitiva. aux_operator_eigenvalues ya no es un campo válido.

  • Se ha añadido un nuevo argumento de palabra clave atol al método SparsePauliOp.equiv() para ajustar la tolerancia de la comprobación de equivalencia,

  • Se ha introducido una nueva interfaz de complemento para las etapas del transpilador que se utiliza para habilitar objetos alternativos PassManager objetos de un paquete externo en una etapa concreta como parte de transpile() o la StagedPassManager salida de generate_preset_pass_manager(), level_0_pass_manager(), level_1_pass_manager(), level_2_pass_manager()y level_3_pass_manager(). Los usuarios pueden seleccionar un plugin para utilizar en una etapa de transpilador con los argumentos de palabra clave init_method, layout_method, routing_method, translation_method, optimization_method, y scheduling_method en transpile() y generate_preset_pass_manager(). Puede encontrar una lista completa de los nombres de los plugins instalados actualmente con la función list_stage_plugins() función. Para crear plugins, consulte la documentación del módulo qiskit.transpiler.preset_passmanagers.plugin que incluye una guía para escribir plugins de escenario.

  • El transpile() tiene dos nuevos argumentos de palabra clave, init_method y optimization_method que se utilizan para especificar plugins alternativos a utilizar para las etapas init y optimization respectivamente.

  • La clase PassManagerConfig tiene 2 nuevos atributos, init_method y optimization_method junto con argumentos de palabras clave coincidentes en los métodos constructores. Representan los plugins init y optimization especificados por el usuario que se utilizarán para la compilación.

  • Se añade la clase SteppableOptimizer clase se añade. Permite perfore las optimizaciones clásicas paso a paso utilizando el step() método. Estos optimizadores implementan la interfaz "ask and tell" que (opcionalmente) permite calcular manualmente las evaluaciones de funciones o gradientes necesarias e introducirlas de nuevo en el optimizador. Para más información sobre esta interfaz, consulte: interfaz ask and tell. Un caso de uso muy sencillo en el que el usuario puede querer hacer la optimización paso a paso es para la lectura:

    import random
    import numpy as np
    from qiskit.algorithms.optimizers import GradientDescent
    
    def objective(x):
          return (np.linalg.norm(x) - 1) ** 2
    
    def grad(x):
          return 2 * (np.linalg.norm(x) - 1) * x / np.linalg.norm(x)
    
    
    initial_point = np.random.normal(0, 1, size=(100,))
    
    optimizer = GradientDescent(maxiter=20)
    optimizer.start(x0=initial_point, fun=objective, jac=grad)
    
    for _ in range(maxiter):
        state = optimizer.state
        # Here you can manually read out anything from the optimizer state.
        optimizer.step()
    
    result = optimizer.create_result()

    Un caso más complejo sería la gestión de errores. Imagina que la función que estás evaluando tiene una probabilidad aleatoria de fallar. En este caso, puede detectar el error y volver a ejecutar la función hasta que obtenga el resultado deseado antes de continuar con el proceso de optimización. En este caso se utilizaría la interfaz preguntar y decir.

    import random
    import numpy as np
    from qiskit.algorithms.optimizers import GradientDescent
    
    def objective(x):
        if random.choice([True, False]):
            return None
        else:
            return (np.linalg.norm(x) - 1) ** 2
    
    def grad(x):
        if random.choice([True, False]):
            return None
        else:
            return 2 * (np.linalg.norm(x) - 1) * x / np.linalg.norm(x)
    
    
    initial_point = np.random.normal(0, 1, size=(100,))
    
    optimizer = GradientDescent(maxiter=20)
    optimizer.start(x0=initial_point, fun=objective, jac=grad)
    
    while optimizer.continue_condition():
        ask_data = optimizer.ask()
        evaluated_gradient = None
    
        while evaluated_gradient is None:
            evaluated_gradient = grad(ask_data.x_center)
            optimizer.state.njev += 1
    
        optmizer.state.nit += 1
    
        cf  = TellData(eval_jac=evaluated_gradient)
        optimizer.tell(ask_data=ask_data, tell_data=tell_data)
    
    result = optimizer.create_result()

    Transición de GradientDescent para que sea una subclase de SteppableOptimizer.

  • El método subset_fitter se añade a la clase TensoredMeasFitter clase. La aplicación se limita a patrones de mitigación en los que cada qubit se mitiga individualmente, por ejemplo [[0], [1], [2]]. Sin embargo, este es el caso más extendido. Permite que el TensoredMeasFitter en los casos en que el orden numérico de los qubits físicos no coincide con el índice del bit clásico.

  • Las operaciones de flujo de control ahora se admiten a través del transpilador en los niveles de optimización 0 y 1 (por ejemplo, llamar a transpile() o generate_preset_pass_manager() con el argumento optimization_level=1). Ahora se puede construir un circuito como

    from qiskit import QuantumCircuit
    
    qc = QuantumCircuit(2, 1)
    qc.h(0)
    qc.measure(0, 0)
    with qc.if_test((0, True)) as else_:
      qc.x(1)
    with else_:
      qc.y(1)

    y transpilar esto con éxito, como por:

    from qiskit import transpile
    from qiskit_aer import AerSimulator
    
    backend = AerSimulator(method="statevector")
    transpiled = transpile(qc, backend)

    Los valores disponibles para el argumento de palabra clave layout_method son "trivial" y "denso". Para routing_method, están disponibles "stochastic" y "none". La traducción (translation_method) puede hacerse con "translator" o "unroller". Los niveles de optimización 2 y 3 aún no son compatibles con el flujo de control, ni tampoco lo es la programación de circuitos (es decir, proporcionar un valor a scheduling_method), aunque tenemos la intención de ampliar el soporte para estos, y los otros métodos de diseño, enrutamiento y traducción en versiones posteriores de Qiskit Terra.

    Para que la transpilación con operaciones de flujo de control tenga éxito con un backend, éste debe tener las operaciones de flujo de control necesarias en su base declarada. Qiskit Aer, por ejemplo, lo hace. Si simplemente desea probar este tipo de transpilaciones, considere la posibilidad de sustituir el argumento basis_gates por transpile().

  • Los siguientes pases del transpilador han sido todos enseñados para entender las construcciones de flujo de control en forma de ControlFlowOp instrucciones en un circuito:


    Relacionado con el diseño


    Relacionado con el enrutamiento


    Relacionado con la traducción


    Relacionado con la optimización

    Estos pases se utilizan sobre todo a través de los gestores de pases predefinidos (los utilizados internamente por transpile() y generate_preset_pass_manager()), pero también están disponibles para otros usos. Estos pases recurrirán ahora a operaciones de flujo de control cuando proceda, actualizando o analizando los bloques internos.

  • Se ha añadido una nueva TrotterQRTE que implementa la interfaz RealTimeEvolver que utiliza un qiskit.primitives.BaseEstimator para realizar el cálculo. Esta nueva clase sustituye a la clase qiskit.algorithms.TrotterQRTE (que será obsoleta y posteriormente eliminada en futuras versiones) que utilizaba una clase Backend o QuantumInstance para realizar el cálculo.

  • DAGCircuit.substitute_node_with_dag() ahora toma propagate_condition como argumento de palabra clave. Por defecto es True, que era el comportamiento anterior, y copia cualquier condición en el nodo a reemplazar en cada nodo de operación en el reemplazo. Si se establece en False, la condición no se copiará, lo que permite sustituir un nodo condicional por un sub-DAG que ya implemente fielmente la condición.

  • DAGCircuit.substitute_node_with_dag() ahora puede tomar un mapeo para su parámetro wires así como una secuencia. La asignación debe asignar los bits del DAG de sustitución a los bits del DAG en el que se inserta. Esto permite un estilo de construcción más fácil para los llamadores cuando el nodo de entrada tiene tanto bits clásicos como una condición, y el DAG de reemplazo puede usarlos fuera de orden.

  • Se ha añadido el paquete qiskit.algorithms.minimum_eigensolvers para incluir interfaces para algoritmos con primitivas. VQE se ha refactorizado en esta implementación para aprovechar las primitivas.

    Para utilizar la nueva implementación con una primitiva de referencia, se puede hacer, por ejemplo:

    from qiskit.algorithms.minimum_eigensolvers import VQE
    from qiskit.algorithms.optimizers import SLSQP
    from qiskit.circuit.library import TwoLocal
    from qiskit.primitives import Estimator
    from qiskit.quantum_info import SparsePauliOp
    
    h2_op = SparsePauliOp(
        ["II", "IZ", "ZI", "ZZ", "XX"],
        coeffs=[
            -1.052373245772859,
            0.39793742484318045,
            -0.39793742484318045,
            -0.01128010425623538,
            0.18093119978423156,
        ],
    )
    
    estimator = Estimator()
    ansatz = TwoLocal(rotation_blocks=["ry", "rz"], entanglement_blocks="cz")
    optimizer = SLSQP()
    
    vqe = VQE(estimator, ansatz, optimizer)
    result = vqe.compute_minimum_eigenvalue(h2_op)
    eigenvalue = result.eigenvalue

    Nótese que los operadores auxiliares evaluados se obtienen ahora a través del campo aux_operators_evaluated sobre los resultados. Consistirá en una lista o dict de tuplas que contendrán los valores de expectativa de estos operadores, así como los metadatos de ejecución primitiva. aux_operator_eigenvalues ya no es un campo válido.

Notas de actualización

  • Para Target que sólo contienen operaciones de 2 qubits definidas globalmente sin ningún tipo de conectividad, el resultado del método Target.build_coupling_map() devolverá None en lugar de un objeto CouplingMap que contiene num_qubits nodos y ninguna arista. Este cambio se realizó para reflejar mejor las restricciones de conectividad reales del Target porque en este caso no hay restricciones de conectividad en el backend modelado por el modelo Targety no una falta de conectividad. Si por alguna razón desea el comportamiento anterior, puede reproducirlo comprobando si hay un retorno None y construyendo manualmente un mapa de acoplamiento, por ejemplo:

    from qiskit.transpiler import Target, CouplingMap
    from qiskit.circuit.library import CXGate
    
    target = Target(num_qubits=3)
    target.add_instruction(CXGate())
    cmap = target.build_coupling_map()
    if cmap is None:
        cmap = CouplingMap()
        for i in range(target.num_qubits):
            cmap.add_physical_qubit(i)
  • El valor por defecto para el argumento de la palabra clave entanglement en el constructor de los objetos RealAmplitudes y EfficientSU2 ha cambiado de "full" a "reverse_linear". Este cambio se hizo porque el circuito de salida es equivalente pero utiliza sólo n1n-1 en lugar de n(n1)2\frac{n(n-1)}{2} CXGate puertas. Si desea el valor predeterminado anterior, puede establecer explícitamente entanglement="full" al llamar a cualquiera de los constructores.

  • Se ha añadido una comprobación de validación a BaseSampler.run(). Genera un error si no hay bit clásico.

  • Se ha mejorado el comportamiento de la call() se ha mejorado. Cuando una instancia ScheduleBlock instancia es llamada por este método, éste crea internamente una Reference en el contexto actual, e inmediatamente asigna el programa llamado a la referencia. Por lo tanto, la instrucción Call instrucción ya no se genera. Junto con este cambio, se prohíbe llamar a diferentes bloques con el mismo argumento name . Dicha operación dará lugar a un error.

  • Para la mayoría de las arquitecturas a partir de la siguiente versión de Qiskit Terra, 0.23, el paquete tweedledum se convertirá en una dependencia opcional, en lugar de un requisito. Esto lo utilizan actualmente algunas funciones clásicas de oráculo de fase. Si su aplicación o biblioteca necesita esta funcionalidad, puede prepararse añadiendo inmediatamente tweedledum a las dependencias de su paquete.

    tweedledum ya no es un requisito en macOS arm64 ( M1 ) con efecto inmediato en Qiskit Terra 0.22. Esto se debe a que las ruedas proporcionadas para esta plataforma están rotas, y la construcción desde el sdist no es fiable para la mayoría de la gente. Si instala manualmente una versión operativa de tweedledum, toda la funcionalidad dependiente seguirá funcionando.

  • El atributo ._layout del objeto QuantumCircuit ha pasado de almacenar un objeto Layout a almacenar una clase de datos con 2 atributos, initial_layout que contiene un objeto Layout para la disposición inicial establecida durante la compilación y input_qubit_mapping que contiene un diccionario que asigna qubits a índices de posición en el circuito original. Este cambio era necesario para proporcionar toda la información para que un circuito post-transpilado sea capaz de invertir completamente la permutación causada por el trazado inicial en todas las situaciones. Aunque este atributo es privado y no debe ser utilizado externamente, es la única manera de rastrear el diseño inicial a través de transpile() por lo que el cambio se documenta en caso de que confíes en él. Si tienes algún caso de uso para el atributo _layout que no esté contemplado en la API de Qiskit, abre una incidencia para que podamos solucionar esta carencia.

  • Los constructores para SetPhase, ShiftPhase, SetFrequencyy ShiftFrequency lanzarán un error PulseError si el valor introducido mediante el argumento channel no es una instancia de PulseChannel. Este cambio se ha realizado para validar que la entrada a los constructores es válida, ya que las instrucciones sólo son válidas para canales de impulsos y no para otros tipos de canales.

  • La función plot_histogram() ha sido modificada para devolver un histograma real de valores discretos. El comportamiento anterior de la función era, a pesar del nombre, generar realmente una visualización de la distribución de la entrada. Debido a esta disparidad entre el nombre de la función y el comportamiento, el comportamiento de la función se ha cambiado para que ahora genere un histograma adecuado de datos discretos. Si desea conservar el comportamiento anterior de trazar una distribución de probabilidad de los datos de recuento, puede aprovechar la función plot_distribution() para generar un gráfico equivalente. Por ejemplo, el comportamiento anterior de plot_histogram({'00': 512, '11': 500}) se puede recrear con:

    from qiskit.visualization import plot_distribution
    import matplotlib.pyplot as plt
    
    ax = plt.subplot()
    plot_distribution({'00': 512, '11': 500}, ax=ax)
    ax.set_ylabel('Probabilities')
  • Se han eliminado los contextos qiskit.pulse.builder inline y pad . Se eliminaron por primera vez en Terra 0.18.0 (julio de 2021). No hay reemplazo para inline; uno puede simplemente escribir los pulsos en el ámbito de aplicación que contiene. El gestor de contextos pad no tiene ningún efecto desde que fue obsoleto.

  • La salida del SabreSwap transpiler pass (incluyendo cuando optimization_level=3 o routing_method o layout_method se establecen en 'sabre' al llamar a transpile()) con un valor de semilla fijo puede 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 SabreSwap 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.

  • El comportamiento de Layout.add() cuando no se especifica physical_bit ha cambiado con respecto a versiones anteriores. En versiones anteriores, se añadía un nuevo bit físico en función de la longitud del Layout objeto. Por ejemplo, si tuviera un Layout con los bits físicos 1 y 3, las sucesivas llamadas a add() añadiría los bits físicos 2, 4, 5, 6, etc. Si los bits físicos fueran 2 y 3, las llamadas sucesivas sumarían 4, 5, 6, 7, etc. Esto ha cambiado para que en su lugar Layout.add() añadirá primero los bits físicos que falten entre 0 y el bit físico máximo contenido en el archivo Layout. Así que para el ejemplo 1 y 3 ahora añade 0, 2, 4, 5 y para el ejemplo 2 y 3 añade 0, 1, 4, 5 al Layout. Este cambio se hizo tanto para aumentar la previsibilidad del resultado, como para corregir una clase de errores causados por el comportamiento inesperado. Como los bits físicos en un backend siempre son secuencias contiguas de 0 a nn añadir nuevos bits cuando todavía hay bits físicos sin usar podría potencialmente causar que el diseño utilice más bits de los disponibles en el backend. Si desea el comportamiento anterior, puede especificar manualmente el bit físico deseado al llamar a Layout.add().

  • El método obsoleto SparsePauliOp.table atributo ha sido eliminado. Originalmente estaba obsoleto en Qiskit Terra 0.19. En su lugar, debe utilizarse el método paulis() .

  • Se ha eliminado la posibilidad de devolver un PauliTable desde la función pauli_basis() se ha eliminado. Del mismo modo, el argumento pauli_list de la función pauli_basis() que se utilizaba para cambiar a un PauliList (ahora el único tipo de retorno). Esta funcionalidad quedó obsoleta en la versión de Qiskit Terra 0.19.

  • Los objetos backend falsos FakeJohannesburg, FakeJohannesburgV2, FakeAlmaden, FakeAlmadenV2, FakeSingaporey FakeSingaporeV2 ya no contienen las cargas útiles por defecto del pulso. Esto significa para las BackendV1 el método BackendV1.defaults() y la simulación de impulsos mediante BackendV1.run() ya no está disponible. Para las clases basadas en BackendV2 la propiedad calibration para instrucciones en la clase Target ya no se rellena. Este cambio se realizó porque estos sistemas tenían cargas útiles de impulsos predeterminados excesivamente grandes (en total ~50MB ) debido al uso de formas de onda muestreadas en lugar de definiciones de impulsos paramétricas. Estos tres archivos de carga útil ocuparon más del 50% del espacio en disco necesario para instalar qiskit-terra. Si se compara con el valor potencial de poder compilar con conocimiento de pulso o simular con pulso estos dispositivos retirados, el tamaño del archivo no merece la pena. Si necesitas aprovechar estas propiedades puedes aprovechar una versión anterior de Qiskit y aprovechar qpy para transferir circuitos de versiones anteriores de qiskit a la versión actual.

  • isinstance comprobar con clases de pulso Gaussian, GaussianSquare, Drag y Constant se invalidará porque estas subclases de pulsos ya no se instancian. Seguirán funcionando en Terra 0.22, pero debe comenzar la transición inmediatamente. En lugar de utilizar información de tipo, debería utilizarse SymbolicPulse.pulse_type . Se supone que es un identificador de cadena único para las envolventes de pulso, y podemos utilizar la igualdad de cadenas para investigar los tipos de pulso. Por ejemplo:

    from qiskit.pulse.library import Gaussian
    
    pulse = Gaussian(160, 0.1, 40)
    
    if isinstance(pulse, Gaussian):
      print("This is Gaussian pulse.")

    Este código debe actualizarse a

    from qiskit.pulse.library import Gaussian
    
    pulse = Gaussian(160, 0.1, 40)
    
    if pulse.pulse_type == "Gaussian":
      print("This is Gaussian pulse.")

    Por la misma razón, no se debe acceder a los atributos de clase como pulse.__class__.__name__ para obtener información sobre el tipo de pulso.

  • La excepción qiskit.exceptions.QiskitIndexError ha sido eliminada y ya no existe según el aviso de depreciación de qiskit-terra 0.18.0 (publicado el 12 de julio de 2021).

  • Se han eliminado los argumentos obsoletos epsilon y factr del constructor de la clase L_BFGS_B se han eliminado. Estos argumentos quedaron obsoletos en la versión 0.18.0 (publicada el 12 de julio de 2021). En su lugar se debe utilizar el argumento ftol , puede consultar la documentación de scipy sobre el optimizador para obtener más detalles sobre la relación entre estos argumentos.

  • Los gestores de paso preestablecidos para los niveles 1 y 2, que se utilizarán cuando optimization_level=1 o optimization_level=2 con transpile() o generate_preset_pass_manager() y la salida de level_1_pass_manager() y level_2_pass_manager()utilizarán ahora SabreLayout y SabreSwap por defecto en lugar de los anteriores DenseLayout y StochasticSwap. Este cambio se hizo para mejorar la calidad de salida del transpilador, la combinación de SabreLayout y SabreSwap suele dar lugar a que se inserten menos SwapGate objetos insertados en el circuito de salida. Si desea utilizar los pases anteriores por defecto puede configurar layout_method='dense' y routing_method='stochastic' en transpile() o generate_preset_pass_manager() para aprovechar DenseLayout y StochasticSwap respectivamente.

  • Se ha desactivado el uso implícito de approximation_degree!=1.0 por defecto en la función transpile() cuando se establece optimization_level=3 . El transpilador debería, por defecto, preservar la unitaridad de la entrada hasta transformaciones conocidas como permutaciones unilaterales y transformaciones de similitud. Esto se rompió por el uso previo de approximation_degree=None que conducía a resultados incorrectos en casos como la evolución Trotterizada con muchos pasos de tiempo donde los unitarios estaban siendo excesivamente aproximados conduciendo a resultados incorrectos. Se decidió que las transformaciones que rompen la equivalencia unitaria deben ser activadas explícitamente por el usuario. Si desea el comportamiento predeterminado anterior, en el que las instrucciones UnitaryGate sintetizadas se aproximan a las tasas de error de las instrucciones nativas del backend de destino, puede definir explícitamente approximation_degree=None al llamar a transpile() con optimization_level=3, por ejemplo:

    transpile(circuit, backend, approximation_degree=None, optimization_level=3)
  • Cambie el valor por defecto del número máximo de evaluaciones de función permitidas (maxfun) en L_BFGS_B de 1000 a 15000 para que coincida con el valor predeterminado de SciPy. Este número también coincide con el número de iteraciones por defecto (maxiter).

  • Actualizado ProbDistribution y QuasiDistribution para almacenar la información del número de bits si se dan cadenas de bits sin prefijo “0b”. ProbDistribution.binary_probabilities() y QuasiDistribution.binary_probabilities() utilizar el número de bits almacenado como valor por defecto del número de bits.

  • RZXCalibrationBuilder y RZXCalibrationBuilderNoEcho se han actualizado para omitir las puertas CX de estiramiento implementadas por secuencia de resonancia cruzada sin eco (ECR) para evitar la terminación del paso con errores inesperados. Estos pases toman un nuevo argumento verbose que controla si los pases avisan cuando esto ocurre. Si verbose=True está configurado, pass emite una advertencia al usuario cuando detecta una secuencia no ECR.

  • El módulo de visualización qiskit.visualization ha experimentado una reorganización interna. Esto no debería haber afectado a la interfaz pública, pero si estabas accediendo a alguna parte interna de los cajones del circuito, puede que ahora estén en lugares diferentes. Las únicas partes del módulo de visualización que se consideran públicas son los componentes que se documentan en esta documentación en línea.

Notas sobre características en desuso

  • Importar los nombres Int1, Int2, classical_function y BooleanExpression directamente de qiskit.circuit está obsoleta. Esto forma parte del movimiento para hacer de tweedledum una dependencia opcional en lugar de un requisito completo. En su lugar, debe importar estos nombres desde qiskit.circuit.classicalfunction.

  • Los módulos qiskit.algorithms.factorizers y qiskit.algorithms.linear_solvers están obsoletos y se eliminarán en una futura versión. Se sustituyen por tutoriales en el libro de texto Qiskit: Shor HHL

  • La dirección random_stabilizer_table() ha quedado obsoleta y se eliminará en una próxima versión. En su lugar, debe utilizarse la función random_pauli_list() .

  • La función del módulo de impulsos qiskit.pulse.utils.deprecated_functionality está obsoleta y se eliminará en una futura versión. Se trataba de una función principalmente interna. La misma funcionalidad la proporciona qiskit.utils.deprecate_function, que debería utilizarse en su lugar.

  • Se ha modificado el método de ejecución de las primitivas. Los métodos BaseSampler.__call__() y BaseEstimator.__call__() han quedado obsoletos. Por ejemplo:

    estimator = Estimator(...)
    result = estimator(circuits, observables, parameters)
    
    sampler = Sampler(...)
    result = sampler(circuits, observables, parameters)

    debe reescribirse como

    estimator = Estimator()
    result = estimator.run(circuits, observables, parameter_values).result()
    
    sampler = Sampler()
    result = sampler.run(circuits, parameter_values).result()

    El uso de primitivas como gestores de contexto está obsoleto. No todas las primitivas disponen de un gestor de contexto. Cuando está disponible (por ejemplo, en qiskit-ibm-runtime), el gestor de contexto de la sesión proporciona una funcionalidad equivalente.

    circuits observables y en el constructor ha quedado obsoleto. parameters circuits y observables pueden pasarse desde los métodos run . run no admiten parameters. Los usuarios deben recurrir a los valores de los parámetros por sí mismos.

  • El argumento no utilizado qubit_channel_mapping en el RZXCalibrationBuilder y RZXCalibrationBuilderNoEcho han quedado obsoletos y se eliminarán en una futura versión. Este argumento ya no se utiliza y no tiene ningún efecto sobre el funcionamiento de los pases.

Corrección de errores

  • Se ha solucionado un problema por el que Pauli.evolve() y PauliList.evolve() provocaba un error de tipo al evolucionar por ciertas puertas Clifford que modificaban la fase de Pauli. Corregido #8438

  • Se ha corregido un error en QuantumCircuit.initialize() y QuantumCircuit.prepare_state() que provocaba que no aceptaran un único Qubit como argumento para inicializar.

  • El método QuantumCircuit.while_loop() resolverá ahora las referencias clásicas a bits en su condición de la misma forma que QuantumCircuit.if_test() y InstructionSet.c_if() lo hacen.

  • Los métodos DAGCircuit métodos depth(), size() y DAGCircuit.count_ops() antes devolvían silenciosamente resultados que tenían poco o ningún significado si el flujo de control estaba presente en el circuito. En depth() y size() lanzarán ahora correctamente un error en estos casos, pero tienen un nuevo argumento de palabra clave recurse para permitir el cálculo de un valor proxy, mientras que los métodos count_ops() recurrirá por defecto a los bloques y contará las operaciones dentro de ellos.

  • Se ha corregido un problema en el DenseLayout transpilador, por el que cualquier objeto Qubit sueltos (es decir, que no formaban parte de un objeto QuantumRegister) que formaban parte de QuantumCircuit no se incluían en la salida Layout generada por el pase.

  • El método constructor Operator.from_circuit() ha sido actualizado para que pueda manejar la salida de diseño de transpile() e invierta correctamente la permutación de qubits causada por la disposición en todos los casos. Antes, si su circuito transpilado utilizaba objetos sueltos Qubit objetos, varios QuantumRegister o un único objeto QuantumRegister con un nombre distinto de "q" el constructor habría fallado al crear un Operator del circuito. Corregido #8800.

  • Se ha corregido un error por el que fallaba la descomposición de una instrucción con un qubit y un bit clásico que contenía una única puerta cuántica. Ahora lo siguiente se descompone como se esperaba:

    block = QuantumCircuit(1, 1)
    block.h(0)
    
    circuit = QuantumCircuit(1, 1)
    circuit.append(block, [0], [0])
    
    decomposed = circuit.decompose()
  • Corregida la inicialización de la matriz simpléctica vacía en from_symplectic() en PauliList por ejemplo:

    from qiskit.quantum_info.operators import PauliList
    
    x = np.array([], dtype=bool).reshape((1,0))
    z = np.array([], dtype=bool).reshape((1,0))
    pauli_list = PauliList.from_symplectic(x, z)
  • Solucionar un problema en el GateDirection para el archivo CZGate. La puerta CZ es simétrica, por lo que se permite voltear los argumentos de los qubits para que coincidan con el mapa de acoplamiento dirigido.

  • Se han solucionado problemas con el método DerivativeBase.gradient_wrapper() cuando se reutiliza un muestreador de circuitos entre las llamadas y se vinculan parámetros anidados.

  • Se ha solucionado un problema en los cajones de los circuitos mpl y latex , cuando al establecer la opción idle_wires en Falso cuando había un barrier en el circuito provocaba el fallo de los cajones. Corregido #8313

  • Se ha corregido un problema en circuit_drawer() y QuantumCircuit.draw() con el método latex por el que se producía un error OSError en sistemas cuyos directorios temporales (por ejemplo, /tmp) se encuentran en un sistema de archivos diferente del directorio de trabajo. Correcciones #8542

  • Anidar un FlowController dentro de otro en un PassManager antes podía hacer que algunos pases del transpilador se "olvidaran" durante la transpilación, si los pases devolvían un nuevo DAGCircuit en lugar de mutar su entrada. Los sitios FlowControllerafectarán ahora correctamente a la transpilación.

  • Comparando QuantumCircuit y DAGCircuits para la igualdad era previamente no determinista si los circuitos contenían más de un registro del mismo tipo (por ejemplo, dos o más QuantumRegisters), devolviendo a veces False incluso si los registros eran idénticos. Ahora comparará correctamente circuitos con múltiples registros.

  • El exportador OpenQASM 2 (QuantumCircuit.qasm()) definirá ahora correctamente los parámetros de los qubits para las operaciones UnitaryGate que no afectan a todos los qubits sobre los que se definen. Corregido #8224.

  • Se han corregido dos errores en el cajón del circuito text . Estos aparecían cuando vertical_compression estaba configurado como medium, que es el valor por defecto. El primero a veces hacía que el texto sobrescribiera otro texto o puertas, y el segundo a veces hacía que se rompieran las conexiones entre una puerta y sus controles. Ver #8588.

  • Se ha solucionado un problema con el UnitarySynthesis por el que un circuito con puertas de 1 qubit y una entrada Target fallaba a veces en lugar de procesar el circuito como se esperaba.

  • El transpilador GateDirection respetará los valores disponibles para los parámetros de las puertas cuando se manipulen puertas parametrizadas con un parámetro Target.

  • Se ha corregido un problema en la clase SNOBFIT cuando se producía un error interno durante la ejecución del método minimize() si no se especificaban límites de entrada. Esto se comprueba ahora en el momento de la llamada para que aparezca rápidamente un ValueError si faltan los límites requeridos en la minimize() llamada. Correcciones #8580

  • Se ha corregido un problema en la llamada de salida del método get_energy_evaluation() de la clase VQD ahora llamará correctamente al callback especificado cuando se ejecute. Anteriormente, la llamada de retorno no se utilizaba correctamente en este caso. Corregido #8575

  • Se ha solucionado un problema cuando se utilizaba circuit_drawer() con reverse_bits=True en un circuito sin bits clásicos que provocaba la emisión de una advertencia potencialmente confusa sobre cregbundle . Corregido #8690

  • El exportador OpenQASM 3 (qiskit.qasm3) tratará ahora correctamente los módulos integrados de OpenQASM (como reset y measure) que tengan una condición clásica aplicada por c_if(). Antes se habría ignorado esta condición.

  • Se ha solucionado un problema con la clase SPSA que internamente intentaba agrupar los trabajos en lotes de tamaño uniforme, lo que provocaba una excepción si no era posible crear lotes uniformes. Esto se ha corregido para que siempre se procesen correctamente los trabajos por lotes aunque no tengan el mismo tamaño.

  • Se ha corregido el comportamiento de Layout.add() que podía provocar que la salida de transpile() no fuera válida y contuviera más Qubits de los disponibles en el backend de destino. Arreglado: #8667

  • Se ha corregido un problema con la función state_to_latex() : si se pasaba una cadena de texto látex al argumento opcional prefix de la función, se producía un error. Corregido #8460

  • La función state_to_latex() no producía LaTeX válida en presencia de valores cercanos a cero, lo que provocaba errores cuando se llamaba a state_drawer() . Corregido #8169.

  • GradientDescent ahora contará correctamente el número de iteraciones, evaluaciones de función y evaluaciones de gradiente. Además, la documentación indica ahora correctamente que el gradiente se aproxima mediante un método de diferencias finitas hacia delante.

  • Corrección de advertencias de desaprobación en NaturalGradientque ahora utiliza StandardScaler para escalar los datos antes de ajustar el modelo si el parámetro normalize se establece en True.

Aer 0.11.0

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.