Skip to content

Commit f224889

Browse files
committed
Merge branch 'documentation' of github.com:tqsd/EQSN_python
2 parents 87afb4c + d34e8cc commit f224889

5 files changed

Lines changed: 284 additions & 21 deletions

File tree

eqsn/gates.py

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ def stop_all(self):
6767
def X_gate(self, q_id):
6868
"""
6969
Applies the Pauli X gate to the Qubit with q_id.
70+
71+
Args:
72+
q_id(String): ID of the Qubit to apply the gate to.
7073
"""
7174
x = np.array([[0, 1], [1, 0]], dtype=np.csingle)
7275
q = self.shared_dict.get_queues_for_ids([q_id])[0]
@@ -75,6 +78,9 @@ def X_gate(self, q_id):
7578
def Y_gate(self, q_id):
7679
"""
7780
Applies the Pauli Y gate to the Qubit with q_id.
81+
82+
Args:
83+
q_id(String): ID of the Qubit to apply the gate to.
7884
"""
7985
x = np.array([[0, 0 - 1j], [0 + 1j, 0]], dtype=np.csingle)
8086
q = self.shared_dict.get_queues_for_ids([q_id])[0]
@@ -83,6 +89,9 @@ def Y_gate(self, q_id):
8389
def Z_gate(self, q_id):
8490
"""
8591
Applies the Pauli Z gate to the Qubit with q_id.
92+
93+
Args:
94+
q_id(String): ID of the Qubit to apply the gate to.
8695
"""
8796
x = np.array([[1, 0], [0, -1]], dtype=np.csingle)
8897
q = self.shared_dict.get_queues_for_ids([q_id])[0]
@@ -91,6 +100,9 @@ def Z_gate(self, q_id):
91100
def H_gate(self, q_id):
92101
"""
93102
Applies the Hadamard gate to the Qubit with q_id.
103+
104+
Args:
105+
q_id(String): ID of the Qubit to apply the gate to.
94106
"""
95107
x = (1 / 2.0) ** 0.5 * np.array([[1, 1], [1, -1]], dtype=np.csingle)
96108
q = self.shared_dict.get_queues_for_ids([q_id])[0]
@@ -99,6 +111,9 @@ def H_gate(self, q_id):
99111
def T_gate(self, q_id):
100112
"""
101113
Applies the T gate to the Qubit with q_id.
114+
115+
Args:
116+
q_id(String): ID of the Qubit to apply the gate to.
102117
"""
103118
x = np.array(
104119
[[1, 0], [0, (0.7071067811865476 + 0.7071067811865475j)]],
@@ -109,6 +124,9 @@ def T_gate(self, q_id):
109124
def S_gate(self, q_id):
110125
"""
111126
Applies the S gate to the Qubit with q_id.
127+
128+
Args:
129+
q_id(String): ID of the Qubit to apply the gate to.
112130
"""
113131
x = np.array([[1, 0], [0, 1j]], dtype=np.csingle)
114132
q = self.shared_dict.get_queues_for_ids([q_id])[0]
@@ -117,14 +135,21 @@ def S_gate(self, q_id):
117135
def K_gate(self, q_id):
118136
"""
119137
Applies the K gate to the Qubit with q_id.
138+
139+
Args:
140+
q_id(String): ID of the Qubit to apply the gate to.
120141
"""
121142
x = 0.5 * np.array([[1+1j, 1-1j], [-1+1j, -1-1j]], dtype=np.csingle)
122143
q = self.shared_dict.get_queues_for_ids([q_id])[0]
123144
q.put([SINGLE_GATE, x, q_id])
124145

125146
def RX_gate(self, q_id, rad):
126147
"""
127-
Applies the T gate to the Qubit with q_id.
148+
Applies a rotational X gate to the Qubit with q_id.
149+
150+
Args:
151+
q_id(String): ID of the Qubit to apply the gate to.
152+
rad(int): Rotational degrees in rad.
128153
"""
129154
mid = np.cos(rad / 2)
130155
other = -1j * np.sin(rad / 2)
@@ -134,7 +159,11 @@ def RX_gate(self, q_id, rad):
134159

135160
def RY_gate(self, q_id, rad):
136161
"""
137-
Applies the T gate to the Qubit with q_id.
162+
Applies a rotational Y gate to the Qubit with q_id.
163+
164+
Args:
165+
q_id(String): ID of the Qubit to apply the gate to.
166+
rad(int): Rotational degrees in rad.
138167
"""
139168
mid = np.cos(rad / 2)
140169
other = np.sin(rad / 2)
@@ -144,7 +173,11 @@ def RY_gate(self, q_id, rad):
144173

145174
def RZ_gate(self, q_id, rad):
146175
"""
147-
Applies the T gate to the Qubit with q_id.
176+
Applies a rotational Z gate to the Qubit with q_id.
177+
178+
Args:
179+
q_id(String): ID of the Qubit to apply the gate to.
180+
rad(int): Rotational degrees in rad.
148181
"""
149182
top = np.exp(-1j * (rad / 2))
150183
bot = np.exp(1j * (rad / 2))
@@ -155,6 +188,10 @@ def RZ_gate(self, q_id, rad):
155188
def custom_gate(self, q_id, gate):
156189
"""
157190
Applies a custom gate to the qubit with q_id.
191+
192+
Args:
193+
q_id(String): Id of the Qubit to apply the gate on.
194+
gate(np.ndarray): unitary 2x2 matrix, of the gate.
158195
"""
159196
q = self.shared_dict.get_queues_for_ids([q_id])[0]
160197
q.put([SINGLE_GATE, gate, q_id])
@@ -216,18 +253,45 @@ def cphase_gate(self, applied_to_id, controlled_by_id):
216253
q.put([CONTROLLED_GATE, x, applied_to_id, controlled_by_id])
217254

218255
def give_statevector_for(self, q_id):
256+
"""
257+
Gives the statevector and Qubits of a Qubit and all other Qubits with
258+
which the qubit is entangled.
259+
260+
Args:
261+
q_id(String): Qubit id of the Qubit to get the statevector from.
262+
263+
Returns:
264+
Tuple. Tuple of a lists and vector, where the first list are the qubits of
265+
the statevector and the second list is the statevector.
266+
"""
219267
ret = self.manager.Queue()
220268
q = self.shared_dict.get_queues_for_ids([q_id])[0]
221269
q.put([GIVE_STATEVECTOR, q_id, ret])
222270
qubits, vector = ret.get()
223271
return qubits, vector
224272

225273
def custom_two_qubit_gate(self, q_id1, q_id2, gate):
274+
"""
275+
Applies a two Qubit gate to two Qubits.
276+
277+
Args:
278+
q_id1(String): ID of the first Qubit of the gate.
279+
q_id2(String): ID of the second Qubit of the gate.
280+
gate(np.ndarray): 4x4 unitary matrix gate.
281+
"""
226282
self.merge_qubits(q_id1, q_id2)
227283
q = self.shared_dict.get_queues_for_ids([q_id1])[0]
228284
q.put([DOUBLE_GATE, gate, q_id1, q_id2])
229285

230286
def custom_controlled_gate(self, applied_to_id, controlled_by_id, gate):
287+
"""
288+
Applies a custom controlled gate to a Qubit.
289+
290+
Args:
291+
applied_to_id(String): ID of the qubit to apply the gate to.
292+
controlled_by_id(String): ID of the qubit which controls the gate.
293+
gate(np.ndarray): Unitary 2x2 matrix which should be applied.
294+
"""
231295
self.merge_qubits(applied_to_id, controlled_by_id)
232296
q = self.shared_dict.get_queues_for_ids([applied_to_id])[0]
233297
q.put([CONTROLLED_GATE, gate, applied_to_id, controlled_by_id])

eqsn/process_picker.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,25 @@ class ProcessPicker(object):
55
__instance = None
66

77
@staticmethod
8-
def get_instance(cpu_count, process_queue_list):
8+
def get_instance(amount_processes, process_queue_list):
9+
"""
10+
Gets the existing instance of the Process Picker class. If none exists,
11+
a new object o the class is created.
12+
13+
Args:
14+
cpu_count(int): The amount of CPU cores.
15+
process_queue_list(List): A List of all Processes.
16+
"""
917
if ProcessPicker.__instance is None:
10-
return ProcessPicker(cpu_count, process_queue_list)
18+
return ProcessPicker(amount_processes, process_queue_list)
1119
return ProcessPicker.__instance
1220

13-
def __init__(self, cpu_count, process_queue_list):
21+
def __init__(self, amount_processes, process_queue_list):
1422
if ProcessPicker.__instance is not None:
1523
raise ValueError(
1624
"Use get instance to get the Process picker class.")
1725
ProcessPicker.__instance = self
18-
self.amount_processes = cpu_count
26+
self.amount_processes = amount_processes
1927
self.pointer = 0
2028
self.process_queue_list = process_queue_list
2129

@@ -29,4 +37,7 @@ def get_next_process_queue(self):
2937
return res_q
3038

3139
def stop_process_picker(self):
40+
"""
41+
Released the process picker object.
42+
"""
3243
ProcessPicker.__instance = None

eqsn/qubit_thread.py

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@
1818

1919

2020
class QubitThread(object):
21+
"""
22+
The Qubit thread is the smallest object in EQSN.
23+
It consists of a statevector and the Qubit IDs of the state vector.
24+
Most operations here can be applid asynchronously.
25+
"""
2126

2227
def __init__(self, q_id, queue):
2328
"""
@@ -42,15 +47,15 @@ def __init__(self, q_id, queue):
4247

4348
logging.debug("Qubit thread with qubit %s has been created.", q_id)
4449

45-
def apply_single_gate(self, mat, q_id):
50+
def apply_single_gate(self, gate, q_id):
4651
"""
4752
Applys a single gate to a qubit.
4853
4954
Args:
50-
mat (np.array): 2x2 unitary array.
55+
gate (np.array): 2x2 unitary array.
5156
id (String): Qubit on which the gate should be applied to.
5257
"""
53-
apply_mat = mat
58+
apply_mat = gate
5459
nr = self.qubits.index(q_id)
5560
total_amount = len(self.qubits)
5661
before = nr
@@ -62,11 +67,17 @@ def apply_single_gate(self, mat, q_id):
6267
self.qubit = np.dot(apply_mat, self.qubit)
6368

6469
def give_statevector(self, channel):
70+
"""
71+
Sends the Qubit IDs and their state vectors over a channel.
72+
73+
Args:
74+
channel(Queue): Channel to return the requested data to.
75+
"""
6576
channel.put((dp(self.qubits), dp(self.qubit)))
6677

6778
def apply_controlled_gate(self, mat, q_id1, q_id2):
6879
"""
69-
Apply a controlled gate to
80+
Applies a controlled gate to q_id1
7081
"""
7182
first_mat = 1
7283
second_mat = 1
@@ -111,7 +122,11 @@ def apply_controlled_gate(self, mat, q_id1, q_id2):
111122

112123
def merge_accept(self, channel):
113124
"""
114-
Receive another process to merge it with this one.
125+
Receive the statevector and qubit information of another
126+
thread with this thread and merge the vectors.
127+
128+
Args:
129+
channel(Queue): channel to receive qubit ids and statevectors from.
115130
"""
116131
ids = channel.get()
117132
vector = channel.get()
@@ -122,6 +137,11 @@ def merge_accept(self, channel):
122137
def merge_send(self, channel, chanel2):
123138
"""
124139
Send own process data to another process and suicide.
140+
141+
Args:
142+
channel(Queue): Channel to send own data to other Qubit Thread.
143+
channel2(Queue): Channel to send qubit ids to parent, to update
144+
the qubit ids in its dictionary.
125145
"""
126146
channel.put(dp(self.qubits))
127147
channel.put(dp(self.qubit))
@@ -132,6 +152,9 @@ def swap_qubits(self, q_id1, q_id2):
132152
"""
133153
Swaps the position of qubit q_id1 with q_id2
134154
in the statevector.
155+
156+
q_id1(String): Qubit id of one of the qubits to swap.
157+
q_id2(String): Qubit id of the other qubit to swap.
135158
"""
136159
def cnot(q_id1, q_id2):
137160
mat = np.asarray([[0, 1], [1, 0]])
@@ -150,7 +173,15 @@ def cnot(q_id1, q_id2):
150173
i2 = self.qubits.index(q_id2)
151174
self.qubits[i1], self.qubits[i2] = self.qubits[i2], self.qubits[i1]
152175

153-
def apply_two_qubit_gate(self, mat, q_id1, q_id2):
176+
def apply_two_qubit_gate(self, gate, q_id1, q_id2):
177+
"""
178+
Applies a two qubit gate to the statevector.
179+
180+
Args:
181+
gate(np.ndarray): 4x4 unitary matrix
182+
q_id1(String): First qubit id.
183+
q_id2(String): Second qubit id.
184+
"""
154185
# Bring the qubits in the right order
155186
i2 = self.qubits.index(q_id2)
156187
if i2 > 0:
@@ -159,7 +190,7 @@ def apply_two_qubit_gate(self, mat, q_id1, q_id2):
159190
else:
160191
self.swap_qubits(q_id1, self.qubits[0])
161192
self.swap_qubits(q_id2, self.qubits[1])
162-
apply_mat = mat
193+
apply_mat = gate
163194
nr1 = self.qubits.index(q_id1)
164195
total_amount = len(self.qubits)
165196
before = nr1
@@ -170,9 +201,13 @@ def apply_two_qubit_gate(self, mat, q_id1, q_id2):
170201
apply_mat = np.kron(apply_mat, np.eye(2 ** after))
171202
self.qubit = np.dot(apply_mat, self.qubit)
172203

173-
def measure_non_destructive(self, q_id, ret_channel):
204+
def measure_non_destructive(self, q_id, channel):
174205
"""
175206
Perform a non destructive measurement on qubit with the id.
207+
208+
Args:
209+
q_id(String): ID of the Qubit to measure.
210+
channel(Queue): Channel to transmit measurement result to.
176211
"""
177212
# determine probability for |1>
178213
measure_vec = np.array([1, 0], dtype=np.csingle)
@@ -194,11 +229,11 @@ def measure_non_destructive(self, q_id, ret_channel):
194229
reduction_mat = None
195230
if meas_res == 0:
196231
# |0> has been measured
197-
ret_channel.put(0)
232+
channel.put(0)
198233
reduction_mat = np.array([[1, 0], [0, 0]], dtype=np.csingle)
199234
else:
200235
# |1> has been measured
201-
ret_channel.put(1)
236+
channel.put(1)
202237
reduction_mat = np.array([[0, 0], [0, 1]], dtype=np.csingle)
203238
if before > 0:
204239
reduction_mat = np.kron(
@@ -212,9 +247,13 @@ def measure_non_destructive(self, q_id, ret_channel):
212247
norm = np.linalg.norm(self.qubit)
213248
self.qubit = self.qubit / norm
214249

215-
def measure(self, q_id, ret_channel):
250+
def measure(self, q_id, channel):
216251
"""
217252
Perform a destructive measurement on qubit with the id.
253+
254+
Args:
255+
q_id(String): ID of the Qubit to measure.
256+
channel(Queue): Channel to transmit measurement result to.
218257
"""
219258
# determine probability for |1>
220259
measure_vec = np.array([1, 0], dtype=np.csingle)
@@ -236,11 +275,11 @@ def measure(self, q_id, ret_channel):
236275
reduction_mat = None
237276
if meas_res == 0:
238277
# |0> has been measured
239-
ret_channel.put(0)
278+
channel.put(0)
240279
reduction_mat = np.array([1, 0], dtype=np.csingle)
241280
else:
242281
# |1> has been measured
243-
ret_channel.put(1)
282+
channel.put(1)
244283
reduction_mat = np.array([0, 1], dtype=np.csingle)
245284
if before > 0:
246285
reduction_mat = np.kron(
@@ -278,6 +317,7 @@ def run(self):
278317
elif item[0] == MERGE_ACCEPT:
279318
self.merge_accept(item[1])
280319
elif item[0] == MERGE_SEND:
320+
# After merge, this thread is not needed anymore
281321
self.merge_send(item[1], item[2])
282322
return
283323
elif item[0] == MEASURE_NON_DESTRUCTIVE:

0 commit comments

Comments
 (0)