Notas de la versión de Qiskit SDK 2.1
2.1.2
Preludio
Qiskit 2.1.2 es un pequeño parche que corrige varios errores encontrados en la serie 2.1.
Corrección de errores
-
En Qiskit 2.1.0 el
VF2PostLayouttranspiler pass se añadió a la etapaoptimizationdel gestor de pases predefinidos cuandooptimization_level=3. Sin embargo, la salida del paso nunca se aplicó al circuito. Esta versión elimina el pase de la etapaoptimizationdel gestor de pases predefinidos para ahorrar costes de ejecución. En Qiskit 2.2.0 el pase formará parte de la etapaoptimizationy la salida se aplicará si el pase encuentra un diseño mejor. -
Se ha solucionado un problema en el
VF2Layoutdonde incluso con un conjunto de semillas fijo la salida del pase era potencialmente no determinista; específicamente si el circuito de entrada tenía qubits activos que sólo contenían operaciones de qubit único. Corregido #14729 -
Se ha corregido un error en
PassManager.run()por el que no se invocaba la funcióncallbackcuando se ejecutaba con varios circuitos. Ahora la llamada de retorno se activa correctamente para cada pasada en cada circuito, incluso en ejecución paralela. -
Los pases de transpilador integrados que establecen la propiedad
final_layoutahora gestionarán correctamente la actualización de este campo si ya estaba establecido. Esto puede observarse como el métodoTranspileLayout.routing_permutationdevuelve ahora una permutación correcta después de ejecutar más de una pasada que establecefinal_layout.Esto no afectó a las llamadas normales a
transpile()ogenerate_preset_pass_manager()usando los plugins incorporados de Qiskit; ningún pipeline construido de esta forma intentaría establecerfinal_layoutmás de una vez. -
Se ha corregido un error en
Target.instruction_supported()por el que se omitía la comprobación del orden de los qubits de la instrucción cuando se llamaba al método con argumentosoperation_nameyparametersque coincidían con una instrucción existente. -
Se ha corregido un error de corrección al exportar circuitos con instrucciones de retardo utilizando
psunidades a QASM3. -
Corregido un caso extremo en la visualización del
QFTcircuito. Anteriormente, cuando se llamaba aQFT.inverse()y se modificaban los atributos del circuito QFT, el nombre del QFT aparecía como"IQFT_dg". Esto era incorrecto, y ahora muestra correctamente"IQFT". Corregido #14758. -
Se ha corregido una fuga de memoria en la coordinación del uso de
qk_circuit_get_instructionyqk_circuit_instruction_clear. -
Aclarado el mensaje de error para versiones no válidas especificadas en
qpy.dump()para que sea más fácil actuar en consecuencia. -
Se ha corregido un problema con la función
generate_preset_pass_manager()por el que ignoraba incorrectamente los datos de restricciones de temporización contenidos en un objetoTargetcuando el argumentobackendno estaba definido. Corregido #14329 -
Se ha corregido un error en
SparsePauliOp.simplify()por el que el método eliminaba los términos de Pauli basándose en las magnitudes de sus coeficientes antes de combinar los duplicados. Esto provocaba un comportamiento incorrecto en dos casos extremos clave:- Cuando varios términos de Pauli idénticos tenían coeficientes pequeños que individualmente estaban por debajo del umbral de simplificación pero cuya suma superaba el umbral, esos términos se eliminaban incorrectamente.
- Cuando múltiples términos de Pauli idénticos tenían coeficientes por encima del umbral pero sumados a casi cero, se mantenían incorrectamente.
Ver #14194 para más detalles.
2.1.1
Preludio
Qiskit 2.1.1 es un pequeño parche que corrige varios errores encontrados en la serie 2.1.
Corrección de errores
-
Se ha corregido un error en la
DAGOpNodecomprobación de igualdad, por el que la comparación de dosDAGOpNodeque contienen una instrucciónBoxOpinstrucción. Anteriormente, el atributoBoxOp.unitno se tenía en cuenta como parte de la comprobación de igualdad, lo que podía dar lugar a que dos nodos desiguales se evaluaran como iguales. -
Corregido el aviso de obsoleto para Python 3.9 para que se identifique correctamente como causado por código de usuario al importar Qiskit. Anteriormente, no se identificaba como causado por código de usuario, y esto significaba que los filtros de advertencia predeterminados de Python no mostraban la advertencia al usuario.
-
Se ha corregido el comportamiento del argumento
max_trialsparaVF2Layoutcuando se establece enNoneo en un número negativo. El pase estaba documentado como limitando la búsqueda a basarse en el tamaño del circuito o del objetivo si la opción se establecía enNone, y como aceptando valores negativos para especificar una búsqueda sin límites. Sin embargo, en 2.1.0 este comportamiento se modificó incorrectamente de modo queNoneejecutaba una búsqueda no limitada y el uso de un número negativo provocaba un error. Estos descuidos se han corregido para que el pase se comporte según lo documentado y sea coherente con las versiones anteriores. -
Solucionado un problema en los plugins de síntesis de alto nivel
MCXSynthesis1DirtyKG24yMCXSynthesis2DirtyKG24paraMCXGatedonde los plugins no consideraban los qubits auxiliares limpios disponibles como qubits auxiliares sucios disponibles. En particular, el complementoMCXSynthesis2DirtyKG24no se aplicaba cuando se disponía de un qubits auxiliar limpio y otro sucio. -
Se ha corregido una regresión de rendimiento al construir incrementalmente
ParameterExpressioncombinando un gran número de subexpresiones. Corregido #14653
2.1.0
Preludio
La versión de Qiskit v2.1 introduce varias mejoras importantes en áreas clave como la API de C, las capacidades del transpilador y la usabilidad de los circuitos cuánticos. Además, incluye muchas mejoras generales y correcciones de errores. Entre las principales destacan:
- Extensiones de la API de C: Basándose en el trabajo iniciado en la versión anterior, Qiskit v2.1 añade soporte para crear e interactuar con circuitos cuánticos a través de funciones de la API de C, soportando la adición de puertas estándar, instrucciones estándar y puertas unitarias. En esta versión también se ha añadido un conjunto de funciones C para construir y manipular un objeto
Targetcomo preparación para soportar un flujo de trabajo de transpilación completo basado en la API de C en la próxima versión. Además,QkComplex64se define ahora como una estructura, sirviendo como una representación independiente del compilador para números complejos cuando se trabaja con la API C de Qiskit. También se ha actualizado el archivo de cabecera de la API de C para que, en general, sea compatible para su uso nativo en C++.- Soporte del conjunto de bases Clifford+T: Ahora es posible transpilar circuitos para un objetivo con puertas Clifford+T. Si el conjunto de bases consiste sólo en puertas Clifford+T, Qiskit se asegura de que los pases apropiados para manejar estas puertas se añadan a los gestores de pases predefinidos. Este es un paso inicial hacia el apoyo a la transpilación para backends tolerantes a fallos.
- Mejoras para
BoxOp: Esta versión añade la posibilidad de adjuntar anotaciones personalizadas aBoxOpinstrucciones, apoyando aún más el concepto de declaraciones de caja de OpenQASM 3 en Qiskit. También incluye la serialización de anotaciones en los formatos QASM y QPY. Además, se ha añadido soporte para utilizar duraciones de estiramiento en las cajas.- Python 3.9 obsoleto: Python 3.9 es obsoleto a partir de Qiskit v2.1 y ya no será compatible con Qiskit v2.3.
Para más detalles sobre lo anterior y mucho más, consulte las notas de la versión que figuran a continuación y visite la documentación actualizada.
Características de la API C
-
La API C de Qiskit ( qiskit.h ) soporta ahora la construcción e interacción con Circuitos Cuánticos. La API C de circuitos se centra en el tipo opaco
QkCircuitque representa el circuito. El tipoQkCircuitpermite construir un circuito con cualquier elemento de circuito definido de forma nativa en el modelo de datos interno Rust de Qiskit paraQuantumCircuit. Actualmente incluye puertas estándar,Measure,Delay,Reset,BarrieryUnitaryGate. Las capacidades de los circuitos C API se ampliarán en futuras versiones a medida que se añada más del modelo de datos Qiskit de forma nativa al modelo de datos interno de Rust, lo que permitirá utilizarlo en la C API.Por ejemplo, puedes utilizar la API de C para construir un estado GHZ de 1000 qubits:
#include <qiskit.h> int main() { // Create an empty circuit with 1000 qubits and 1000 clbits QkCircuit *qc = qk_circuit_new(1000, 1000); // Add a Hadamard Gate on Qubit 0 uint32_t one_qubit[1] = {0,}; qk_circuit_gate(qc, QkGate_H, one_qubit, NULL); // The NULL pointer is for the parameter array. // Since Hadamard doesn't have parameters it // is never accessed. // Add the CX Gates: uint32_t qubits[2] = {0, 0}; uint32_t num_qubits = qk_circuit_num_qubits(qc); for (int i = 1; i<num_qubits; i++) { qubits[1] = i; qk_circuit_gate(qc, QkGate_CX, qubits, NULL); } // Add the measurements: uint32_t num_clbits = qk_circuit_num_clbits(qc); for (uint32_t i = 0; i<num_clbits; i++) { qk_circuit_measure(qc, i, i); } qk_circuit_free(qc); return 0; } -
La API C de Qiskit ( qiskit.h ) ahora soporta la construcción de un
Targetpara representar un objetivo de transpilación. Por ejemplo:#include <qiskit.h> #include <math.h> int main() { // Create a Target with 3 qubits QkTarget *target = qk_target_new(3); // Create a Target Entry for a CX Gate QkTargetEntry *cx_entry = qk_target_entry_new(QkGate_CX); // Define properties for CX between qubits (0, 1) with a duration of 1.93e-9 sec and error rate 3.17e-10. uint32_t qargs[2] = {0, 1}; qk_target_entry_add_property(cx_entry, qargs, 2, 1.93e-9, 3.17e-10); // Define properties for cx between qubits (1, 0) with a duration of 1.27e-9 sec and no error. uint32_t rev_qargs[2] = {1, 2}; qk_target_entry_add_property(cx_entry, rev_qargs, 2, 1.27e-9, NAN); // Add the cx entry to the target. QkExitCode result_cx = qk_target_add_instruction(target, cx_entry); // Add global ideal Y gate entry to the target QkExitCode result_y = qk_target_add_instruction(target, qk_target_entry_new(QkGate_Y)); // Create a Target entry for a Measurement with increasing duration and error as the qubit indices increase QkTargetEntry *measure = qk_target_entry_new_measure(); for (uint32_t i = 0; i< qk_target_num_qubits(target); i++) { uint32_t q[1] = {i}; qk_target_entry_add_property(measure, q, 1, 1e-6 * (i + 1), 1e-3 * (i + 1)); } QkExitCode result_measure = qk_target_add_instruction(target, measure); return 0; } -
Añadido soporte para consultar la información de la versión de Qiskit desde la API de C utilizando las siguientes macros:
QISKIT_VERSION_MAJORcontiene el número de versión principal.QISKIT_VERSION_MINORcontiene el número de versión menor.QISKIT_VERSION_PATCHcontiene el número de versión del parche.QISKIT_VERSION: Contiene una representación numérica de la información de la versión, que puede utilizarse para comparaciones.QISKIT_VERSION_NUMERIC(M,m,p): Una macro de tipo función que devuelve la versión " M.m.p " como valor numérico, que puede utilizarse para comparaciones.
Por ejemplo, para comprobar si la versión actual es al menos 2.1.0, puede utilizar:
if (QISKIT_VERSION >= QISKIT_VERSION_NUMERIC(2, 1, 0)) { // Code for version 2.1.0 or later } -
Habilitada la compatibilidad C++ para la API C. La cabecera generada permite ahora llamar directamente a objetos y funciones desde C++. Por ejemplo, un observable de 100 qubits con el término XYZ en los 3 primeros qubits puede construirse como
#include <iostream> #include <complex> #include <vector> #include <qiskit.h> int main() { uint32_t num_qubits = 100; // Use smart pointer with custom deleter to manage QkObs memory QkObs *obs = qk_obs_zero(num_qubits); // Construct the observable term std::complex<double> coeff_complex = 2.0; QkComplex64 coeff = qk_complex64_from_native(coeff_complex); std::vector<QkBitTerm> bit_terms = {QkBitTerm_X, QkBitTerm_Y, QkBitTerm_Z}; std::vector<uint32_t> indices = {0, 1, 2}; QkObsTerm term { .coeff = coeff, .len = bit_terms.size(), .bit_terms = bit_terms.data(), .indices = indices.data(), .num_qubits = num_qubits }; qk_obs_add_term(obs.get(), &term); // Print observable properties std::cout << "num_qubits: " << qk_obs_num_qubits(obs) << "\n"; std::cout << "num_terms: " << qk_obs_num_terms(obs) << "\n"; qk_obs_free(obs); return 0; }
Características de los circuitos
-
Se ha añadido una función
random_circuit_from_graph()que genera un circuito aleatorio que induce el mismo grafo de interacción que el especificado por interaction_graph.La probabilidad de extraer aleatoriamente una arista del grafo de interacción como una puerta de dos qubits puede ser establecida por el usuario en el atributo de peso de una arista en el grafo de interacción de entrada. Si el usuario no fija la probabilidad, cada arista se dibuja uniformemente. Es decir, cada puerta de dos qubits representada por una arista en el grafo de interacción tiene la misma probabilidad de ser añadida al circuito aleatorio. Si sólo se establece un subconjunto de probabilidades de arista, aparecerá
ValueError.En este ejemplo,
cp_mapes una lista de aristas con pesos arbitrarios.from qiskit.circuit.random.utils import random_circuit_from_graph import rustworkx as rx pydi_graph = rx.PyDiGraph() n_q = 5 cp_map = [(0, 1, 0.18), (1, 2, 0.15), (2, 3, 0.15), (3, 4, 0.22)] pydi_graph.extend_from_weighted_edge_list(cp_map) # cp_map can be passed in directly as interaction_graph qc = random_circuit_from_graph(interaction_graph = pydi_graph, min_2q_gate_per_edge = 1, max_operands = 2, measure = True, conditional = True, reset = True, seed = 0, insert_1q_oper = True, prob_conditional = 0.21, prob_reset = 0.1) qc.draw(output='mpl')
-
Se ha añadido un nuevo
QuantumCircuitmétodoQuantumCircuit.has_control_flow_op()para comprobar si unQuantumCircuitcontiene alguna operación de flujo de control. -
Un nuevo módulo
qiskit.circuit.annotationy objeto principalAnnotationse han añadido.Las anotaciones son una forma de etiquetar instrucciones (actualmente sólo
BoxOp) con datos locales, personalizados por el usuario. Estos datos están destinados a ser consumidos por pases de transpilador personalizados. Las anotaciones proporcionan una forma de adjuntar datos a instrucciones específicas, en lugar de utilizar el objeto global-contextPropertySetdurante la compilación.Todos los objetos
Annotationobjetos tienen un camponamespace. Esta clave de cadena se utiliza para búsquedas, para que los consumidores puedan saber si manejan una anotación en particular o no. Actualmente no existen métodos para consultar la semántica abstracta de unaAnnotationpero se espera que se amplíen en el futuro.Consulte
qiskit.circuit.annotationpara una discusión completa de las capacidades y casos de uso. -
BoxOp(creadas porQuantumCircuit.box()) se pueden anotar con instanciasAnnotationpersonalizadas. La igualdad de dos casillas depende de que las anotaciones sean iguales.Normalmente, esto se consigue pasando una lista de anotaciones como único argumento posicional cuando se utiliza
QuantumCircuit.box()en forma de gestor de contexto:from qiskit.circuit import annotation, QuantumCircuit class MyAnnotation(annotation.Annotation): namespace = "my.annotation" def __eq__(self, other): return isinstance(other, MyAnnotation) qc = QuantumCircuit() with qc.box([MyAnnotation()]): pass -
El método
UnitaryGate.control()utiliza ahora internamenteqs_decomposition()en lugar deIsometrypara la descomposición utilizada para definir el controlUnitaryGate. Este cambio reduce el número deCXGateutilizados en eldefinitionpara elControlledGateen aproximadamente 2x. -
Mejorada la síntesis de un multi-controlado
U1Gatepara que no crezca exponencialmente con el número de controles. -
El atributo
BoxOp.durationahora puede ser unexpr.Exprnodo de tipoDurationigual queDelay.duration. Esto incluye también el apoyoStretchdurante la duración de unBoxOp.
Características primitivas
-
Los estimadores PUB utilizados como entrada para
BaseEstimatorV2.run()pueden definirse ahora utilizando objetosSparseObservablepara el componente observable de PUB. Esto se suma a los tipos ya admitidos de:str,Pauli,SparsePauliOpy una correspondencia de los valoresstroPaulia los valores defloat. Sin embargo, si elSparseObservablecontiene proyectores, el soporte para manejar eso depende de la implementación de la primitiva. A partir de esta versión, las implementaciones en Qiskit (StatevectorEstimatoryBackendEstimatorV2),qiskit-ibm-runtime(qiskit_ibm_runtime.EstimatorV2), y Qiskit Aer's (qiskit_aer.primitives.EstimatorV2) aún no soportan observables proyectivos. Los observables proyectivos son aquellos que contienen los términos:0,1,+,-,r, ol. -
Añade soporte a la clase
DataBinpara hacerla serializable conpickle. Esto permite hacer elPrimitiveJobyPrimitiveResultserializable conpickletambién.
OpenQASM Características
-
qasm3.dump()yqasm3.dumps()tienen un nuevo argumentoannotation_handlers, que se utiliza para proporcionar instancias deannotation.OpenQASM3Serializeral proceso de exportación de OpenQASM 3, que puede serializar objetos personalizadosAnnotationa OpenQASM 3. -
Cuando se instala
qiskit_qasm3_import>=0.6.0,qasm3.load()yqasm3.loads()tienen un nuevo argumentoannotation_handlers, que se utiliza para proporcionar instancias deannotation.OpenQASM3Serializeral proceso de importación de OpenQASM 3, que puede deserializar objetos personalizadosAnnotationde OpenQASM 3. Este soporte se limita actualmente a las declaracionesbox, ya que es el único lugar donde Qiskit puede representar anotaciones en su modelo de datos.
Características de QPY
-
Añadida una nueva versión 15 del formato QPY que incluye soporte para los nuevos
Annotationobjetos, con soporte de serializadores y deserializadores externos. El formato permite que dichos serializadores sean de estado, y se asignan lugares seguros en el formato binario para los objetos de estado personalizados y las representaciones de anotación personalizadas. -
qpy.dump()yqpy.load()ahora tienen un argumento opcionalannotation_factories, que se utiliza para proporcionar funciones constructoras deannotation.QPYSerializerobjetos para manejarAnnotationsubclases. Estos deben ser suministrados por el usuario, de forma similar ametadata_serializer, ya que en general, Qiskit no puede conocer todos los posibles objetos definidos externamenteAnnotationdefinidos externamente. -
Se ha añadido una nueva función
get_qpy_version()al móduloqpymódulo. Esta función inspeccionará un archivo QPY y recuperará la versión de formato QPY utilizada en la carga útil. La versión se devuelve como un número entero, que puede utilizarse con fines de registro o depuración. ver #14201.
Características de la información cuántica
-
Se añade una nueva clase,
PauliLindbladMapque es una parametrización basada en Pauli de un subconjunto de mapas lineales de operadores multi-qubit, utilizados en aplicaciones de aprendizaje de ruido. Se espera que esta clase constituya la espina dorsal de algoritmos mejorados de aprendizaje del ruido y proporcione un control mejor y más eficaz de los modelos de ruido en futuras versiones de Qiskit. -
Introdujo el
QubitSparsePauliyQubitSparsePauliListque representan los mismos conceptos quePauliyPauliListrespectivamente, pero sólo almacenan términos no identitarios, de forma análoga aSparseObservable. Estas clases están pensadas principalmente para ser utilizadas con el nuevoPauliLindbladMap.
Características de síntesis
-
Se ha añadido un nuevo algoritmo de síntesis para
HalfAdderGateque no requiere qubits auxiliares y tiene mejor recuento de CX en comparación conadder_qft_d00(): -
Añadidas nuevas descomposiciones para
MCXGateutilizar ancillae limpia, mejorando la profundidad del circuito y la eficiencia:synth_mcx_1_clean_kg24()usando 1 qubit ancilla limpio adicionalsynth_mcx_1_dirty_kg24()usando 1 qubit ancilla sucio adicionalsynth_mcx_2_clean_kg24()usando 2 qubits auxiliares limpios adicionalessynth_mcx_2_dirty_kg24()usando 2 qubits auxiliares sucios adicionales
Ejemplo de uso:
from qiskit.synthesis.multi_controlled import synth_mcx_1_clean_kg24 n_ctrls = 10 qc = synth_mcx_1_clean_kg24(n_ctrls) qc.draw() -
Se ha mejorado la síntesis de puertas
CZGatese ha mejorado para reducir el número de compuertas sintetizadas; en algunos casos es posible una reducción de hasta el 99%. Esto se logró aprovechando la síntesis mejorada en torno a laMCXGatecon una síntesisCZGatetambién la síntesis. -
Mejorado el plugin por defecto para sintetizar
AnnotatedOperationobjetos. La mejora es especialmente útil al crear y transpilar circuitos controlados con puertas controladas en su interior. Por ejemplo:from qiskit.circuit import QuantumCircuit from qiskit.circuit.library import CXGate from qiskit.compiler import transpile inner = QuantumCircuit(5) inner.append(CXGate().control(3, annotated=True), [0, 1, 2, 3, 4]) controlled_inner_gate = inner.to_gate().control(2, annotated=True) qc = QuantumCircuit(15) qc.append(controlled_inner_gate, [0, 1, 2, 3, 4, 5, 6]) qct = transpile(qc, basis_gates=["cx", "u"])Este código crea un circuito cuántico
qcque contiene un circuito cuántico de 2 controles con una puerta CX de 3 controles en su interior. Con esta mejora, el número de puertas CX en el circuito transpilado se reduce de378a30. Tenga en cuenta que al especificarannotated=Trueal definir la lógica de control, las puertas controladas se crean como operaciones anotadas. Esto evita la síntesis ansiosa, permite al transpilador detectar quecontrolled_inner_gatees equivalente a una X-gate controlada por 6, y elegir el mejor método de síntesis disponible para X-gates multicontroladas, en particular utilizando los qubits ancilla disponibles. -
La función
adder_qft_d00()utilizada para sintetizarModularAdderGateyHalfAdderGateacepta ahora un parámetro adicionalannotated. SiTrue, la puerta-QFT inversa dentro de los sumadores se implementa como una operación anotada, lo que permite al transpilador aplicar optimizaciones adicionales. -
La descomposición cuántica de Shannon (
qs_decomposition()) incluye ahora una optimización que reduce elCXGateen el caso de que el unitario de entrada sea un unitario controlado. -
La función de síntesis
synth_mcx_1_clean_b95()produce ahora un circuito con menos puertas CX. -
La clase
SolovayKitaevDecompositiontiene ahora argumentos adicionales en el inicializador, que permiten construirla directamente a partir de un conjunto debasis_gatesy undepthpara las aproximaciones básicas. -
Se ha añadido
SolovayKitaevDecomposition.save_basic_approximations()para guardar el conjunto de aproximaciones básicas que utiliza la clase en un formato binario. Este cambio, en combinación con los nuevos argumentos del inicializador, permite a los usuarios omitir el uso explícito degenerate_basic_approximations()y confiar únicamente enSolovayKitaevDecomposition.
Características del transpilador
-
La función
generate_preset_pass_manager()genera ahora un gestor de pases especial cuando el conjunto de bases está formado sólo por puertas Clifford+T. Formalmente, un conjunto de bases Clifford+T debe contener sólo puertas Clifford, junto conTGate,TdgGateo ambas. La lista completa de puertas Clifford compatibles puede obtenerse utilizandoget_clifford_gate_names().Por ejemplo:
from qiskit.circuit import QuantumCircuit from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager from qiskit.quantum_info import get_clifford_gate_names basis_gates = get_clifford_gate_names() + ["t", "tdg"] pm = generate_preset_pass_manager(basis_gates=basis_gates) qc = QuantumCircuit(1) qc.rx(0.8, 0) qct = pm.run(qc) print(qct.count_ops())Resultaría con:
OrderedDict([('h', 10210), ('t', 4508), ('tdg', 4503), ('sdg', 943), ('s', 941)])Anteriormente, el gestor de pases generado no podía manejar el ejemplo anterior porque no podía descomponer puertas de rotación de un solo qubit
UGateen puertas Clifford+T. Sin embargo, el nuevo gestor de pases utiliza la descomposición Solovay-Kitaev para aproximar puertas de rotación de un solo qubit utilizando las puertasH,TyTdg, y llama al paseBasisTranslatorpara traducir las puertas al conjunto de bases objetivo. El nuevo gestor de pases también tiene otros cambios para permitir una traducción más eficiente a puertas Clifford+T.Es importante señalar que el conjunto de puertas base Clifford+T especificado debe ser universal, o de lo contrario la transpilación podría no tener éxito. Aunque el conjunto de puertas
["h", "t", "tdg"]o incluso["h", "t"]es suficiente para la universalidad, se recomienda añadir más puertas Clifford al conjunto si es posible, ya que de lo contrario la traducción podría ser menos eficiente. Por ejemplo, si no se incluye la puerta S, las puertas S podrían descomponerse en pares de puertas T (es decir, las puertas Clifford podrían descomponerse en puertas no Clifford, lo que podría no ser el comportamiento deseado).A continuación se muestra un ejemplo ligeramente mayor:
from qiskit.circuit import QuantumCircuit from qiskit.circuit.library import QFTGate from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager qc = QuantumCircuit(4) qc.append(QFTGate(4), [0, 1, 2, 3]) basis_gates = ["cx", "s", "sdg", "h", "t", "tdg"] pm = generate_preset_pass_manager(basis_gates=basis_gates, optimization_level=2) qc = QuantumCircuit(4) qc.append(QFTGate(4), [0, 1, 2, 3]) qct = pm.run(qc) print(qct.count_ops())Resultaría con:
OrderedDict([('h', 96510), ('tdg', 42396), ('t', 42389), ('s', 8240), ('sdg', 8235), ('cx', 12)]) -
Añadido un nuevo plugin de síntesis de alto nivel
HalfAdderSynthesisR25para sintetizar unHalfAdderGate. El nuevo plugin se basa enadder_ripple_r25().La página
HalfAdderSynthesisDefaulttambién se ha actualizado para seguir la siguiente secuencia de sintetizadores de medio sumador:"HalfAdder.ripple_r25"cuando hay qubits,"HalfAdder.ripple_c04"cuando se dispone de un qubit auxiliar, y"HalfAdder.ripple_r25"en todos los casos restantes. -
Añadidos múltiples plugins de síntesis de alto nivel para sintetizar un
MCXGate:MCXSynthesis1CleanKG24basado ensynth_mcx_1_clean_kg24().MCXSynthesis1DirtyKG24basado ensynth_mcx_1_dirty_kg24().MCXSynthesis2CleanKG24basado ensynth_mcx_2_clean_kg24().MCXSynthesis2DirtyKG24basado ensynth_mcx_2_dirty_kg24().
La clase
MCXSynthesisDefaulttambién se ha actualizado para que ejecute la siguiente secuencia de métodos de síntesis MCX hasta que el primero tenga éxito: :"mcx.2_clean_kg24","mcx.1_clean_kg24","mcx.n_clean_m15","mcx.n_dirty_i15"`, ``"mcx.2_dirty_kg24","mcx.1_dirty_kg24","mcx.1_clean_b95","mcx.noaux_v24". Los métodos se ordenan de forma que se apliquen primero los de mejor calidad. -
VF2PostLayoutse ha añadido al final de la etapa de optimización por defecto cuando se utiliza el nivel de optimización 3. -
Se ha añadido un nuevo
OptimizeCliffordTque combina pares de puertas T consecutivas en puertas S y pares de puertas Td consecutivas en puertas Sd. Esta optimización es especialmente eficaz para reducir el número de T tras la descomposición Solovay-Kitaev, que produce múltiples puertas T o Tdg consecutivas. Por ejemplo:from qiskit.circuit import QuantumCircuit from qiskit.transpiler.passes import SolovayKitaev, OptimizeCliffordT qc = QuantumCircuit(1) qc.rx(0.8, 0) # Run Solovay-Kitaev pass on qc transpiled = SolovayKitaev()(qc) print(transpiled.count_ops().get("t", 0) + transpiled.count_ops().get("tdg", 0)) # Should print 12779 # Run Clifford+T optimization optimized = OptimizeCliffordT()(transpiled) print(optimized.count_ops().get("t", 0) + optimized.count_ops().get("tdg", 0)) # Should print 9011 -
Se ha añadido el
ContextAwareDynamicalDecouplingque implementa un desacoplamiento dinámico contextual basado en secuencias Walsh-Hadamard. Las secuencias de retardo insertadas serán mutuamente ortogonales a las secuencias en qubits vecinos, y tendrán en cuenta los espectadores de control/objetivo de las puertas CX y ECR. Consulte arXiv:2403.06852 para más información.Ejemplo:
from qiskit.circuit.library import QFT from qiskit.transpiler import PassManager, CouplingMap from qiskit.transpiler.passes import ALAPScheduleAnalysis, ContextAwareDynamicalDecoupling from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager from qiskit.providers.fake_provider import GenericBackendV2 num_qubits = 10 circuit = QFT(num_qubits) circuit.measure_all() target = GenericBackendV2( 100, basis_gates=["id", "rz", "sx", "x", "ecr"], coupling_map=CouplingMap.from_grid(10, 10) ).target pm = generate_preset_pass_manager(optimization_level=2, target=target) dd = PassManager([ ALAPScheduleAnalysis(target=target), ContextAwareDynamicalDecoupling(target=target), ]) transpiled = pm.run(circuit) with_dd = dd.run(transpiled) with_dd.draw("mpl", idle_wires=False)
-
Se han añadido los siguientes atributos a la clase
DAGCircuitpara poder consultar el número de variables de estiramiento:num_stretches,num_captured_stretchesynum_declared_stretches. -
Añadido un nuevo plugin de síntesis unitaria
CliffordUnitarySynthesisque intenta sintetizar una puerta unitaria dada comprobando si puede ser representada por un Clifford, en cuyo caso devuelve un circuito que implementa este unitario y consiste sólo en puertas Clifford.El complemento es invocado por el
UnitarySynthesistranspiler pass cuando el parámetromethodse establece en"clifford".Además, el parámetro
plugin_configdeUnitarySynthesisse puede utilizar para pasar los siguientes parámetros específicos del plugin:- min_qubits: el número mínimo de qubits a considerar (el valor por defecto es 1).
- max_qubits: el número máximo de qubits a considerar (el valor por defecto es 3).
Por ejemplo:
import math from qiskit.circuit import QuantumCircuit from qiskit.circuit.library import UnitaryGate from qiskit.quantum_info import Operator from qiskit.transpiler.passes import UnitarySynthesis # clifford unitary over 2 qubits c2 = QuantumCircuit(2) c2.h(0) c2.rz(math.pi / 4, 1) c2.rz(math.pi / 4, 1) c2.sdg(1) uc2 = UnitaryGate(Operator(c2).data) # non-clifford unitary over 2 qubits n2 = QuantumCircuit(2) n2.h(0) n2.rz(math.pi / 4, 1) n2.sdg(1) un2 = UnitaryGate(Operator(n2).data) # quantum circuit with two unitary gates qc = QuantumCircuit(3) qc.append(uc2, [2, 1]) qc.append(un2, [0, 2]) transpiled = UnitarySynthesis(method="clifford")(qc) transpiled.draw("mpl")
Ejecutando el código anterior se resintetiza la primera puerta unitaria en puertas Clifford, mientras que la segunda puerta permanece inalterada.
Si modificamos el ejemplo anterior de la siguiente manera
config = {"min_qubits": 3} transpiled = UnitarySynthesis(method="clifford", plugin_config=config)(qc)entonces ambas puertas unitarias permanecen inalteradas.
Funciones de visualización
-
Se han introducido estilos personalizados para la función
dag_drawer()función. Esto permite pasar un diccionario al parámetrostylecon atributos personalizados que cambian el estilo del DAG que devuelve la función. Por ejemplo:from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit from qiskit.converters import circuit_to_dag from qiskit.visualization import dag_drawer q = QuantumRegister(3, 'q') c = ClassicalRegister(3, 'c') circ = QuantumCircuit(q, c) circ.h(q[0]) circ.cx(q[0], q[1]) circ.measure(q[0], c[0]) circ.rz(0.5, q[1]).c_if(c, 2) dag = circuit_to_dag(circ) style = { "inputnodecolor": "pink", "outputnodecolor": "lightblue", "opnodecolor": "red", } dag_drawer(dag, style=style)
Notas de actualización
-
La biblioteca
python-dateutilya no es una dependencia de Qiskit. Desde que Qiskit v2.0 nada en la librería estaba usando elpython-dateutily Qiskit ya no dependía de la librería. Esta versión lo elimina de la lista de dependencias, por lo que no se instala automáticamente como requisito previo para utilizar Qiskit. Si usted estaba confiando en Qiskit para instalar dateutil para usted como una dependencia que ahora tendrá que asegurarse de que está instalando manualmente (que es la mejor práctica para las dependencias directas). -
sympyya no es un requisito para instalar Qiskit. Tras la migración a un motor simbólico basado en Rust para la claseParameterExpressionlos usos de SymPy quedan aislados a algunas utilidades de visualización, elTemplateOptimizationtranspiler pass,ParameterExpression.sympify()(que es explícitamente para SymPy interoperabilidad) ySparsePauliOp.simplify()si se utilizan coeficientes parametrizados. Esta funcionalidad no es la más utilizada por lo que SymPy se trata ahora como una dependencia opcional y esas funciones lanzarán unaMissingOptionalLibraryErrorexcepción si se utilizan y SymPy no está instalado. -
Se ha eliminado la dependencia de
symengineque se utilizaba para construirParameterExpressionse ha eliminado. Ha sido sustituido por un motor simbólico interno y ya no es necesario para las funciones básicas de Qiskit. La única excepción es que symengine se incluyó en los formatos QPY 10, 11 y 12, por lo que sigue siendo necesario si está deserializando esos formatos. La dependencia de symengine paraqpy.load()se ha hecho explícitamente opcional en 2.0.0, pero si antes confiabas en que symengine se instalara por defecto para esta funcionalidad, ahora tendrás que instalarlo manualmente para cargar la carga útil. Si estuviera utilizandoParameterExpression.sympify()para obtener un objeto de expresión symengine de un archivoParameterExpressionque ahora devolverá una expresiónsympy. Si necesitas usar esto con symengine puedes aprovecharsymengine.sympifypara convertir la expresiónsympyen una de symengine.
Notas sobre la actualización de circuitos
-
El atributo
definitiondel atributoHalfAdderGatese ha cambiado para utilizar internamenteadder_ripple_r25()para generar la definición de la puerta para un circuito más eficiente sin qubits auxiliares. Si por alguna razón se desea la definición antigua, se puede utilizar directamente la funciónadder_qft_d00()que generará un circuito equivalente al quedefinitionen versiones anteriores. -
El circuito devuelto por la función
excitation_preserving()y la claseExcitationPreservingse construyen ahora con un único circuitoXXPlusYYGate. Esto supone un cambio con respecto a versiones anteriores en las que se utilizaba unRXXGateseguido de unRYYGate. Esta nueva construcción del circuito es equivalente pero utiliza menos puertas que son todas de excitación preservando por definición más simple. -
Los
definitionatributos de varias puertas estándar se han actualizado de acuerdo con los siguientes principios:- Cuando está disponible, se prefiere una definición que utilice puertas Clifford a las definiciones que incluyan puertas que no sean Clifford.
- Cuando está disponible, se prefiere una definición que utilice puertas Clifford+T a una que utilice una puerta
UGate. - El uso de
PhaseGatees preferible aU1Gate. - El uso de
UGatees preferible a`U2Gatey`U3Gate.
Lo más importante es que se mantiene la siguiente invariante: ampliando recursivamente las definiciones de las puertas, cualquier puerta puede expresarse utilizando únicamente la base
["cx", "u"]. Las definiciones de todas las puertas estándar son equivalentes, por lo que no cambia la semántica detrás de las puertas, sólo la construcción exacta del circuito devuelto para algunas puertas ya no es exactamente la misma. Este cambio era necesario para apoyar la transpilación Clifford+T. -
Qiskit utiliza ahora su propia biblioteca de expresiones simbólicas basada en Rust para implementar las funciones internas de
ParameterExpressionyParameter. Dado que se trata de una nueva implementación del motor matemático simbólico central utilizado paraParameterExpressionpuede haber pequeñas diferencias en el comportamiento exacto de algunas funciones. Siempre debería producir resultados equivalentes para la API documentada. Por favor, abra una incidencia si encuentra algún problema de corrección.
Notas sobre la actualización de la API C
-
La forma en que se exponen los números complejos en la API C de Qiskit ha cambiado. Anteriormente,
QkComplex64era un typedef dependiente del compilador que permitía pasar tipos complejos nativos por puntero a la API de Qiskit (por ejemplo comodouble complex*). Aunque resultaba cómodo, este enfoque se basaba implícitamente en suposiciones sobre la disposición de la memoria que no están estrictamente garantizadas.Qiskit v2.1 ahora expone
QkComplex64 { double re; double im; }como una estructura, para asegurar que la disposición de la memoria es siempre compatible y para una mayor compatibilidad con el compilador. Para mayor comodidad, se proporcionan convertidores dependientes del compiladorqk_complex64_from_nativeyqk_complex64_to_native, que permiten traducir del struct a un número complejo nativo. Tenga en cuenta que sólo funcionan en plataformas compatibles condouble complexo para compiladores MSVC que utilicen_Dcomplex.Por ejemplo:
#include <qiskit.h> #include <math.h> #include <stdio.h> #include <complex.h> int main(int argc, char *argv[]) { // platform-independent constructions: QkComplex64 coeff = {5.0, 3.0}; // ... or using converter // double complex native = 5.0 + I * 3; // uses C11 standard, does not work on MSVC // QkComplex64 coeff = qk_complex64_from_native(&native); // convert from native uint32_t num_qubits = 100; QkObs *obs = qk_obs_zero(num_qubits); QkBitTerm bit_terms[3] = {QkBitTerm_X, QkBitTerm_Y, QkBitTerm_Z}; uint32_t indices[3] = {0, 1, 2}; QkObsTerm term = {coeff, 3, bit_terms, indices, num_qubits}; qk_obs_add_term(obs, &term); printf("num_qubits: %u\n", qk_obs_num_qubits(obs)); printf("num_terms: %lu\n", qk_obs_num_terms(obs)); qk_obs_free(obs); return 0; }
Notas sobre la actualización de QPY
- La versión QPY por defecto emitida por
qpy.dump()se ha cambiado a la última versión 15 de QPY. Si por alguna razón necesita generar una versión de formato anterior, puede utilizar el argumentoversionenqpy.dump()para especificar una versión más antigua a generar.
Notas sobre la actualización de Synthesis
-
El formato de serialización para las aproximaciones básicas en los algoritmos Solovay-Kitaev se ha cambiado de
.npya otro formato binario, basado enserdeybincodede Rust. Todas las rutinas que cargan aproximaciones básicas (comogenerate_basic_approximations(),SolovayKitaevDecomposition.load_basic_approximations()o el inicializador deSolovayKitaev) siguen soportando la carga del formato heredado. Sin embargo, cualquier archivo nuevo se almacenará en el nuevo formato. Si confiabas en el formato antiguo, baja Qiskit a < 2.2 y guarda los archivos necesarios. -
Los valores por defecto para
SolovayKitaev(y clases afines) han aumentado adepth=12yreps=5. Esto se debe a que la implementación subyacente está ahora en Rust, lo que nos permite aumentar la precisión por defecto, sin dejar de ser significativamente más rápido que la versión anterior Python.
Notas sobre la actualización del transpilador
-
Los plugins de diseño incorporados para los gestores de pases actuales ya no contendrán su componente principal (por ejemplo, una
SabreLayoutpara la etapa "sable ") si no se proporcionan restricciones de acoplamiento. Anteriormente, los plugins construían instancias inválidas de sus pases de diseño, bajo la suposición de que una lógica separada evitaría que los pases se ejecutaran y lanzaran excepciones.Esto no debería tener ningún efecto significativo en el uso de los gestores de pases predefinidos o los plugins, ya que nunca fue válido llamar a los pases en un estado no válido.
Notas sobre características en desuso
-
El soporte para ejecutar Qiskit con Python 3.9 ha sido obsoleto y será eliminado en la versión de Qiskit v2.3. La versión 2.3.0 es la primera versión después de que Python 3.9 llegue al final de su vida útil y deje de recibir soporte [1]. Esto significa que a partir de la versión 2.3.0 deberá actualizar la versión Python que esté utilizando a Python 3.9 o superior.
Circuitos obsoletos
-
La biblioteca de circuitos sufrió una refactorización en la versión de Qiskit v1.3, en la que se proporcionaron alternativas para objetos de tipo
QuantumCircuitque son o bien unInstructiono una función Python para su construcción. Esta refactorización permite al compilador razonar sobre instrucciones de alto nivel y reduce la sobrecarga de los circuitos que no requieren optimizaciones de alto nivel.Todas las subclases de
QuantumCircuitsubclases están ahora obsoletas en favor de sus alternativas introducidas en Qiskit v1.3. Como parte de esto, la clase baseBlueprintCircuittambién queda obsoleta. Todos ellos tienen un periodo de obsoleto ampliado y sólo se eliminarán en Qiskit v3.0.La clase
BlueprintCircuitno tiene un reemplazo directo, en su lugar utiliza unQuantumCircuitdirectamente o una función que genere circuitos. Consulteqiskit.circuit.librarypara más detalles, pero a continuación figuran algunos circuitos comunes y sus sustitutos:QFT→QFTGateTwoLocal→n_local()(no se trata de una errata, esta función abarca losNLocalyTwoLocalfuncionalidad)EfficientSU2→efficient_su2()RealAmplitudes→real_amplitudes()ZZFeatureMap→zz_feature_map()QuantumVolume→quantum_volume()EvolvedOperatorAnsatz→evolved_operator_ansatz()MCXGrayCode→synth_mcx_gray_code()MCXRecursive→synth_mcx_n_dirty_i15()MCXVChain→synth_mcx_n_clean_m15()
Corrección de errores
-
Se ha corregido un error en la función
dag_drawer()y en el métodoDAGCircuit.draw()donde al establecer el argumento de la palabra clavestyle=plainno se mostraban las etiquetas de circuito para los nodos del DAG en la visualización. -
Se ha corregido un error en el método
QuantumCircuit.assign_parameters()por el que los parámetros que no se utilizaban en el circuito y se pasaban como cadenas no se ignoraban cuando se establecía el argumentostrict=False. Consulte el problema nº 13933 para obtener más información. -
Se han corregido casos extremos en la configuración de
Makefilepara Windows, en los que la variable de entorno predefinidaOSno coincidía con la salida del comandouname -s. -
Se ha corregido el atributo
namedel archivoOrGateque anteriormente se establecía incorrectamente a la cadena"and"en lugar del valor esperado"or"que ahora se devuelve. Este valor incorrecto"and"entraba en conflicto con elAndGate.namey podría haber dado lugar a varios problemas relacionados con el uso deOrgatey su diferenciación de un archivoAndGate. -
Se ha corregido un error en la función
qpy.load()por el que podía fallar la deserialización de circuitos cuyos parámetros habían sido reasignados a parámetros con los mismos nombres. Corregido #13720, #13720, y #13720. -
Se ha corregido el
GenericBackendV2para incluir ahoraBoxOpcomo un tipo de instrucción soportado en elGenericBackendV2.targetcuando el argumento de palabra clavecontrol_flow=Truese establece en el constructor. -
Cuando se sintetiza una
MCXGatepuerta con 3 controles, la función de síntesissynth_mcx_n_dirty_i15()requería un qubit auxiliar, lo que producía un circuito con 5 qubits (3 de control, 1 objetivo y 1 auxiliar). Sin embargo, el algoritmo de síntesis real no hace uso de este qubit auxiliar. Ahora se ha corregido este comportamiento: el circuito sintetizado tiene más de 4 qubits (3 de control y 1 de destino), lo que permite aplicar la función de síntesis en un número ligeramente mayor de casos. -
En
QuantumCircuit.draw()ycircuit_drawer()mostrará ahora las instruccionesBoxOpen unQuantumCircuiten el mismo corte vertical si los tramos verticales no se solapan ahora se renderizan en el mismo corte vertical, siempre que sea posible. -
Se ha corregido el
QuantumCircuit.draw()método ycircuit_drawer()función en el modo"mpl"para insertar menos espacio extraño dentro del borde izquierdo al dibujarBoxOpinstancias en unQuantumCircuit.
Otras notas
-
Se ha añadido un nuevo objetivo de dependencia adicional opcional
qpy-compat. Este objetivo debe utilizarse si planea cargarqpyarchivos con formatos QPY antiguos. El objetivo instala requisitos adicionales utilizados para cargar archivos QPY utilizando versiones de formato < 13. If you are only using newer QPY format versions you do no need to install this. Theqpy.dump()only generates QPY > =13 esto sólo es necesario para cargar archivos generados con versiones antiguas (anteriores a 2.0.0 ) de Qiskit Puede instalar esta nueva variante opcional conpip install qiskit[qpy-compat]. -
Los pesos relativos de los componentes "básico" y "anticipado" del
SabreSwapySabreLayoutse han modificado cuando el seguimiento de conjunto ampliado está activo (como siempre enSabreLayouty por defecto enSabreSwap). El componente heurístico relativo a la distancia entre qubits en una puerta individual de la capa frontal ya no se debilita proporcionalmente al número de puertas de la capa frontal; este comportamiento fue una elección histórica, pero en circuitos de gran tamaño, tiene el efecto accidental de hacer que la capa frontal sea casi ignorada, lo que es desastroso para la eficiencia.Las mejoras de enrutamiento resultantes deberían ser más notables en los circuitos que con frecuencia pueden estratificarse en capas de más de 20 puertas paralelas de dos qubits.