assert get_number_of_gate_params(ql.HGate) == 0
assert get_number_of_gate_params(ql.CXGate) == 0
assert get_number_of_gate_params(ql.U1Gate) == 1
assert get_number_of_gate_params(ql.U2Gate) == 2
assert get_number_of_gate_params(ql.U3Gate) == 3
Qiskit circuits backend
Qiskit based quantum circuit backend.
Utils
get_number_of_gate_params
get_number_of_gate_params (gate_cls:type[qiskit.circuit.gate.Gate])
instruction_name_to_qiskit_gate
instruction_name_to_qiskit_gate (name:str)
get_target_control_qubits
get_target_control_qubits (qc:qiskit.circuit.quantumcircuit.QuantumCircu it, gate:qiskit.circuit.gate.Gate)
Get the target and control qubits of a Qiskit Gate
of a QuantumCircuit
.
Backend
CircuitsQiskitBackend
CircuitsQiskitBackend ()
Backends implement at least these functions.
Test
from genQC.platform.tokenizer.circuits_tokenizer import CircuitTokenizer
genqc <-> backend
= torch.tensor([
tensor 3, 0, -2, 0, 0],
[0, 0, 2, 0, 1],
[0, 3, -2, 3, 0],
[=torch.int32)
], dtype
= torch.tensor([ # ... [max_params, time]
params_tensor 0, 0, 0, 0, 0.9],
[0, 0, 0, 0, -0.7]
[
])
= {"u2":1, "ccx":2, "h":3}
vocabulary = CircuitTokenizer(vocabulary)
tokenizer = tokenizer.decode(tensor, params_tensor)
instructions
print() instructions.
CircuitInstruction(name='h', control_nodes=[], target_nodes=[0], params=[6.2831854820251465, 6.2831854820251465])
CircuitInstruction(name='h', control_nodes=[], target_nodes=[2], params=[6.2831854820251465, 6.2831854820251465])
CircuitInstruction(name='ccx', control_nodes=[0, 2], target_nodes=[1], params=[6.2831854820251465, 6.2831854820251465])
CircuitInstruction(name='h', control_nodes=[], target_nodes=[2], params=[6.2831854820251465, 6.2831854820251465])
CircuitInstruction(name='u2', control_nodes=[], target_nodes=[1], params=[11.9380521774292, 1.8849557638168335])
= CircuitsQiskitBackend()
backend
= backend.genqc_to_backend(instructions)
qc "mpl") qc.draw(
= backend.backend_to_genqc(qc)
dec_instructions print() dec_instructions.
CircuitInstruction(name='h', control_nodes=[], target_nodes=[0], params=[])
CircuitInstruction(name='h', control_nodes=[], target_nodes=[2], params=[])
CircuitInstruction(name='ccx', control_nodes=[0, 2], target_nodes=[1], params=[])
CircuitInstruction(name='h', control_nodes=[], target_nodes=[2], params=[])
CircuitInstruction(name='u2', control_nodes=[], target_nodes=[1], params=[11.9380521774292, 1.8849557638168335])
= tokenizer.encode(dec_instructions)
enc_tensor, enc_params_tensor enc_tensor, enc_params_tensor
(tensor([[ 3, 0, -2, 0, 0],
[ 0, 0, 2, 0, 1],
[ 0, 3, -2, 3, 0]], dtype=torch.int32),
tensor([[ 0.0000, 0.0000, 0.0000, 0.0000, 0.9000],
[ 0.0000, 0.0000, 0.0000, 0.0000, -0.7000]]))
assert torch.allclose(tensor, enc_tensor)
assert torch.allclose(params_tensor, enc_params_tensor)
Calculate unitary and optimize circuit
= ["u3", "cx", "h"]
gate_pool = backend.rnd_circuit(2, 10, gate_pool, np.random.default_rng())
qc = backend.get_unitary(qc)
U_initial
= backend.optimize_circuit(qc, gate_pool, silent=0)
qc_opt = backend.get_unitary(qc_opt, remove_global_phase=False)
U_opt
print(np.round(U_initial, 2))
assert np.allclose(U_initial, U_opt)
[[ 0.64+0.59j -0.25+0.04j -0.31-0.27j 0.12-0.02j]
[-0.18-0.18j -0.86+0.11j 0.09+0.08j 0.41-0.06j]
[-0.11+0.05j -0.11+0.4j -0.23+0.1j -0.21+0.84j]
[ 0.37-0.17j -0.03+0.12j 0.78-0.39j -0.05+0.25j]]
= %timeit -o -q backend.get_unitary(qc)
res print(f"Timeit get_unitary: {str(res)}")
Timeit get_unitary: 524 μs ± 407 ns per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
print(f"Initial number of gates {len(qc.data)}:")
"mpl"))
display(qc.draw(
print(f"After optimization {len(qc_opt.data)}:")
"mpl")) display(qc_opt.draw(
Initial number of gates 10:
After optimization 3:
= backend.randomize_params(qc_opt, np.random.default_rng())
qc_rand "mpl")) display(qc_rand.draw(
Schmidt-rank-vector
def plot_srv_stat(num_of_qubits, min_gates, max_gates, gate_pool, samples, rng=np.random.default_rng()):
= list()
srv_list for i in range(samples):
= backend.rnd_circuit(num_of_qubits, rng.integers(min_gates, max_gates+1), gate_pool, rng)
qc = backend.optimize_circuit(qc, gate_pool)
qc = backend.schmidt_rank_vector(qc)
srv
srv_list.append(srv)
= np.unique(np.array(srv_list), axis=0, return_counts=True)
srv_unique, srv_cnt = [f"{s}" for s in srv_unique]
srv_unique
plt.bar(srv_unique, srv_cnt)"Different SRV distribution")
plt.title( plt.show()
= [ql.HGate, ql.CXGate]
gate_pool
=3, min_gates=6, max_gates=8, gate_pool=gate_pool, samples=int(1e3), rng=np.random.default_rng()) plot_srv_stat(num_of_qubits
def test_srv(system_dims, init, target):
= qi.Statevector(init, dims=system_dims)
vec *= 1/np.sqrt(vec.trace())
vec = backend.schmidt_rank_vector(densityMatrix=qi.DensityMatrix(vec))
srv assert srv == target, f"srv: {srv}"
print(f"passed test, svr: {srv}")
'latex', prefix='|\\psi\\rangle = ')) display(vec.draw(
#---------------- |0+> = |00>+|01>
= (2,2)
system_dims = np.zeros(np.prod(system_dims), dtype=complex)
init 0] = 1
init[1] = 1
init[1, 1])
test_srv(system_dims, init, [
#----------------Bell, |00>+|11>
= (2,2)
system_dims = np.zeros(np.prod(system_dims), dtype=complex)
init 0] = 1
init[3] = 1
init[2, 2])
test_srv(system_dims, init, [
#----------------GHZ, |000>+|111>
= (2,2,2)
system_dims = np.zeros(np.prod(system_dims), dtype=complex)
init 0] = 1
init[7] = 1
init[2,2,2])
test_srv(system_dims, init, [
#----------------Sym, |000>+|111>+|222>
= (3,3,3)
system_dims = np.zeros(np.prod(system_dims), dtype=complex)
init 0] = 1
init[13] = 1
init[26] = 1
init[3,3,3])
test_srv(system_dims, init, [
#----------------Wikipedia example, |000>+|101>+|210>+|311>
= (4,4,4)
system_dims = np.zeros(np.prod(system_dims), dtype=complex)
init 0] = 1
init[17] = 1
init[36] = 1
init[53] = 1
init[2, 2, 4]) test_srv(system_dims, init, [
passed test, svr: [1, 1]
\[|\psi\rangle = \frac{\sqrt{2}}{2} |00\rangle+\frac{\sqrt{2}}{2} |01\rangle\]
passed test, svr: [2, 2]
\[|\psi\rangle = \frac{\sqrt{2}}{2} |00\rangle+\frac{\sqrt{2}}{2} |11\rangle\]
passed test, svr: [2, 2, 2]
\[|\psi\rangle = \frac{\sqrt{2}}{2} |000\rangle+\frac{\sqrt{2}}{2} |111\rangle\]
passed test, svr: [3, 3, 3]
$$\[\begin{align} |\psi\rangle = \begin{bmatrix} \frac{\sqrt{3}}{3} & 0 & 0 & 0 & \cdots & 0 & 0 & \frac{\sqrt{3}}{3} \\ \end{bmatrix} \\ \text{dims=(3, 3, 3)} \end{align}\]$$
passed test, svr: [2, 2, 4]
$$\[\begin{align} |\psi\rangle = \begin{bmatrix} \frac{1}{2} & 0 & 0 & 0 & \cdots & 0 & 0 & 0 \\ \end{bmatrix} \\ \text{dims=(4, 4, 4)} \end{align}\]$$