Skip to content

Commit 197482f

Browse files
committed
Merge branch 'master' of github.com:tqsd/EQSN_python into homework_check_eqsn
2 parents 761bf60 + 315ba50 commit 197482f

File tree

5 files changed

+126
-2
lines changed

5 files changed

+126
-2
lines changed

eqsn/gates.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import logging
33
import numpy as np
44
from eqsn.qubit_thread import SINGLE_GATE, MERGE_SEND, MERGE_ACCEPT, MEASURE,\
5-
MEASURE_NON_DESTRUCTIVE, GIVE_STATEVECTOR, \
5+
MEASURE_NON_DESTRUCTIVE, GIVE_STATEVECTOR, DOUBLE_GATE, \
66
CONTROLLED_GATE, NEW_QUBIT, ADD_MERGED_QUBITS_TO_DICT
77
from eqsn.shared_dict import SharedDict
88
from eqsn.worker_process import WorkerProcess
@@ -151,6 +151,13 @@ def RZ_gate(self, q_id, rad):
151151
q = self.shared_dict.get_queues_for_ids([q_id])[0]
152152
q.put([SINGLE_GATE, x, q_id])
153153

154+
def custom_gate(self, q_id, gate):
155+
"""
156+
Applies a custom gate to the qubit with q_id.
157+
"""
158+
q = self.shared_dict.get_queues_for_ids([q_id])[0]
159+
q.put([SINGLE_GATE, gate, q_id])
160+
154161
def merge_qubits(self, q_id1, q_id2):
155162
"""
156163
Merges two qubits to one process, if they are not already
@@ -210,6 +217,16 @@ def give_statevector_for(self, q_id):
210217
qubits, vector = ret.get()
211218
return qubits, vector
212219

220+
def custom_two_qubit_gate(self, q_id1, q_id2, gate):
221+
self.merge_qubits(q_id1, q_id2)
222+
q = self.shared_dict.get_queues_for_ids([q_id1])[0]
223+
q.put([DOUBLE_GATE, gate, q_id1, q_id2])
224+
225+
def custom_controlled_gate(self, applied_to_id, controlled_by_id, gate):
226+
self.merge_qubits(applied_to_id, controlled_by_id)
227+
q = self.shared_dict.get_queues_for_ids([applied_to_id])[0]
228+
q.put([CONTROLLED_GATE, gate, applied_to_id, controlled_by_id])
229+
213230
def measure(self, q_id, non_destructive=False):
214231
"""
215232
Measures a qubit with an id. If non_destructive is False, the qubit

eqsn/qubit_thread.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
NEW_QUBIT = 8
1515
ADD_MERGED_QUBITS_TO_DICT = 9
1616
GIVE_STATEVECTOR = 10
17+
DOUBLE_GATE = 11
1718

1819

1920
class QubitThread(object):
@@ -127,6 +128,48 @@ def merge_send(self, channel, chanel2):
127128
chanel2.put(dp(self.qubits))
128129
return
129130

131+
def swap_qubits(self, q_id1, q_id2):
132+
"""
133+
Swaps the position of qubit q_id1 with q_id2
134+
in the statevector.
135+
"""
136+
def cnot(q_id1, q_id2):
137+
mat = np.asarray([[0, 1], [1, 0]])
138+
self.apply_controlled_gate(mat, q_id1, q_id2)
139+
140+
# Check if they are the same ids
141+
if q_id1 == q_id2:
142+
return
143+
144+
# Perform swap
145+
cnot(q_id1, q_id2)
146+
cnot(q_id2, q_id1)
147+
cnot(q_id1, q_id2)
148+
# Change ordering in the list
149+
i1 = self.qubits.index(q_id1)
150+
i2 = self.qubits.index(q_id2)
151+
self.qubits[i1], self.qubits[i2] = self.qubits[i2], self.qubits[i1]
152+
153+
def apply_two_qubit_gate(self, mat, q_id1, q_id2):
154+
# Bring the qubits in the right order
155+
i2 = self.qubits.index(q_id2)
156+
if i2 > 0:
157+
new_i1 = i2-1
158+
self.swap_qubits(q_id1, self.qubits[new_i1])
159+
else:
160+
self.swap_qubits(q_id1, self.qubits[0])
161+
self.swap_qubits(q_id2, self.qubits[1])
162+
apply_mat = mat
163+
nr1 = self.qubits.index(q_id1)
164+
total_amount = len(self.qubits)
165+
before = nr1
166+
after = total_amount - nr1 - 2
167+
if before > 0:
168+
apply_mat = np.kron(np.eye(2 ** before), apply_mat)
169+
if after > 0:
170+
apply_mat = np.kron(apply_mat, np.eye(2 ** after))
171+
self.qubit = np.dot(apply_mat, self.qubit)
172+
130173
def measure_non_destructive(self, q_id, ret_channel):
131174
"""
132175
Perform a non destructive measurement on qubit with the id.
@@ -241,5 +284,7 @@ def run(self):
241284
self.measure_non_destructive(item[1], item[2])
242285
elif item[0] == GIVE_STATEVECTOR:
243286
self.give_statevector(item[1])
287+
elif item[0] == DOUBLE_GATE:
288+
self.apply_two_qubit_gate(item[1], item[2], item[3])
244289
else:
245290
raise ValueError("Command does not exist!")

eqsn/worker_process.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
from eqsn.shared_dict import SharedDict
66
from eqsn.qubit_thread import SINGLE_GATE, MERGE_SEND, MERGE_ACCEPT, MEASURE,\
77
MEASURE_NON_DESTRUCTIVE, GIVE_STATEVECTOR, \
8-
CONTROLLED_GATE, NEW_QUBIT, ADD_MERGED_QUBITS_TO_DICT, QubitThread
8+
CONTROLLED_GATE, NEW_QUBIT, ADD_MERGED_QUBITS_TO_DICT, \
9+
DOUBLE_GATE, QubitThread
910

1011

1112
class WorkerProcess(object):
@@ -44,6 +45,8 @@ def run(self):
4445
self.add_merged_qubits_to_thread(item[1], item[2])
4546
elif item[0] == GIVE_STATEVECTOR:
4647
self.give_statevector_for(item[1], item[2])
48+
elif item[0] == DOUBLE_GATE:
49+
self.apply_two_qubit_gate(item[1], item[2], item[3])
4750
else:
4851
raise ValueError("Command does not exist!")
4952

@@ -86,6 +89,11 @@ def stop_all(self):
8689
self.shared_dict.stop_all_threads()
8790
self.shared_dict.stop_shared_dict()
8891

92+
def apply_two_qubit_gate(self, gate, q_id1, q_id2):
93+
self.merge_qubits(q_id1, q_id2)
94+
q = self.shared_dict.get_queues_for_ids([q_id1])[0]
95+
q.put([DOUBLE_GATE, gate, q_id1, q_id2])
96+
8997
def apply_single_gate(self, gate, q_id):
9098
"""
9199
Applies a single gate to a Qubit.

tests/test_custom_gates.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from eqsn import EQSN
2+
import numpy as np
3+
4+
def test_custom_single_gate():
5+
eqsn = EQSN()
6+
gate = (1/2)**0.5 * np.array([[1, 1],[1,-1]], dtype=np.csingle)
7+
eqsn.new_qubit('1')
8+
eqsn.custom_gate('1', gate)
9+
eqsn.custom_gate('1', gate)
10+
res = eqsn.measure('1')
11+
eqsn.stop_all()
12+
assert res == 0
13+
14+
def test_custom_controlled_gate():
15+
eqsn = EQSN()
16+
gate = np.array([[0, 1],[1,0]], dtype=np.csingle)
17+
eqsn.new_qubit('1')
18+
eqsn.new_qubit('2')
19+
eqsn.H_gate('1')
20+
eqsn.custom_controlled_gate('2', '1', gate)
21+
res1 = eqsn.measure('1')
22+
res2 = eqsn.measure('2')
23+
eqsn.stop_all()
24+
assert res1 == res2
25+
26+
27+
if __name__ == "__main__":
28+
print("Start custom gate tests...")
29+
test_custom_single_gate()
30+
test_custom_controlled_gate()
31+
print("Finished custom gates test.")

tests/test_custom_two_qubit_gate.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from eqsn import EQSN
2+
import time
3+
import numpy as np
4+
5+
6+
def test_two_qubit_gate():
7+
eqsn = EQSN()
8+
eqsn.new_qubit("1")
9+
eqsn.new_qubit("2")
10+
eqsn.X_gate("1")
11+
custom_gate = np.asarray(
12+
[[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]]
13+
)
14+
eqsn.custom_two_qubit_gate("1", "2", custom_gate)
15+
m1 = eqsn.measure("1")
16+
m2 = eqsn.measure("2")
17+
assert m1 == 0
18+
assert m2 == 1
19+
eqsn.stop_all()
20+
21+
22+
if __name__ == "__main__":
23+
test_two_qubit_gate()

0 commit comments

Comments
 (0)