Capítulo 1. Circuitos y operaciones cuánticas
Este trabajo se ha traducido utilizando IA. Agradecemos tus opiniones y comentarios: translation-feedback@oreilly.com
En Qiskit, los programas cuánticos se expresan normalmente con circuitos cuánticos que contienen operaciones cuánticas. Los circuitos cuánticos están representados por la clase QuantumCircuit
, y las operaciones cuánticas están representadas por subclases de la claseInstruction
.
Construir circuitos cuánticos
Se puede crear un circuito cuántico suministrando a un argumento que indique el número de hilos cuánticos (qubits) deseados para ese circuito. A menudo se proporciona como un número entero:
from
qiskit
import
QuantumCircuit
QuantumCircuit
(
2
)
Opcionalmente, también se puede especificar el número de hilos clásicos (bits) deseados. El primer argumento se refiere al número de hilos cuánticos, y el segundo argumento al número de hilos clásicos:
QuantumCircuit
(
2
,
2
)
El número de hilos cuánticos y clásicos deseados también puede expresarse proporcionando instancias de QuantumRegister
y ClassicalRegister
como argumentos a QuantumCircuit
. Estas clases se tratan en "Uso de la clase QuantumRegister" y "Uso de la clase ClassicalRegister".
Uso de la clase QuantumCircuit
La clase QuantumCircuit
contiene un gran número de métodos y atributos. La finalidad de muchos de sus métodos es aplicar operaciones cuánticas a un circuito cuántico. La mayoría de sus otros métodos y atributos manipulan o proporcionan información sobre un circuito cuántico.
Puertas de uso común
La Tabla 1-1 contiene algunas puertas monocuánticas de uso común y ejemplos de código. La variable qc
se refiere a una instancia de QuantumCircuit
que contiene al menos cuatro hilos cuánticos.
Nombres | Ejemplo | Notas |
---|---|---|
H, Hadamard |
|
Aplica la puerta H al qubit 0. Ver "Puerta H". |
I, Identidad |
|
Aplica la puerta I al qubit 2. Ver "Puerta I". |
P, Fase |
|
Aplica la puerta P con rotación de fase π/2 al qubit 0. Ver "Puerta de fase". |
RX |
|
Aplica la puerta RX con rotación π/4 al qubit 2. Ver "PuertaRX". |
RY |
|
Aplica la puerta RY con rotación π/8 al qubit 0. Ver "Puerta RY". |
RZ |
|
Aplica la puerta RZ con rotación π/2 al qubit 1. Ver "Puerta RZ". |
S |
|
Aplica la puerta S al qubit 3. Equivale a la puerta P con rotación de fase π/2. Ver "Puerta S". |
S† |
|
Aplica la puerta S† al qubit 3. Equivale a la puerta P con rotación de fase 3π/2. Véase "SdgGate". |
SX |
|
Aplica la puerta SX (raíz cuadrada de X) al qubit 2. Equivale a la puerta RX con rotación π/2. Ver "Puerta SX". |
T |
|
Aplica la puerta T al qubit 1. Equivale a la puerta P con rotación de fase π/4. Ver "Puerta T". |
T† |
|
Aplica la puerta T† al qubit 1. Equivale a la puerta P con rotación de fase 7π/4. Ver "TdgGate". |
U |
|
Aplica la rotación con 3 ángulos de Euler al qubit 1. Ver "UGate". |
X |
|
Aplica la puerta X al qubit 3. Ver "Puerta X". |
Y |
|
Aplica puertas Y a los qubits 0, 2 y 3. Ver "Compuerta Y". |
Z |
|
Aplica la puerta Z al qubit 2. Equivale a la puerta P con rotación de fase π. Ver "Puerta Z". |
La Figura 1-1 contiene un circuito sin sentido con todos los ejemplos de puertas de un solo qubit de la Tabla 1-1.
La Tabla 1-2 contiene algunas puertas multiqubit de uso común y ejemplos de código. La variable qc
se refiere a una instancia de QuantumCircuit
que contiene al menos cuatro hilos cuánticos.
Nombres | Ejemplo | Notas |
---|---|---|
CCX, Toffoli |
|
Aplica la puerta X al hilo cuántico 2, en función del estado de los qubits de control de los hilos 0 y 1. Ver "CCXPuerta". |
CH |
|
Aplica la puerta H al hilo cuántico 1, en función del estado del qubit de control del hilo 0. Ver "CHGate". |
CP, Fase de Control |
|
Aplica la puerta de fase al hilo cuántico 1, en función del estado del qubit de control del hilo 0. Ver "CPhaseGate". |
CRX, Control-RX |
|
Aplica la puerta RX al hilo cuántico 3, en función del estado del qubit de control del hilo 2. Ver "Puerta CRX". |
CRY, Control-RY |
|
Aplica la puerta RY al hilo cuántico 3, en función del estado del qubit de control del hilo 2. Véase "CRYGate". |
CRZ |
|
Aplica la puerta RZ al hilo cuántico 1, en función del estado del qubit de control del hilo 0. Ver "Puerta CRZ". |
CSwap, Fredkin |
|
Intercambia los estados de los qubits de los hilos 2 y 3, en función del estado del qubit de control del hilo 0. Ver "CSwapGate". |
CSX |
|
Aplica la puerta SX (raíz cuadrada de X) al hilo cuántico 1, en función del estado del qubit de control del hilo 0. Ver "Puerta CSX". |
CU |
|
Aplica la puerta U con un argumento de fase global adicional al hilo cuántico 1, sujeto al estado del qubit de control del hilo 0. Ver "CUGate". |
CX, CNOT |
|
Aplica la puerta X al hilo cuántico 3, en función del estado del qubit de control del hilo 2. Ver "Puerta CX". |
CY, Control-Y |
|
Aplica la puerta Y al hilo cuántico 3, en función del estado del qubit de control del hilo 2. Ver "CYGate". |
CZ, Control-Z |
|
Aplica la puerta Z al hilo cuántico 2, en función del estado del qubit de control del hilo 1. Ver "CZGate". |
DCX |
|
Aplica dos compuertas CNOT cuyos qubits de control estén en los hilos 2 y 3. Ver "Compuerta DCX". |
iSwap |
|
Intercambia los estados de los qubits de los hilos 0 y 1, y cambia la fase del y amplitudes mediante |
MCP, Fase de control múltiple |
|
Aplica la puerta de fase al hilo cuántico 3, en función del estado de los qubits de control de los hilos 0, 1 y 2. Consulta "MCPhaseGate". |
MCX, Multicontrol X |
|
Aplica la puerta X al hilo cuántico 3, en función del estado de los qubits de control de los hilos 0, 1 y 2. Ver "MCXPuerta". |
Intercambia |
|
Intercambia los estados de los qubits de los hilos 2 y 3. Ver "SwapGate". |
La Figura 1-2 contiene un circuito sin sentido con todos los ejemplos de puertas multiqubit de la Tabla 1-2.
Dibujar un circuito cuántico
El método draw()
dibuja un circuito cuántico en variosformatos.
Utilizando el método dibujar()
El siguiente fragmento de código utiliza el método draw()
en el formato por defecto:
qc
=
QuantumCircuit
(
3
)
qc
.
h
(
0
)
qc
.
cx
(
0
,
1
)
qc
.
cx
(
0
,
2
)
qc
.
draw
()
La Figura 1-3 muestra el circuito dibujado.
Crear una barrera
El método barrier()
coloca una barrera en un circuito (como se muestra en la Figura 1-4), que proporciona tanto una separación visual como funcional entre las puertas de un circuito cuántico. Las puertas situadas a ambos lados de una barrera no son candidatas a ser optimizadas juntas cuando el circuito se convierte para funcionar en hardware cuántico o en un simulador.
Nota
El conjunto de puertas expresado mediante Qiskit representa una abstracción de las puertas reales implementadas en un determinado ordenador cuántico o simulador. Qiskit transpila las puertas a las implementadas en la plataforma de destino, combinando puertas cuando es posible para optimizar el circuito.
Utilizando el método barrera()
El método barrier()
toma como argumento opcional los hilos qubit sobre los que colocar una barrera. Si no se proporciona ningún argumento, se coloca una barrera en todos los hilos cuánticos. Este método crea una instancia Barrier
(ver "Barrera").
El siguiente fragmento de código demuestra el uso del método barrier()
con y sin argumentos:
qc
=
QuantumCircuit
(
2
)
qc
.
h
([
0
,
1
])
qc
.
barrier
()
qc
.
x
(
0
)
qc
.
x
(
0
)
qc
.
s
(
1
)
qc
.
barrier
([
1
])
qc
.
s
(
1
)
qc
.
draw
()
La Figura 1-4 muestra el circuito resultante.
Observa que las puertas S del circuito están separadas por una barrera y, por tanto, no son candidatas a combinarse en una puerta Z. Sin embargo, las puertas X pueden combinarse eliminando ambas, ya que se anulan entre sí.
Medir un circuito cuántico
Los métodos utilizados habitualmente para medir circuitos cuánticos son measure()
y measure_all()
. El primero es útil cuando el circuito cuántico contiene hilos clásicos en los que recibir el resultado de una medición. El segundo es útil cuando el circuito cuántico no tiene cables clásicos. Estos métodos crean instancias Measure
(ver "Medida").
Utilizando el método measure()
El método measure()
toma dos argumentos:
-
Los cables del qubit a medir
-
Los hilos clásicos en los que almacenar los bits resultantes
Este fragmento de código utiliza el método measure()
, y la Figura 1-5 muestra un dibujo del circuito resultante:
qc
=
QuantumCircuit
(
3
,
3
)
qc
.
h
([
0
,
1
,
2
])
qc
.
measure
([
0
,
1
,
2
],
[
0
,
1
,
2
])
qc
.
draw
()
Observa que el método measure()
añade al circuito las operaciones de medida solicitadas.
Utilizar el método measure_all()
El método measure_all()
se puede llamar sin argumentos a . Este fragmento de código utiliza el método measure_all()
, y la Figura 1-6 muestra un dibujo del circuito resultante:
qc
=
QuantumCircuit
(
3
)
qc
.
h
([
0
,
1
,
2
])
qc
.
measure_all
()
qc
.
draw
()
Observa que el método measure_all()
creó tres hilos clásicos y añadió una barrera al circuito antes de añadir las operaciones de medición .
Obtener información sobre un circuito cuántico
Los métodos utilizados habitualmente para obtener información sobre un circuito cuántico incluyen depth()
, size()
y width()
. Se enumeran en la Tabla 1-3. Observa que la variable qc
se refiere a una instancia de QuantumCircuit
.
Nombres | Ejemplo | Notas |
---|---|---|
|
|
Devuelve la profundidad (ruta crítica) de un circuito si se han eliminado directivas como barrera |
|
|
Devuelve el número total de operaciones de puerta en un circuito |
|
|
Devuelve la suma de los hilos qubits y los hilos clásicos de un circuito |
Los atributos utilizados habitualmente para obtener información sobre un circuito cuántico son clbits
, data
, global_phase
, num_clbits
, num_qubits
y qubits
. Se enumeran en la Tabla 1-4. Observa que la variable qc
se refiere a una instancia de QuantumCircuit
.
Nombres | Ejemplo | Notas |
---|---|---|
|
|
Obtiene la lista de bits clásicos en el orden en que se añadieron los registros |
|
|
Obtiene una lista de las operaciones (por ejemplo, puertas, barreras y operaciones de medida) del circuito |
|
|
Obtiene la fase global del circuito en radianes |
|
|
Obtiene el número de hilos clásicos del circuito |
|
|
Obtiene el número de hilos cuánticos del circuito |
|
|
Obtiene la lista de bits cuánticos en el orden en que se añadieron los registros |
Manipular un circuito cuántico
Entre los métodos utilizados habitualmente para manipular circuitos cuánticos se incluyen append()
, bind_parameters()
, compose()
, copy()
, decompose()
, from_qasm_file()
, from_qasm_str()
, initialize()
, reset()
, qasm()
, to_gate()
, y to_instruction()
.
Utilizar el método append()
El método append()
añade una instrucción o puerta al final del circuito en los hilos especificados, modificando el circuito en su lugar. El siguiente fragmento de código utiliza el método append()
, y la Figura 1-7 muestra un dibujo del circuito resultante:
from
qiskit.circuit.library
import
CXGate
qc
=
QuantumCircuit
(
2
)
qc
.
h
(
1
)
cx_gate
=
CXGate
()
qc
.
append
(
cx_gate
,
[
1
,
0
])
qc
.
draw
()
Nota
La clase CXGate
(véase "CXGate") utilizada aquí es una de las puertas definidas en el paquete qiskit.circuit.library
. Te aconsejamos que añadas las declaraciones import
adecuadas a los fragmentos de código de este libro.
Utilizar el método bind_parameters()
El método bind_parameters()
vincula parámetros (ver "Crear una instancia de parámetro") a un circuito cuántico. El siguiente fragmento de código crea un circuito en el que hay tres puertas de fase parametrizadas. Observa que los argumentos de los constructores Parameter
de este fragmento de código son cadenas, en este caso unas que contienen caracteres theta. La Figura 1-8 muestra un dibujo del circuito:
from
qiskit.circuit
import
QuantumCircuit
,
\Parameter
theta1
=
Parameter
(
'θ1'
)
theta2
=
Parameter
(
'θ2'
)
theta3
=
Parameter
(
'θ3'
)
qc
=
QuantumCircuit
(
3
)
qc
.
h
([
0
,
1
,
2
])
qc
.
p
(
theta1
,
0
)
qc
.
p
(
theta2
,
1
)
qc
.
p
(
theta3
,
2
)
qc
.
draw
()
Para vincular los valores de los parámetros a un circuito nuevo, pasaremos un diccionario que contenga las referencias de los parámetros y los valores deseados al método bind_parameters()
. El siguiente fragmento de código utiliza esta técnica, y la Figura 1-9 muestra el circuito enlazado en el que los parámetros de la puerta de fase se sustituyen por los valores suministrados:
b_qc
=
qc
.
bind_parameters
({
theta1
:
math
.
pi
/
8
,
theta2
:
math
.
pi
/
4
,
theta3
:
math
.
pi
/
2
})
b_qc
.
draw
()
Utilizar el método componer()
El método compose()
devuelve un nuevo circuito compuesto por el original y otro circuito. El siguiente fragmento de código utiliza el método compose()
, y la Figura 1-10 muestra un dibujo del circuito resultante:
qc
=
QuantumCircuit
(
2
,
2
)
qc
.
h
(
0
)
another_qc
=
QuantumCircuit
(
2
,
2
)
another_qc
.
cx
(
0
,
1
)
bell_qc
=
qc
.
compose
(
another_qc
)
bell_qc
.
draw
()
Ten en cuenta que un circuito pasado al método compose()
puede tener menos hilos cuánticos o clásicos que el circuito original.
Utilizar el método descomponer()
El método decompose()
devuelve un nuevo circuito tras descomponer el circuito original un nivel. El siguiente fragmento de código utiliza el método decompose()
. La Figura 1-11 muestra un dibujo del circuito resultante en el que las puertas S, H y X se descomponen en las operaciones más fundamentales de la puerta U (ver "Puerta U"):
qc
=
QuantumCircuit
(
2
)
qc
.
h
(
0
)
qc
.
s
(
0
)
qc
.
x
(
1
)
decomposed_qc
=
qc
.
decompose
()
decomposed_qc
.
draw
()
Utilizar el método from_qasm_file()
El método from_qasm_file()
devuelve un nuevo circuito a partir de un archivo que contiene un programa en lenguaje ensamblador cuántico (OpenQASM). El siguiente fragmento de código utiliza el método from_qasm_file()
:
new_qc
=
QuantumCircuit
.
from_qasm_file
(
"file.qasm"
)
Utilizar el método from_qasm_str()
El método from_qasm_str()
devuelve un nuevo circuito a partir de una cadena que contiene un programa OpenQASM. El siguiente fragmento de código utiliza el método from_qasm_str()
, y la Figura 1-12 muestra un dibujo del circuito resultante:
qasm_str
=
"""
OPENQASM 2.0;
include "qelib1.inc";
qreg q[2];
creg c[2];
h q[0];
cx q[0],q[1];
measure q[0] -> c[0];
measure q[1] -> c[1];
"""
new_qc
=
QuantumCircuit
.
from_qasm_str
(
qasm_str
)
new_qc
.
draw
()
Utilizar el método inicializar()
El método initialize()
inicializa los qubits de un circuito cuántico a un estado determinado y no es una operación unitaria. El código siguiente utiliza el métodoinitialize()
y la Figura 1-13 muestra un dibujo del circuito resultante. En este fragmento de código, el circuito se inicializa al vector estado normalizado :
qc
=
QuantumCircuit
(
2
)
qc
.
initialize
([
0
,
0
,
0
,
1
])
qc
.
draw
()
Utilizar el método reset()
El método reset()
restablece un qubit en un circuito cuántico a la posición y no es una operación unitaria. El siguiente fragmento de código utiliza el método reset()
, y la Figura 1-14 muestra un dibujo del circuito resultante. Observa que el estado del qubit es antes de la operación de reinicio. Este método crea una instancia Reset
(ver "Reinicio"):
qc
=
QuantumCircuit
(
1
)
qc
.
x
(
0
)
qc
.
reset
(
0
)
qc
.
draw
()
Utilizar el método qasm()
El método qasm()
devuelve un programa OpenQASM que representa el circuito cuántico. El siguiente fragmento de código utiliza el método qasm()
, y el Ejemplo 1-1 muestra el programa OpenQASM resultante:
qc
=
QuantumCircuit
(
2
,
2
)
qc
.
h
(
0
)
qc
.
cx
(
0
,
1
)
qasm_str
=
qc
.
qasm
()
(
qasm_str
)
Ejemplo 1-1. Programa OpenQASM resultante de utilizar el método qasm()
OPENQASM
2.0
;
include
"qelib1.inc"
;
qreg
q
[
2
];
creg
c
[
2
];
h
q
[
0
];
cx
q
[
0
],
q
[
1
];
Utilizar el método to_gate()
El método to_gate()
crea una puerta personalizada (ver "La clase Puerta") a partir de un circuito cuántico. El siguiente fragmento de código crea un circuito que se convertirá en una puerta, y la Figura 1-15 muestra un dibujo del circuito:
anti_cnot_qc = QuantumCircuit(2) anti_cnot_qc.x(0) anti_cnot_qc.cx(0,1) anti_cnot_qc.x(0) anti_cnot_qc.draw()
Esta puerta personalizada implementará una puerta NOT anticontrol en la que la puerta X sólo se aplica cuando el qubit de control es . El siguiente fragmento de código crea un circuito que utiliza esta puerta personalizada, y la Figura 1-16 muestra un dibujo descompuesto de este circuito:
anti_cnot_gate = anti_cnot_qc.to_gate() qc = QuantumCircuit(3) qc.x([0,1,2]) qc.append(anti_cnot_gate, [0,2]) qc.decompose().draw()
Nota
Una puerta representa una operación unitaria. Para crear una operación personalizada que no sea unitaria, utiliza el método to_instruction()
que se muestra en "Utilización del método to_instruction()".
Utilizar el método to_instruction()
El método to_instruction()
crea una instrucción personalizada (ver "La clase Instrucción") a partir de un circuito cuántico. El siguiente fragmento de código crea un circuito que se convertirá en una instrucción, y la Figura 1-17 muestra un dibujo del circuito:
reset_one_qc = QuantumCircuit(1) reset_one_qc.reset(0) reset_one_qc.x(0) reset_one_qc.draw()
Nota
Una instrucción representa una operación que no es necesariamente unitaria. Para crear una operación personalizada que sea unitaria, utiliza el método to_gate()
que se muestra en "Utilización del método to_gate()".
Esta instrucción personalizada reiniciará un qubit y aplicará una puerta X, reiniciando en efecto el qubit al estado . El siguiente fragmento de código crea un circuito que utiliza esta instrucción personalizada, y la Figura 1-18 muestra un dibujo descompuesto de este circuito en :
reset_one_inst = reset_one_qc.to_instruction() qc = QuantumCircuit(2) qc.h([0,1]) qc.reset(0) qc.append(reset_one_inst, [1]) qc.decompose().draw()
Guardar estado al ejecutar un circuito en AerSimulator
Cuando se ejecuta un circuito en un backend AerSimulator
(ver "Uso de los simuladores Aer"), el estado del simulador puede guardarse en la instancia del circuito utilizando los métodos QuantumCircuit
de la Tabla 1-5. Ten en cuenta que estos métodos están disponibles tras obtener un AerSimulator
backend.
Uso de la clase QuantumRegister
A veces resulta útil tratar grupos de hilos cuánticos o clásicos como una unidad. Por ejemplo, los qubits de control de las puertas CNOT del circuito cuántico expresado en el siguiente fragmento de código, así como en la Figura 1-19, esperan tres qubits en superposiciones iguales. El cable cuántico adicional del circuito se utiliza como zona de rascado cuya salida se desprecia:
from qiskit import QuantumRegister, \ ClassicalRegister qr = QuantumRegister(3, 'q') scratch = QuantumRegister(1, 'scratch') cr = ClassicalRegister(3, 'c') qc = QuantumCircuit(qr, scratch, cr) qc.h(qr) qc.x(scratch) qc.h(scratch) qc.cx(qr[0], scratch) qc.cx(qr[2], scratch) qc.barrier(qr) qc.h(qr) qc.measure(qr, cr) qc.draw()
Al definir un QuantumRegister
formado por tres qubits, métodos como h()
, barrier()
y measure()
pueden aplicarse a los tres hilos pasando una referencia QuantumRegister
. Del mismo modo, definir un ClassicalRegister
(ver "Uso de la clase ClassicalRegister") formado por tres bits permite al método measure()
especificar los tres hilos clásicos pasando una referencia ClassicalRegister
. Además, los nombres suministrados a los constructores QuantumRegister
y ClassicalRegister
se muestran en el dibujo del circuito.
Uso de los atributos de QuantumRegister
Los atributos QuantumRegister
y utilizados habitualmente son name
y size
. Se enumeran en la Tabla 1-6. Ten en cuenta que la variable qr
se refiere a una instancia de QuantumRegister
.
Nombres | Ejemplo | Notas |
---|---|---|
|
|
Obtiene el nombre del registro cuántico |
|
|
Obtiene el número de hilos qubit del registro cuántico |
Utilización de la clase ClassicalRegister
Consulta "Utilización de la clase QuantumRegister" para conocer las razones para utilizar la clase ClassicalRegister
.
Uso de los atributos de ClassicalRegister
Los atributos ClassicalRegister
y utilizados habitualmente son name
y size
. Se enumeran en la Tabla 1-7. Ten en cuenta que la variable cr
se refiere a una instancia de ClassicalRegister
.
Nombres | Ejemplo | Notas |
---|---|---|
|
|
Obtiene el nombre del registro clásico |
|
|
Instrucciones y puertas
En Qiskit, todas las operaciones que pueden aplicarse a un circuito cuántico derivan de la clase Instruction
. Las operaciones unitarias se derivan de la clase Gate
, que es una subclase de Instruction
. Las operaciones unitarias controladas se derivan de la clase ControlledGate
, que es una subclase de Gate
. Estas clases pueden utilizarse para definir nuevas instrucciones, puertas unitarias y puertas unitarias controladas, respectivamente.
La Clase de Instrucción
Las operaciones no unitarias de Qiskit (como Measure
y Reset
) son subclases directas de Instruction
. Aunque es posible definir tus propias instrucciones personalizadas subclasificando Instruction
, otra forma es utilizar el método to_instruction()
de la clase QuantumCircuit
(consulta un ejemplo de esto en "Utilización del método to_instruction()").
Los métodos de la clase Instruction
incluyen copy()
, repeat()
y reverse_ops()
. Se enumeran en la Tabla 1-8. Observa que la variable inst
se refiere a una instancia de Instruction
.
Nombres | Ejemplo | Notas |
---|---|---|
|
|
Devuelve una copia de la instrucción, dando el nombre suministrado a la copia |
|
|
Devuelve una instrucción con esta instrucción repetida un número determinado de veces |
|
|
Devuelve una instrucción con sus operaciones en orden inverso |
Los atributos más utilizados en la clase Instruction
incluyen definition
y params
. Se enumeran en la Tabla 1-9. Observa que la variable inst
se refiere a una instancia de Instruction
.
Nombres | Ejemplo | Notas |
---|---|---|
|
|
Devuelve la definición en términos de puertas básicas |
|
|
Obtiene los parámetros de la instrucción |
La Clase Puerta
Las operaciones unitarias de Qiskit (como HGate
y XGate
) son subclases de Gate
. Aunque es posible definir tus propias compuertas personalizadas subclasificando Gate
, otra forma es utilizar el método to_gate()
de la clase QuantumCircuit
(consulta un ejemplo de ello en "Utilización del método to_gate()").
Los métodos más utilizados en la clase Gate
incluyen los métodos Instruction
enumerados en la Tabla 1-8, así como control()
, inverse()
, power()
y to_matrix()
. Todos ellos se enumeran en la Tabla 1-10. Observa que la variable gate
se refiere a una instancia de Gate
.
Nombres | Ejemplo | Notas |
---|---|---|
|
|
Dado un número de qubits de control, devuelve una versión controlada de la puerta |
|
|
Devuelve una copia de la puerta, dando el nombre suministrado a la copia |
|
|
Devuelve la inversa de la puerta |
|
|
Devuelve la puerta elevada a una potencia de coma flotante dada |
|
|
Devuelve una puerta con esta puerta repetida un número determinado de veces |
|
|
Devuelve una puerta con sus operaciones en orden inverso |
|
|
Devuelve una matriz para la matriz unitaria de la puerta |
Los atributos de uso común en la clase Gate
incluyen los atributos Instruction
enumerados en la Tabla 1-9, así como label
. Todos ellos se enumeran en la Tabla 1-11. Ten en cuenta que la variable gate
se refiere a una instancia de Gate
.
Nombres | Ejemplo | Notas |
---|---|---|
|
|
Devuelve la definición en términos de puertas básicas |
|
|
Obtiene la etiqueta de la instrucción |
|
|
Obtiene los parámetros de la instrucción |
La clase ControlledGate
Las operaciones unitarias controladas en Qiskit (como CZGate
y CCXGate
) son subclases de ControlledGate
, que es una subclase de Gate
.
Los métodos más utilizados en la clase ControlledGate
son los métodos Gate
enumerados en la Tabla 1-10
Los atributos de uso común en la clase ControlledGate
incluyen los atributos Gate
enumerados en la Tabla 1-11, así como num_ctrl_qubits
y ctrl_state
.
Utilizar el atributo num_ctrl_qubits
El atributo num_ctrl_qubits
contiene un entero que representa el número de qubits de control en una ControlledGate
. El siguiente fragmento de código, cuya salida impresa sería 2, utiliza el atributo num_ctrl_qubits
de una puerta Toffoli:
from
qiskit.circuit.library
import
CCXGate
toffoli
=
CCXGate
()
(
toffoli
.
num_ctrl_qubits
)
Utilizar el método ctrl_state()
Un ControlledGate
puede tener uno o más qubits de control, cada uno de los cuales puede ser, en realidad, qubits de control o de anticontrol (consulta el ejemplo de anticontrol en "Uso del método to_gate()"). El atributo ctrl_state
contiene un número entero cuyo valor binario representa qué qubits son de control y cuáles son de anticontrol. En concreto, el dígito binario 1
representa un qubit de control, y el dígito binario 0
representa un qubit de anticontrol.
El atributo ctrl_state
permite tanto acceder a su valor como modificarlo. El siguiente fragmento de código utiliza el atributo ctrl_state
, en el que el valor binario 10
hace que el qubit de control superior sea un qubit de anticontrol. La Figura 1-20 muestra un dibujo del circuito resultante:
toffoli
=
CCXGate
()
toffoli
.
ctrl_state
=
2
toffoli
.
definition
.
draw
()
Definir una puerta controlada personalizada
Aunque es posible definir tus propias compuertas controladas personalizadas subclasificando ControlledGate
, otra forma es seguir estos dos pasos:
-
Crea una puerta personalizada con el método
to_gate()
de la claseQuantumCircuit
(consulta un ejemplo en "Utilización del método to_gate()"). -
Añade qubits de control a tu puerta personalizada utilizando el
control()
que se muestra en la Tabla 1-10.
Seguiremos esos dos pasos para definir una puerta controlada personalizada que aplique una rotación de fase π/16 cuando sus dos qubits de control sean . En primer lugar, el siguiente fragmento de código define un circuito que contiene una puerta π/16 P y lo convierte en una puerta personalizada, y la Figura 1-21 muestra un dibujo de la puerta personalizada:
from
qiskit
import
QuantumCircuit
import
math
p16_qc
=
QuantumCircuit
(
1
)
p16_qc
.
p
(
math
.
pi
/
16
,
0
)
p16_gate
=
p16_qc
.
to_gate
()
p16_gate
.
definition
.
draw
()
En segundo lugar, el siguiente fragmento de código utiliza el método control()
para crear un ControlledGate
a partir de nuestra compuerta personalizada, y la Figura 1-22 muestra un dibujo de la compuerta controlada personalizada:
ctrl_p16
=
p16_gate
.
control
(
2
)
ctrl_p16
.
definition
.
draw
()
Aprovecharemos el método append()
(ver "Uso del método append()") en el siguiente fragmento de código para utilizar nuestra puerta controlada personalizada en un circuito cuántico. La Figura 1-23 muestra un dibujo de el circuito:
qc
=
QuantumCircuit
(
4
)
qc
.
h
([
0
,
1
,
2
,
3
])
qc
.
append
(
ctrl_p16
,[
0
,
1
,
3
])
qc
.
decompose
()
.
draw
()
Circuitos cuánticos parametrizados
A veces es útil crear un circuito cuántico en el que se puedan suministrar valores en tiempo de ejecución. Esta capacidad está disponible en Qiskit mediante circuitos parametrizados, implementados en parte por las clases Parameter
y ParameterVector
.
Crear una instancia de parámetro
La clase Parameter
se utiliza para representar un parámetro en un circuito cuántico. Consulta "Utilización del método bind_parameters()" para ver un ejemplo de definición y utilización de un circuito parametrizado. Como se muestra en ese ejemplo, se puede crear un parámetro suministrando una cadena unicode a su constructor de la siguiente manera:
theta1 = Parameter("θ1")
La referencia al objeto Parameter
denominada theta1
puede utilizarse posteriormente en el método bind_parameters()
o, alternativamente, en el método assign_parameters()
de la clase QuantumCircuit
.
Utilización de la clase ParameterVector
La clase ParameterVector
puede aprovecharse para crear y utilizar parámetros como una colección en lugar de variables individuales. El siguiente fragmento de código crea un circuito en el que hay tres puertas de fase parametrizadas. La Figura 1-24 muestra un dibujo del circuito:
from
qiskit.circuit
import
QuantumCircuit
,
\ParameterVector
theta
=
ParameterVector
(
'θ'
,
3
)
qc
=
QuantumCircuit
(
3
)
qc
.
h
([
0
,
1
,
2
])
qc
.
p
(
theta
[
0
],
0
)
qc
.
p
(
theta
[
1
],
1
)
qc
.
p
(
theta
[
2
],
2
)
qc
.
draw
()
Para vincular los valores de los parámetros a un circuito nuevo, pasaremos un diccionario que contenga la referencia ParameterVector
y la lista de valores deseada al método bind_parameters()
.
El siguiente fragmento de código muestra esta técnica, y la Figura 1-25 muestra el circuito límite en el que los parámetros de la puerta de fase se sustituyen por los valores suministrados por :
import
math
b_qc
=
qc
.
bind_parameters
({
theta
:
[
math
.
pi
/
8
,
math
.
pi
/
4
,
math
.
pi
/
2
]})
b_qc
.
draw
()
Get Guía de bolsillo Qiskit now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.