-
Notifications
You must be signed in to change notification settings - Fork 0
/
ReversibleCircuit.py
130 lines (106 loc) · 3.62 KB
/
ReversibleCircuit.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
import numpy as np
import scipy as sp
import pandas as pd
import matplotlib.pyplot as plt
class Circuit:
def __init__(self,n):
self.n = n
self.wires = [Wire(k) for k in range(n)]
self.gates = []
def addGate(self,g):
self.gates.append(g)
for bit in g.bits:
self.wires[bit].addGate(g)
def __str__(self):
string = ""
for gate in self.gates:
string = string + str(gate)
return string
def fullStoch(self):
stoch = None
for gate in self.gates:
if stoch is None:
stoch = gate.fullStoch(self.n)
else:
stoch = np.dot(gate.fullStoch(self.n), stoch)
return stoch
def printWires(self):
for wire in self.wires:
print(wire)
class Wire:
def __init__(self,k):
self.k = k
self.gates = []
def addGate(self,g):
self.gates.append(g)
def removeLastGate(self):
return self.gates.pop()
def __str__(self):
string = f"[{self.k}]:"
for gate in self.gates:
string += str(gate)
return string
class Gate:
#assumes if bits = (0,1,2), order is kron(b2,b1,b0). This follows from c01 gate having control
#on 0 and target on 1 by convention
gatecount = 0
def __init__(self,matrix,bits):
assert(matrix.shape == (2**len(bits),2**len(bits)))
self.matrix = matrix
self.bits = bits
self.id = Gate.gatecount
Gate.gatecount += 1
def __str__(self):
return f"-g{self.id}-"
def fullStoch(self,n):
#first construct hamiltonian operating on first len(bits) qubits, then swap bits to fit order
stoch = self.matrix
for i in range(n - len(self.bits)):
stoch = np.kron([[1,0],[0,1]],stoch)
print("preswap: \n", stoch)
swaps = Gate._swapcircuit(self,n)
if len(swaps):
stoch = np.dot(stoch, np.transpose(swaps))
stoch = np.dot(swaps, stoch)
print("postswap:\n",stoch)
return stoch
def _swapcircuit(self,n):
swaplist = Gate._bubbleSortOperations(self.bits)
sortedbits = sorted(self.bits)
for i in range(len(sortedbits)-1,-1,-1):
if not (i == sortedbits[i]):
swaplist.append((i,sortedbits[i]))
print(swaplist)
return Gate._swapStoch(self,n,swaplist)
def _swapStoch(self,n,swaplist):
swapMatrix = []
if not (len(swaplist) == 0):
swapMatrix = np.eye(2**n)
for swapbits in swaplist:
swapMatrix = np.dot(Gate._generateSwapMatrix(n,swapbits),swapMatrix)
print(swapMatrix)
return swapMatrix
def _generateSwapMatrix(n,swapbits):
N = 2**n
swapMat = np.zeros((N,N))
for i in range(N):
mask1 = i >> swapbits[0] & 1
mask2 = i >> swapbits[1] & 1
xor = mask1 ^ mask2
xor = xor << swapbits[0] | xor << swapbits[1]
j = i ^ xor
swapMat[i,j] = 1
return swapMat
def _bubbleSortOperations(bits):
issorted = False
swaplist = []
while not issorted:
issorted = True
for i in range(len(bits) - 1):
if bits[i] > bits[i+1]:
temp = bits[i]
bits[i] = bits[i+1]
bits[i+1] = temp
issorted = False
swaplist.append((i,i+1))
return swaplist