Skip to content

Commit 1ab9c1f

Browse files
committed
Added all files
1 parent fc0bc90 commit 1ab9c1f

7 files changed

+4283
-2
lines changed

README.md

+44-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,47 @@
11
# Effect of Entanglement on Model Training in Quantum Machine Learning
22

33
>This repo contains the code for the project from QOSF(Quanutm Open Source Foundation) Mentorship Program.
4-
> **Student:** Syed Farhan Ahmad
5-
> **Mentor:** Amira Abbas
4+
> **Student:** [Syed Farhan Ahmad](https://www.linkedin.com/in/syedfarhanahmad/)
5+
> **Mentor:** [Amira Abbas](https://www.linkedin.com/in/amira-abbas/)
6+
7+
The blog post for the same can be found [here](https://born-2learn.github.io/posts/2020/11/effect-of-entanglement-on-model-training/).
8+
9+
## Project Description
10+
11+
Classical neural networks encode higher dimensional vectors(inputs) to lower dimensional vectors(outputs), but the reverse is not possible. Recent researches have shown that scrambling of information form a small subsystem to a larger one is feasible. In our QOSF project, we analyse the effect of entanglement as a variational circuit trains and also study the role of various entropies to characterize entanglement.
12+
13+
## Running the notebooks
14+
15+
1. Create a virtual environment:
16+
17+
```
18+
$ python3 -m venv venv
19+
```
20+
21+
2. Activate the environment:
22+
23+
```
24+
$ source venv/bin/activate
25+
```
26+
27+
3. Update `pip`:
28+
29+
```
30+
$ pip install --upgrade pip
31+
```
32+
4. Clone the repo
33+
34+
```
35+
git clone https://github.com/born-2learn/Entanglement_in_QML.git
36+
```
37+
5. Launch Jupyter Notebook:
38+
39+
```
40+
$ jupyter notebook
41+
```
42+
43+
6. Open and run the jupyter notebooks
44+
45+
## Project Structure
46+
structure
47+

adam_params.csv

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
v,m,t
2+
[1.90748539e-06 6.95729175e-06 3.73782588e-05 1.03232754e-05],[-0.00138112 -0.00263767 -0.00611378 0.00321299],1
3+
[3.80664446e-06 1.37819009e-05 7.39023650e-05 2.03742208e-05],[-0.00262801 -0.00499958 -0.01157676 0.00607825],2
4+
[5.69728230e-06 2.04766026e-05 1.09585307e-04 3.01506417e-05],[-0.00375399 -0.00711353 -0.01645415 0.00862956],3
5+
[7.57951261e-06 2.70423952e-05 1.44435922e-04 3.96630468e-05],[-0.00477114 -0.00900421 -0.02080427 0.01089932],4
6+
[9.45313793e-06 3.34779746e-05 1.78460370e-04 4.89120241e-05],[-0.00569024 -0.01069338 -0.02467941 0.01291513],5
7+
[1.13192038e-05 3.97878137e-05 2.11674046e-04 5.79016638e-05],[-0.00652143 -0.01220176 -0.02812741 0.01470238],6
8+
[1.31771941e-05 4.59723127e-05 2.44082982e-04 6.66346595e-05],[-0.00727328 -0.0135472 -0.03119052 0.0162837 ],7
9+
[1.50265932e-05 5.20324510e-05 2.75697141e-04 7.51150575e-05],[-0.00795349 -0.01474588 -0.03390713 0.01767969],8
10+
[1.68678253e-05 5.79692062e-05 3.06527703e-04 8.33455325e-05],[-0.00856935 -0.01581237 -0.0363119 0.01890865],9
11+
[1.87006850e-05 6.37846775e-05 3.36581899e-04 9.13307471e-05],[-0.00912717 -0.01676 -0.03843566 0.01998741],10
12+
[2.05265411e-05 6.94809346e-05 3.65875854e-04 9.90733392e-05],[-0.00963321 -0.01760076 -0.04030697 0.02093076],11
13+
[2.23445479e-05 7.50583505e-05 3.94412822e-04 1.06578546e-04],[-0.0100923 -0.01834513 -0.0419504 0.02175247],12
14+
[2.41548108e-05 8.05162040e-05 4.22201192e-04 1.13849591e-04],[-0.01050915 -0.01900229 -0.04338852 0.02246458],13
15+
[2.59577515e-05 8.58576681e-05 4.49260499e-04 1.20890320e-04],[-0.01088809 -0.0195813 -0.04464264 0.02307805],14
16+
[2.77525170e-05 9.10853116e-05 4.75593868e-04 1.27703912e-04],[-0.01123258 -0.0200902 -0.04573049 0.02360265],15
17+
[2.95395316e-05 9.61973009e-05 5.01211895e-04 1.34295400e-04],[-0.01154618 -0.02053532 -0.0466687 0.02404747],16
18+
[3.13185782e-05 1.01195666e-04 5.26121429e-04 1.40668497e-04],[-0.01183185 -0.02092317 -0.0474719 0.0244205 ],17
19+
[3.30897604e-05 1.06084567e-04 5.50338976e-04 1.46824435e-04],[-0.0120924 -0.02126002 -0.04815414 0.02472848],18
20+
[3.48541444e-05 1.10862712e-04 5.73873561e-04 1.52768741e-04],[-0.01233067 -0.02155042 -0.04872742 0.02497823],19
21+
[3.66108603e-05 1.15532069e-04 5.96732958e-04 1.58505035e-04],[-0.01254855 -0.02179912 -0.0492024 0.02517558],20
22+
[3.83593624e-05 1.20095640e-04 6.18931991e-04 1.64037493e-04],[-0.01274787 -0.02201063 -0.04958936 0.02532589],21
23+
[4.00997537e-05 1.24552673e-04 6.40475870e-04 1.69370233e-04],[-0.01293047 -0.02218822 -0.04989665 0.02543397],22
24+
[4.18331091e-05 1.28905610e-04 6.61377983e-04 1.74506730e-04],[-0.01309837 -0.02233551 -0.05013258 0.02550404],23
25+
[4.35585487e-05 1.33154240e-04 6.81642294e-04 1.79449852e-04],[-0.01325269 -0.02245518 -0.05030373 0.02553979],24
26+
[4.52771501e-05 1.37302015e-04 7.01289996e-04 1.84203594e-04],[-0.01339514 -0.02255046 -0.05041769 0.02554476],25
27+
[4.69873737e-05 1.41347152e-04 7.20320269e-04 1.88774703e-04],[-0.01352634 -0.02262311 -0.05047917 0.0255227 ],26
28+
[4.86903030e-05 1.45294105e-04 7.38746033e-04 1.93164187e-04],[-0.01364774 -0.02267606 -0.05049376 0.02547587],27
29+
[5.03850493e-05 1.49142631e-04 7.56579999e-04 1.97376970e-04],[-0.01376001 -0.02271094 -0.05046648 0.02540708],28
30+
[5.20723695e-05 1.52896075e-04 7.73831352e-04 2.01415693e-04],[-0.01386427 -0.02273002 -0.05040151 0.02531841],29
31+
[5.37517000e-05 1.56551645e-04 7.90506989e-04 2.05286223e-04],[-0.0139611 -0.02273397 -0.05030241 0.02521241],30
32+
[5.54231386e-05 1.60115193e-04 8.06620324e-04 2.08991081e-04],[-0.01405125 -0.02272532 -0.05017303 0.02509069],31
33+
[5.70857902e-05 1.63585939e-04 8.22179129e-04 2.12532782e-04],[-0.01413504 -0.02270487 -0.05001628 0.02495472],32
34+
[5.87420761e-05 1.66967617e-04 8.37196480e-04 2.15914354e-04],[-0.0142139 -0.02267437 -0.04983535 0.02480593],33
35+
[6.03890951e-05 1.70255970e-04 8.51674601e-04 2.19142916e-04],[-0.01428731 -0.0226336 -0.04963199 0.02464648],34
36+
[6.20286147e-05 1.73457203e-04 8.65630586e-04 2.22219265e-04],[-0.01435638 -0.02258469 -0.04940933 0.024477 ],35
37+
[6.36590617e-05 1.76570529e-04 8.79068626e-04 2.25149800e-04],[-0.01442099 -0.02252801 -0.04916886 0.02429926],36
38+
[6.52808726e-05 1.79598606e-04 8.92001250e-04 2.27935255e-04],[-0.01448169 -0.02246468 -0.0489128 0.02411365],37
39+
[6.68934782e-05 1.82539207e-04 9.04434604e-04 2.30581847e-04],[-0.01453865 -0.02239459 -0.04864249 0.02392173],38
40+
[6.84993252e-05 1.85398355e-04 9.16381943e-04 2.33090739e-04],[-0.01459302 -0.02231951 -0.04835991 0.0237238 ],39
41+
[7.00961520e-05 1.88174762e-04 9.27852226e-04 2.35465541e-04],[-0.01464429 -0.02223939 -0.0480664 0.02352069],40
42+
[7.16837238e-05 1.90870996e-04 9.38853294e-04 2.37710748e-04],[-0.01469265 -0.02215507 -0.04776305 0.02331335],41
43+
[7.32631522e-05 1.93487212e-04 9.49392912e-04 2.39828858e-04],[-0.01473873 -0.02206675 -0.04745084 0.02310221],42
44+
[7.48338577e-05 1.96024519e-04 9.59482696e-04 2.41823278e-04],[-0.01478253 -0.02197483 -0.0471311 0.02288786],43
45+
[7.63949260e-05 1.98486351e-04 9.69132096e-04 2.43695968e-04],[-0.01482395 -0.02188022 -0.04680482 0.02267053],44
46+
[7.79467993e-05 2.00870958e-04 9.78345588e-04 2.45452974e-04],[-0.01486334 -0.02178253 -0.0464723 0.0224514 ],45
47+
[7.94889018e-05 2.03179890e-04 9.87132462e-04 2.47097011e-04],[-0.01490068 -0.02168217 -0.0461344 0.02223075],46
48+
[8.10216771e-05 2.05416963e-04 9.95507560e-04 2.48630306e-04],[-0.01493628 -0.02158008 -0.04579254 0.02200874],47
49+
[8.25452264e-05 2.07582263e-04 1.00347127e-03 2.50055503e-04],[-0.01497032 -0.0214762 -0.04544635 0.02178562],48
50+
[8.40582916e-05 2.09676793e-04 1.01103626e-03 2.51376506e-04],[-0.0150025 -0.02137073 -0.04509691 0.02156194],49
51+
[8.55626822e-05 2.11701550e-04 1.01821030e-03 2.52595833e-04],[-0.01503359 -0.02126381 -0.04474467 0.02133786],50

libraries/meyer_wallach_measure.py

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import numpy as np
2+
import qutip
3+
4+
def compute_Q_ptrace(ket, N):
5+
"""Computes Meyer-Wallach measure using alternative interpretation, i.e. as
6+
an average over the entanglements of each qubit with the rest of the system
7+
(see https://arxiv.org/pdf/quant-ph/0305094.pdf).
8+
9+
Args:
10+
=====
11+
ket : numpy.ndarray or list
12+
Vector of amplitudes in 2**N dimensions
13+
N : int
14+
Number of qubits
15+
16+
Returns:
17+
========
18+
Q : float
19+
Q value for input ket
20+
"""
21+
ket = qutip.Qobj(ket, dims=[[2]*(N), [1]*(N)]).unit()
22+
print('KET= ', ket)
23+
entanglement_sum = 0
24+
for k in range(N):
25+
print('value of n', k, 'PTrace: ',ket.ptrace([k])**2 )
26+
rho_k_sq = ket.ptrace([k])**2
27+
entanglement_sum += rho_k_sq.tr()
28+
29+
Q = 2*(1 - (1/N)*entanglement_sum)
30+
return Q
31+
32+
if __name__ == "__main__":
33+
34+
# Test #1: bell state (Q should be 1)
35+
n_qubits = 2
36+
test_state = np.zeros(2**n_qubits)
37+
test_state[0] = 1
38+
test_state[-1] = 1
39+
test_state /= np.linalg.norm(test_state)
40+
print('test state:',test_state.shape)
41+
42+
print('Test #1 (Q=1):')
43+
Q_value = compute_Q_ptrace(ket=test_state, N=n_qubits)
44+
print('Q = {}\n'.format(Q_value))
45+
46+
# Test #2: product state (Q should be 0)
47+
n_qubits = 4
48+
test_state = np.zeros(2**n_qubits)
49+
test_state[0] = 1
50+
test_state[1] = 1
51+
test_state /= np.linalg.norm(test_state)
52+
53+
print('Test #2 (Q=0):')
54+
Q_value = compute_Q_ptrace(ket=test_state, N=n_qubits)
55+
print('Q = {}\n'.format(Q_value))
+158
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
import numpy as np
2+
from qiskit import *
3+
from qiskit.circuit import Parameter
4+
from math import radians, pow
5+
from qiskit.quantum_info import Statevector, DensityMatrix, entropy
6+
import matplotlib.pyplot as plt
7+
8+
class GradientDescentOptimizer:
9+
'''
10+
This class is used to perform Optimization on the input angle for the parameterized circuit using the Gradient Descent Optimizer.
11+
12+
'''
13+
def __init__(self, shots):
14+
self.shots = shots
15+
16+
def mse_cost_function(self, prob_avg_01, prob_avg_10):
17+
'''
18+
This function calculates the cost for the parametric circuit, using Mean Squared Error method
19+
20+
Parameters:
21+
-----------
22+
prob_avg_01 : Probability of the state |01>
23+
prob_avg_10 : Probability of the state |10>
24+
'''
25+
return pow((prob_avg_01-prob_avg_10), 2)
26+
27+
def unsymmetrical_cost_function(self, prob_avg_01, prob_avg_10):
28+
'''
29+
This function calculates the cost for the parametric circuit, when only the |01> + |10> state is required in the output.
30+
31+
Parameters:
32+
-----------
33+
prob_avg_01 : Probability of the state |01>
34+
prob_avg_10 : Probability of the state |10>
35+
'''
36+
return prob_avg_10 - (prob_avg_01+prob_avg_10)/(2)
37+
38+
def optimize_circuit_sgd(self, qc, quantum_circuit_parameter, angle_degrees, cost_function='mse', learning_rate = 2):
39+
'''
40+
This function is used for optimizing the values of angle_degrees, using Gradient Descent method.
41+
42+
Parameters:
43+
-----------
44+
qc : Quantum Circuit object
45+
quantum_circuit_parameter : parameter object
46+
angle_degrees : Angle(in degrees) by which the parameterised gates will rotate
47+
cost_function : The type of cost function to be used[default: mse]
48+
learning_rate : The learning rate for optimization[default: 2]
49+
'''
50+
i = 0
51+
max_i = 500
52+
previous_step_size = 1
53+
precision = -1
54+
55+
56+
loss_function = []
57+
vn_entropy = []
58+
epochs = []
59+
epoch_var = 0
60+
while i<max_i and previous_step_size>precision: #iterating over until the error converges
61+
epoch_var+=1
62+
epochs.append(epoch_var)
63+
64+
theta_radians = radians(angle_degrees) #converting the degrees to radians
65+
previous_angle = angle_degrees
66+
67+
bell_state = execute(qc, backend = Aer.get_backend('statevector_simulator'), shots = self.shots, parameter_binds=[{quantum_circuit_parameter: theta_radians}]).result().get_statevector()
68+
#counts = job.result().get_counts()
69+
psi = Statevector(bell_state)
70+
counts = psi.probabilities_dict()
71+
print(counts)
72+
73+
74+
D = DensityMatrix(bell_state)
75+
vn_entropy_val = entropy(D, base=2)
76+
vn_entropy.append(vn_entropy_val)
77+
78+
79+
80+
#print(counts)
81+
try:
82+
prob_avg_01 = counts['00']
83+
84+
except:
85+
prob_avg_01 = 0
86+
try:
87+
prob_avg_10 = counts['11']
88+
except:
89+
prob_avg_10 = 0
90+
91+
if cost_function == 'mse':
92+
loss_function.append(self.mse_cost_function(prob_avg_01, prob_avg_10))
93+
angle_degrees = angle_degrees - learning_rate*self.mse_cost_function(prob_avg_01, prob_avg_10)
94+
95+
if cost_function == 'unsymmetrical':
96+
angle_degrees = angle_degrees - learning_rate*self.unsymmetrical_cost_function(prob_avg_01, prob_avg_10)
97+
98+
previous_step_size = abs(angle_degrees - previous_angle)
99+
i+=1
100+
101+
print(angle_degrees)
102+
103+
return angle_degrees, counts, epochs, vn_entropy, loss_function
104+
105+
def __str__(self):
106+
return "Gradient Descent Optimizer"
107+
108+
109+
class BellStateCircuit:
110+
'''
111+
This class is used to generate a parameterized circuit that will be optimized to form the Bell State circuit with equal
112+
probability of |01> and |10> states.
113+
'''
114+
115+
def __init__(self):
116+
self.qc = None
117+
self.executable = None
118+
self.theta = 90
119+
120+
def create_circuit(self, shots, angle_degrees= 90):
121+
'''
122+
Creates a parameterized circuit with one tunable parameter with angle_degrees.
123+
124+
Parameters:
125+
-----------
126+
shots : The total number of shots for which the quantum experiment will run
127+
angle_degrees : The angle in degrees, that the parameterized gate will be rotated by
128+
'''
129+
self.angle_degrees = angle_degrees
130+
self.parameter = Parameter('param1')
131+
132+
self.qc = QuantumCircuit(2, 2)
133+
state1 = [1,0]
134+
state2 = [1,0]
135+
self.qc.initialize(state1, 0) #initializing qubit 0 to state 0
136+
self.qc.initialize(state2, 1) #initialing qubit 1 to state 1
137+
self.qc.ry(self.parameter, 0)
138+
self.qc.barrier()
139+
self.qc.cx(0, 1)
140+
self.qc.barrier()
141+
#self.qc.measure(0, 0)
142+
#self.qc.measure(1, 1)
143+
144+
def draw_circuit(self):
145+
'''
146+
Displays the circuit in text format.
147+
'''
148+
self.qc.draw('text')
149+
150+
def extract_circuit(self):
151+
'''
152+
This function returns the Quantum Circuit object, parameter object and final angle(in degrees),
153+
that will be passed to the GradientDescent class.
154+
'''
155+
return self.qc, self.parameter, self.angle_degrees
156+
157+
def __str__(self):
158+
return "Bell State Circuit Generator"

toy_model_bell_state.py

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
from libraries.simple_variational_circuit import BellStateCircuit, GradientDescentOptimizer
2+
3+
import matplotlib.pyplot as plt
4+
5+
shots_list = [100] #Number of measurements/shots
6+
results = {} #dictionary to store the final results of the observations
7+
8+
if __name__=='__main__':
9+
'''
10+
This is the main function of the entire project that is used to generate an equal probabilty
11+
of |01> and |10> states, after optimizing the parameters of a parameterized quantum circuit.
12+
'''
13+
#print('Enter initial Angle(in degrees): ')
14+
#angle_degrees = input()
15+
angle_degrees = 0 #initial angle taken
16+
17+
18+
for shots in shots_list:
19+
if shots ==1:
20+
results[shots] = [90.000000000, {'01':1}]
21+
continue
22+
elif shots == 10:
23+
learning_rate = 0.38 #setting learning rate for shots = 10
24+
elif shots == 100:
25+
learning_rate = 1.29
26+
else:
27+
learning_rate = 3.2
28+
29+
#Creation of the parameterized circuit
30+
quantum_circuit = BellStateCircuit()
31+
print(quantum_circuit)
32+
quantum_circuit.create_circuit(shots=shots, angle_degrees= angle_degrees)
33+
quantum_circuit.draw_circuit()
34+
quantum_circuit_object, quantum_circuit_parameter, angle_degrees_ckt = quantum_circuit.extract_circuit()
35+
36+
#Optimization using Gradient Descent
37+
optimizer = GradientDescentOptimizer(shots=shots)
38+
print(optimizer)
39+
angle_degrees_ckt, counts, epochs, vn_entropy, loss_function = optimizer.optimize_circuit_sgd(quantum_circuit_object, quantum_circuit_parameter, angle_degrees_ckt, learning_rate = learning_rate)
40+
41+
plt.xlabel('Epochs')
42+
plt.ylabel('Loss Function')
43+
plt.title('Cost Function')
44+
plt.plot(epochs, loss_function, color='tab:blue')
45+
#plot1 = plt.figure(1)
46+
plt.show()
47+
48+
plt.xlabel('Epochs')
49+
plt.ylabel('von Neumann Entropy')
50+
plt.title('S(X)')
51+
plt.plot(epochs, vn_entropy, color='tab:blue')
52+
#plot1 = plt.figure(1)
53+
plt.show()
54+
55+
plt.xlabel('Loss Function')
56+
plt.ylabel('von Neumann Entropy')
57+
plt.title('vN entropy vs loss')
58+
plt.plot( loss_function, vn_entropy, color='tab:blue')
59+
#plot2 = plt.figure(2)
60+
plt.show()
61+
62+
results[shots] = [angle_degrees_ckt, counts]
63+
64+
#Resetting all varuiables for the next iteration
65+
quantum_circuit = None
66+
optimizer = None
67+
quantum_circuit_object, quantum_circuit_parameter, angle_degrees_ckt = None, None, None
68+
counts = None
69+
70+
for i in results:
71+
print('Number of measurements:\t',i,'\tFinal parameter(angle in degrees):\t', results[i][0], '\tFinal counts:\t', results[i][1])

0 commit comments

Comments
 (0)