Quantum circuit simulator¶
In [1]:
Copied!
import numpy as np
import matplotlib.pyplot as plt
try:
import numqi
except ImportError:
%pip install numqi
import numqi
import numpy as np
import matplotlib.pyplot as plt
try:
import numqi
except ImportError:
%pip install numqi
import numqi
First quantum circuit¶
Build a non-trivial quantum circuit
In [2]:
Copied!
circ = numqi.sim.Circuit()
for x in range(4):
circ.H(x)
circ.cz(3, 4)
circ.cy(2, 3)
circ.cz(2, 4)
circ.cx(1, 2)
circ.cz(1, 3)
circ.cx(1, 4)
circ.cy(0, 2)
circ.cx(0, 3)
circ.cx(0, 4)
circ = numqi.sim.Circuit()
for x in range(4):
circ.H(x)
circ.cz(3, 4)
circ.cy(2, 3)
circ.cz(2, 4)
circ.cx(1, 2)
circ.cz(1, 3)
circ.cx(1, 4)
circ.cy(0, 2)
circ.cx(0, 3)
circ.cx(0, 4)
Out[2]:
Gate(control, cnot, requires_grad=False, array([[0., 1.], [1., 0.]]))
with variable circ
, one can check its properties
In [3]:
Copied!
circ.num_qubit #5
circ.num_qubit #5
Out[3]:
5
Given a initial state (simply a 1-dimensional numpy array), circ
can produce the final state (out-of-place operation)
In [4]:
Copied!
qin0 = np.zeros(2**5, dtype=np.complex128)
qin0[0] = 1
# q0 = numqi.sim.state.new_base(5)
qout0 = circ.apply_state(qin0)
qin1 = np.zeros(2**5, dtype=np.complex128)
qin1[1] = 1
qout1 = circ.apply_state(qin1)
qin0 = np.zeros(2**5, dtype=np.complex128)
qin0[0] = 1
# q0 = numqi.sim.state.new_base(5)
qout0 = circ.apply_state(qin0)
qin1 = np.zeros(2**5, dtype=np.complex128)
qin1[1] = 1
qout1 = circ.apply_state(qin1)
Above, qin0
and qin1
are two computational basis states. qout0
and qout1
is the corresponding output quantum state vectors. Actually, the qout0
and qout1
is the ((5,2,3))
quantum error correcting code wiki/five-qubit-code which will be discussed later. We can also retrieve the full unitary matrix.
In [5]:
Copied!
mat = circ.to_unitary() #(np,complex128,(32,32))
print(mat.shape)
mat = circ.to_unitary() #(np,complex128,(32,32))
print(mat.shape)
(32, 32)
Parametrized quantum circuit¶
In [6]:
Copied!
circ = numqi.sim.Circuit(default_requires_grad=False)
gate0 = circ.ry(1)
circ.H(1)
circ.cnot(0, 1)
circ = numqi.sim.Circuit(default_requires_grad=False)
gate0 = circ.ry(1)
circ.H(1)
circ.cnot(0, 1)
Out[6]:
Gate(control, cnot, requires_grad=False, array([[0., 1.], [1., 0.]]))
above we create a circuit with parameterized gate gate0
. We can modify the parameter in gate0
to get different expectation (say Pauli-Z on qubit q1
)
In [7]:
Copied!
initial_state = numqi.sim.state.new_base(2)
theta = np.linspace(0, 4*np.pi)
op = [[(numqi.gate.Z,1)]]
expectation = []
for x in theta:
gate0.set_args([x])
psi = circ.apply_state(initial_state)
expectation.append(numqi.sim.state.inner_product_psi0_O_psi1(psi, psi, op).item().real)
fig,ax = plt.subplots()
ax.plot(theta, expectation)
ax.set_xlabel(r'$\theta$')
ax.grid()
fig.tight_layout()
initial_state = numqi.sim.state.new_base(2)
theta = np.linspace(0, 4*np.pi)
op = [[(numqi.gate.Z,1)]]
expectation = []
for x in theta:
gate0.set_args([x])
psi = circ.apply_state(initial_state)
expectation.append(numqi.sim.state.inner_product_psi0_O_psi1(psi, psi, op).item().real)
fig,ax = plt.subplots()
ax.plot(theta, expectation)
ax.set_xlabel(r'$\theta$')
ax.grid()
fig.tight_layout()