Saltar al contenido principal

Biblioteca de circuitos (Circuit library)

Versiones de paquetes

El código de esta página se desarrolló utilizando los siguientes requisitos. Recomendamos usar estas versiones o más recientes.

qiskit[all]~=2.3.0

El SDK de Qiskit incluye una biblioteca de circuitos populares para usarlos como bloques de construcción en tus propios programas. Usar circuitos predefinidos ahorra tiempo investigando, escribiendo código y depurando (debugging). La biblioteca incluye circuitos populares de la computación cuántica, circuitos que son difíciles de simular clásicamente y circuitos útiles para la evaluación de rendimiento (benchmarking) del hardware cuántico.

Esta página enlista las diferentes categorías de circuitos que la biblioteca provee. Para obtener una lista completa de los circuitos, consulta la documentación de la API de la biblioteca de circuitos.

Puertas estándar

La biblioteca de circuitos también incluye puertas cuánticas estándar. Algunas son puertas más fundamentales (como la UGate), y otras son puertas de múltiples qubits que usualmente necesitan ser construidas a partir de puertas de uno y dos qubits. Para añadir puertas importadas a tu circuito, usa el método append; el primer argumento es la puerta y el siguiente argumento es una lista de los qubits a los cuales aplicarles dicha puerta.

Por ejemplo, la siguiente celda de código crea un circuito con una puerta de Hadamard y una puerta multicontrolada X (multi-controlled-X gate).

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit
from qiskit import QuantumCircuit
from qiskit.circuit.library import HGate, MCXGate

mcx_gate = MCXGate(3)
hadamard_gate = HGate()

qc = QuantumCircuit(4)
qc.append(hadamard_gate, [0])
qc.append(mcx_gate, [0, 1, 2, 3])
qc.draw("mpl")

Output of the previous code cell

Consulta Puertas estándar (Standard gates) en la documentación de la API de la biblioteca de circuitos.

¿No estás seguro de cómo se llama tu puerta? Intenta preguntarle al Qiskit Code Assistant.

Circuitos N-local

Estos circuitos alternan capas de puertas de rotación de un solo qubit con capas de puertas entrelazadoras (entangling gates) de múltiples qubits.

Esta familia de circuitos es popular en algoritmos cuánticos variacionales (variational quantum algorithms) debido a que pueden producir una amplia gama de estados cuánticos. Los algoritmos variacionales ajustan los parámetros de las puertas para encontrar estados que tienen ciertas propiedades (tales como estados que representan una buena solución a un problema de optimización). Con este propósito, muchos circuitos en la biblioteca están parametrizados (parameterized), lo cual significa que puedes definirlos sin valores fijos.

La siguiente celda de código importa un circuito n_local, en el cual las puertas entrelazadoras son puertas de dos qubits. Este circuito intercala (interleaves) bloques de puertas parametrizadas de un solo qubit, seguidos de bloques entrelazadores de puertas de dos qubits. El siguiente código crea un circuito de tres qubits, con puertas RX de un solo qubit y puertas CZ de dos qubits.

from qiskit.circuit.library import n_local

two_local = n_local(3, "rx", "cz")
two_local.draw("mpl")

Output of the previous code cell

Puedes obtener un objeto similar a una lista de los parámetros del circuito desde el atributo parameters.

two_local.parameters
ParameterView([ParameterVectorElement(θ[0]), ParameterVectorElement(θ[1]), ParameterVectorElement(θ[2]), ParameterVectorElement(θ[3]), ParameterVectorElement(θ[4]), ParameterVectorElement(θ[5]), ParameterVectorElement(θ[6]), ParameterVectorElement(θ[7]), ParameterVectorElement(θ[8]), ParameterVectorElement(θ[9]), ParameterVectorElement(θ[10]), ParameterVectorElement(θ[11])])

También puedes usar esto para asignar estos parámetros a valores reales usando un diccionario con la forma { Parámetro: número }. Para demostrarlo, la siguiente celda de código asigna cada parámetro en el circuito al valor 0.

bound_circuit = two_local.assign_parameters(
{p: 0 for p in two_local.parameters}
)
bound_circuit.decompose().draw("mpl")

Output of the previous code cell

Para obtener más información, consulta Puertas N-local (N-local gates) en la documentación de la API de la biblioteca de circuitos, o toma el curso Diseño de algoritmos variacionales (Variational algorithm design) en IBM Quantum Learning.

Circuitos de codificación de datos (Data-encoding circuits)

Estos circuitos parametrizados codifican datos en estados cuánticos para ser procesados por algoritmos de aprendizaje automático cuántico (quantum machine learning). Algunos circuitos que admite Qiskit son:

  • Codificación de amplitud (Amplitude encoding), que codifica cada número en la amplitud de un estado base. Esto puede almacenar 2n2^n números en un solo estado, pero puede suponer un alto costo su implementación.
  • Codificación de base (Basis encoding), que codifica un número entero kk mediante la preparación del estado base correspondiente k|k\rangle.
  • Codificación de ángulo (Angle encoding), que establece cada número en los datos como un ángulo de rotación en un circuito parametrizado.

El mejor enfoque dependerá de la naturaleza específica de tu aplicación. Sin embargo, en las computadoras cuánticas actuales usamos a menudo circuitos de codificación de ángulos tales como el zz_feature_map.

from qiskit.circuit.library import zz_feature_map

features = [0.2, 0.4, 0.8]
feature_map = zz_feature_map(feature_dimension=len(features))

encoded = feature_map.assign_parameters(features)
encoded.draw("mpl")

Output of the previous code cell

Consulta Circuitos de codificación de datos (Data encoding circuits) en la documentación de la API de la biblioteca de circuitos.

Circuitos de evolución temporal (Time-evolution circuits)

Estos circuitos simulan un estado cuántico evolucionando en el tiempo. Usa circuitos de evolución temporal para investigar efectos físicos como la transferencia de calor (heat transfer) o transiciones de fase en un sistema. Los circuitos de evolución temporal también son un bloque de construcción fundamental de las funciones de onda de la química (como los estados de prueba de agrupamiento acoplado unitario, unitary coupled-cluster trial states) y del algoritmo QAOA que utilizamos para los problemas de optimización.

from qiskit.circuit.library import PauliEvolutionGate
from qiskit.circuit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp

# Prepare an initial state with a Hadamard on the middle qubit
state = QuantumCircuit(3)
state.h(1)

hamiltonian = SparsePauliOp(["ZZI", "IZZ"])
evolution = PauliEvolutionGate(hamiltonian, time=1)

# Evolve state by appending the evolution gate
state.compose(evolution, inplace=True)

state.draw("mpl")

Output of the previous code cell

Lee la documentación de la API de PauliEvolutionGate.

Circuitos de evaluación de rendimiento y teoría de la complejidad

Los circuitos de evaluación de rendimiento nos dan una idea de cuán bien está funcionando realmente nuestro hardware, y los circuitos de la teoría de la complejidad nos ayudan a entender qué tan difíciles son los problemas que queremos resolver.

Por ejemplo, la prueba de rendimiento de "volumen cuántico" (quantum volume benchmark) mide qué tan fielmente ejecuta una computadora cuántica un tipo de circuito cuántico aleatorio. La puntuación de la computadora cuántica aumenta junto con el tamaño del circuito que puede ejecutar de forma confiable. Esto considera todos los aspectos de la computadora, incluido el conteo de qubits, la fidelidad de las instrucciones, la conectividad de los qubits y la pila de software de transpilación y postprocesamiento. Lee más sobre el volumen cuántico en el artículo original sobre volumen cuántico.

El siguiente código muestra un ejemplo de un circuito de volumen cuántico construido en Qiskit que se ejecuta en cuatro qubits (los bloques unitarios o unitary son puertas aleatorias de dos qubits).

from qiskit.circuit.library import quantum_volume

quantum_volume(4).draw("mpl")

Output of the previous code cell

La biblioteca de circuitos también incluye circuitos que se consideran difíciles de simular clásicamente, como los circuitos polinomiales cuánticos instantáneos (iqp). Estos circuitos intercalan ciertas puertas diagonales (en la base computacional) entre bloques de puertas de Hadamard.

Otros circuitos incluyen grover_operator para utilizarse en el algoritmo de Grover, y el circuito fourier_checking para el problema de la comprobación de Fourier. Consulta estos circuitos en Circuitos cuánticos particulares (Particular quantum circuits) en la documentación de la API de la biblioteca de circuitos.

Circuitos aritméticos (Arithmetic circuits)

Las operaciones aritméticas son funciones clásicas, como la suma de enteros y las operaciones bit a bit. Estas pueden ser útiles con algoritmos como la estimación de amplitud para aplicaciones de finanzas, y en algoritmos como el algoritmo HHL, que resuelve sistemas de ecuaciones lineales.

Como ejemplo, intentemos sumar dos números de tres bits usando un circuito de suma con acarreo (ripple-carry) para realizar la suma in-situ (FullAdderGate). Este sumador suma dos números (los llamaremos "A" y "B") y escribe el resultado en el registro que contenía B. En el siguiente ejemplo, A=2 y B=3.

from qiskit.circuit.library import FullAdderGate
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister

adder = FullAdderGate(3) # Adder of 3-bit numbers

# Create the number A=2
reg_a = QuantumRegister(3, "a")
number_a = QuantumCircuit(reg_a)
number_a.initialize(2) # Number 2; |010>

# Create the number B=3
reg_b = QuantumRegister(3, "b")
number_b = QuantumCircuit(reg_b)
number_b.initialize(3) # Number 3; |011>

# Create a circuit to hold everything, including a classical register for
# the result
qregs = [
QuantumRegister(1, "cin"),
QuantumRegister(3, "a"),
QuantumRegister(3, "b"),
QuantumRegister(1, "cout"),
]
reg_result = ClassicalRegister(3)
circuit = QuantumCircuit(*qregs, reg_result)

# Compose number initializers with the adder. Adder stores the result to
# register B, so we'll measure those qubits.
circuit = (
circuit.compose(number_a, qubits=reg_a)
.compose(number_b, qubits=reg_b)
.compose(adder)
)
circuit.measure(reg_b, reg_result)
circuit.draw("mpl")

Output of the previous code cell

Simular el circuito muestra que arroja el resultado de 5 para todos los 1024 shots o disparos (es decir, se mide con probabilidad de 1.0).

from qiskit.primitives import StatevectorSampler

result = StatevectorSampler().run([circuit]).result()

print(f"Count data:\n {result[0].data.c0.get_int_counts()}")
Count data:
{5: 1024}

Consulta Aritmética (Arithmetic) en la documentación de la API de la biblioteca de circuitos.

Siguientes pasos

Recomendaciones