forked from miles0428/GA-Quantum-State-Prepare
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgene.py
153 lines (133 loc) · 6.76 KB
/
gene.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
'''
This file is used to generate a quantum circuit from a gene
author : Yu-Cheng Chung
email : ycchung@ntnu.edu.tw
date : 2023 12 oct
dependencies:
qiskit
numpy
'''
import qiskit as qk
import numpy as np
class Gene_Circuit(object):
'''
Gene Circuit
Methods:
generate_circuit_from_gene: generate a quantum circuit with num_qubit qubits
circuit_0 ~ circuit_10: quantum circuit connect with gene
'''
def __init__(self,gene,num_qubit) -> None:
'''
Args:
gene: a array with shape (num_qubit, length_gene) with element called G_ij
num_qubit: number of qubits
object:
self.gene: a array with shape (num_qubit, length_gene) with element called G_ij
self.num_qubit: number of qubits
self.circuit: a quantum circuit with num_qubit qubits generated from gene
self.draw: draw the circuit
'''
self.gene = gene
self.num_qubit = num_qubit
self.circuit = qk.transpile(self.generate_circuit_from_gene())
self.draw = self.circuit.draw
self.num_parameters = self.circuit.num_parameters
self.depth = self.circuit.depth
def bind_parameters(self, theta : list|np.ndarray) -> qk.QuantumCircuit:
'''
bind parameter to the circuit
Args:
theta: a list of theta
Returns:
bind_circuit: a quantum circuit with parameter binded
'''
binded_circuit = self.circuit.bind_parameters({self.circuit.parameters[i]:theta[i] for i in range(len(theta))})
return binded_circuit
def generate_circuit_from_gene(self)->qk.QuantumCircuit:
'''
Generate a quantum circuit with num_qubit qubits
Args:
self.gene: a array with shape (num_qubit, length_gene) with element called G_ij
self.num_qubit: number of qubits
Returns:
circuit: a quantum circuit
The circuit is generated by the following rule:
------------------------------------------------
| G_00 | G_01 | G_02 | G_03 | G_04 | ...| G_0m |
------------------------------------------------
| G_10 | G_11 | G_12 | G_13 | G_14 | ...| G_1m |
------------------------------------------------
...
------------------------------------------------
| G_n0 | G_n1 | G_n2 | G_n3 | G_n4 | ...| G_nm |
------------------------------------------------
G_ij is the j-th gate of the i-th qubit
G_ij will look like tuple(gate,cotrol)
gate is the index of the gate in gene_gates
control is the index of the control qubit
(if the gate have no control, will ignore the control value)
'''
#gene_gates is a list of gates use to generate the circuit
gene_gates = ['empty','empty','empty','rx','ry','rz','cx']
theta_index = 0
circuit = qk.QuantumCircuit(self.num_qubit)
gene = self.gene
gene = gene.transpose(1,0,2)
temp_last_gate = ['empty' for i in range(self.num_qubit)]
count_rgate = [0 for i in range(self.num_qubit)]
for j,G_nj in enumerate(gene):
for i,G_ij in enumerate(G_nj):
gate = gene_gates[G_ij[0]]
if gate == temp_last_gate[i] and gate in ['rx','ry','rz','h','x','sx']:
continue
control = G_ij[1]
if control >= self.num_qubit:
control = control % self.num_qubit
if gate == 'empty':
continue
elif gate in ['rx','ry','rz']:
if count_rgate[i]>=3:
continue
getattr(circuit,gate)(qk.circuit.Parameter(f'theta_{theta_index}'),i)
temp_last_gate[i] = gate
count_rgate[i]+=1
theta_index+=1
elif gate == 'cx':
if control == i:
continue
else:
circuit.cx(control,i)
temp_last_gate[control] = 'empty'
temp_last_gate[i] = gate
count_rgate[control] = 0
count_rgate[i] = 0
elif gate in ['h','x','sx']:
getattr(circuit,gate)(i)
temp_last_gate[i] = gate
count_rgate[i] = 0
# circuit.draw("mpl",filename='test3.png')
return circuit
if __name__ == '__main__':
'''
test gene:
np.random.seed(776)
gene = np.random.randint(0,7,size=(4,8,2))
the circuit would look like:
┌───┐ ┌─────────────┐ ┌───┐ ┌─────────────┐┌─────────────┐
q_0: ────────────────────┤ X ├─────┤ Rx(theta_3) ├─────┤ X ├─────┤ Ry(theta_7) ├┤ Rz(theta_8) ├
┌─────────────┐ └─┬─┘ ├─────────────┤ └─┬─┘ ├─────────────┤└────┬───┬────┘
q_1: ┤ Ry(theta_0) ├───────┼───────┤ Rz(theta_4) ├───────■───────┤ Rz(theta_5) ├─────┤ X ├─────
└─────────────┘ │ └─────────────┘ └─────────────┘ └─┬─┘
q_2: ──────────────────────■───────────────────────────────────────────────────────────■───────
┌─────────────┐┌─────────────┐┌─────────────┐
q_3: ───────────────┤ Rz(theta_1) ├┤ Rx(theta_2) ├┤ Rz(theta_6) ├──────────────────────────────
└─────────────┘└─────────────┘└─────────────┘
'''
np.random.seed(776)
gene = np.random.randint(0,7,size=(4,8,2))
num_qubit = 4
gene_circuit = Gene_Circuit(gene,num_qubit)
print(gene)
print(gene_circuit.draw())
print(gene_circuit.num_parameters)
print(gene_circuit.depth())