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()