Skip to content
This repository was archived by the owner on Jan 14, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
113 commits
Select commit Hold shift + click to select a range
9dd91e9
Solved optimization bug
Mar 2, 2020
50136fc
Solved bug of accumulated phase
Mar 4, 2020
727fbb3
Testing optimizers
AdrianPerezSalinas Mar 4, 2020
02e5f76
Added previous theory folder
AdrianPerezSalinas Mar 9, 2020
b595998
Keep on optimizing
AdrianPerezSalinas Mar 9, 2020
c3ce6b8
Work on ADAM + SPSA optimizer
AdrianPerezSalinas Mar 9, 2020
3fc3be3
looks like it is optimizing properly, but stop requirements are to be…
AdrianPerezSalinas Mar 11, 2020
a8d1a4f
Batches work
AdrianPerezSalinas Mar 11, 2020
e5cc72b
Take a look!
AdrianPerezSalinas Mar 11, 2020
21bc1e7
results tanh
AdrianPerezSalinas Mar 12, 2020
8b242d7
Coronavirus
AdrianPerezSalinas Mar 12, 2020
9ce76a4
Example
Mar 13, 2020
b435cfd
example: readme
Mar 13, 2020
a06f62b
example: readme
Mar 13, 2020
e1cccb9
Next step: looking for good genetic algorithms
Mar 24, 2020
1305897
Exploring genetic algorithms, testing different strategies
Mar 24, 2020
3fa8360
to titan
Jun 16, 2020
2646972
to titan
Jun 16, 2020
8c4af58
to titan
Jun 16, 2020
54c59c0
Results titan
AdrianPerezSalinas Jun 16, 2020
622303c
to titan
Jun 17, 2020
50a8d0a
qibo, theory
Jun 18, 2020
c1ede50
titan results
AdrianPerezSalinas Jun 19, 2020
39622ff
stashable
AdrianPerezSalinas Jun 19, 2020
707dfa9
del test
AdrianPerezSalinas Jun 19, 2020
25f0d89
to titan
Jun 22, 2020
84adeb8
to titan - clean
Jun 22, 2020
2c38e62
Results from Titan
AdrianPerezSalinas Jun 22, 2020
1ed0e61
results titan
AdrianPerezSalinas Jun 23, 2020
ec49335
minor changes
Jun 23, 2020
0e9f12a
results titan
AdrianPerezSalinas Jul 7, 2020
0bb09c3
Merge branch 'theory' of https://github.com/UB-Quantic/Universal-Appr…
AdrianPerezSalinas Jul 7, 2020
9d53681
cma
AdrianPerezSalinas Jul 27, 2020
a0d81d9
cma titan
AdrianPerezSalinas Jul 27, 2020
73492b1
sigma tuned
AdrianPerezSalinas Jul 27, 2020
06cfc16
to titan-cma
AdrianPerezSalinas Jul 28, 2020
5f0791e
added Bayes optimizer
AdrianPerezSalinas Jul 28, 2020
99a6bb5
parameters for bayes changed
AdrianPerezSalinas Jul 28, 2020
e0ae6da
results titan cma, bayes
AdrianPerezSalinas Jul 30, 2020
ed2f54c
tests to change parametres setting
AdrianPerezSalinas Jul 30, 2020
9cafc8a
Set parameters half done, some issues remaining
AdrianPerezSalinas Jul 30, 2020
7cb0f05
issue solved
AdrianPerezSalinas Jul 31, 2020
a0dc5fc
Merge pull request #1 from UB-Quantic/paramset
AdrianPerezSalinas Jul 31, 2020
f78fd65
function create_hamiltonian updated to match new qibo version
AdrianPerezSalinas Aug 25, 2020
65ea1b1
Merge branch 'theory' of https://github.com/UB-Quantic/Universal-Appr…
AdrianPerezSalinas Aug 25, 2020
aeb7183
plot is visible now
AdrianPerezSalinas Aug 25, 2020
d5efa3e
first changes
AdrianPerezSalinas Sep 3, 2020
b235890
in review
AdrianPerezSalinas Sep 3, 2020
18a0c44
clean up complete
AdrianPerezSalinas Sep 3, 2020
3effebd
cleanup
AdrianPerezSalinas Sep 3, 2020
4fa339d
optimizer improved
AdrianPerezSalinas Sep 8, 2020
8e6e59d
round of benchmarks
AdrianPerezSalinas Nov 18, 2020
f29745c
Fourier round in Titan
AdrianPerezSalinas Nov 24, 2020
80c9bcf
real-valued round titan
AdrianPerezSalinas Nov 24, 2020
68e1627
results Univ Approx
AdrianPerezSalinas Nov 25, 2020
d6bfc8f
summary
AdrianPerezSalinas Nov 25, 2020
cbead2f
esults Titan
AdrianPerezSalinas Nov 25, 2020
ca0e495
reset results
AdrianPerezSalinas Nov 25, 2020
004d181
Merge branch 'cleanup_qibo' of https://github.com/UB-Quantic/Universa…
AdrianPerezSalinas Nov 25, 2020
d4a4be0
Results eset
AdrianPerezSalinas Nov 25, 2020
a4e3f26
round of benchmarks
AdrianPerezSalinas Nov 25, 2020
ceea4b3
first round of results
AdrianPerezSalinas Nov 26, 2020
d129fc7
bunch of results
AdrianPerezSalinas Nov 27, 2020
3832d93
30 nov. - results
AdrianPerezSalinas Nov 30, 2020
3c22a28
summary
AdrianPerezSalinas Nov 30, 2020
84327b4
complex minimizer with absolute values
AdrianPerezSalinas Nov 30, 2020
6fb5a46
runner
AdrianPerezSalinas Nov 30, 2020
8891a7c
painters
AdrianPerezSalinas Nov 30, 2020
6486ea5
Merge branch 'cleanup_qibo' of https://github.com/UB-Quantic/Universa…
AdrianPerezSalinas Nov 30, 2020
efbd9cc
deleted wrong complex opt
AdrianPerezSalinas Nov 30, 2020
ae2e52c
approximant
AdrianPerezSalinas Nov 30, 2020
d5e0740
ansatz updated
AdrianPerezSalinas Nov 30, 2020
dc9f46a
updated ansatz
AdrianPerezSalinas Nov 30, 2020
784ac8b
typos
AdrianPerezSalinas Nov 30, 2020
2b7df6d
results 02/12/2020
AdrianPerezSalinas Dec 2, 2020
3ac477c
results 02/12/2020
AdrianPerezSalinas Dec 2, 2020
4c93ffb
to titan: results 2D
AdrianPerezSalinas Dec 3, 2020
12439f6
fix typos
AdrianPerezSalinas Dec 3, 2020
a399040
also Fourier ansatz
AdrianPerezSalinas Dec 3, 2020
03411dc
results titan 04/12
AdrianPerezSalinas Dec 4, 2020
c32f591
new 2D benchmark functions
AdrianPerezSalinas Dec 14, 2020
7986c78
plt settled again
AdrianPerezSalinas Dec 14, 2020
cf8e87b
added painter
AdrianPerezSalinas Dec 15, 2020
4e1bfff
added painter
AdrianPerezSalinas Dec 15, 2020
7f6db5f
results from titan for new 2d benchmarks
AdrianPerezSalinas Dec 15, 2020
a047146
Merge branch 'benchmark_functions_2D' of https://github.com/UB-Quanti…
AdrianPerezSalinas Dec 15, 2020
7943732
fancy plots
AdrianPerezSalinas Dec 15, 2020
45e433c
New classical results for benckmarks
AdrianPerezSalinas Dec 15, 2020
e12c540
classical 2D benchmark
AdrianPerezSalinas Dec 16, 2020
19d814d
results titan 16/12/2020
AdrianPerezSalinas Dec 16, 2020
cf63578
merging
AdrianPerezSalinas Dec 16, 2020
7220656
16/12 l-bfgs-b missing points
AdrianPerezSalinas Dec 16, 2020
b8882b1
round
AdrianPerezSalinas Dec 16, 2020
528ddf7
results
AdrianPerezSalinas Dec 17, 2020
23a18d3
Error found in ansatz Fourier 2D, all results deleted, ansatz fixed
AdrianPerezSalinas Dec 17, 2020
3dab2e3
Ready to run in Titan new Fourier
AdrianPerezSalinas Dec 17, 2020
348cb8d
poly classical UAT
AdrianPerezSalinas Dec 17, 2020
c87ceac
file to get parameters
AdrianPerezSalinas Dec 17, 2020
df69f2c
classical optimization rosenbrock
AdrianPerezSalinas Dec 17, 2020
25e0ce5
results Fourier 2D titan
AdrianPerezSalinas Dec 18, 2020
76daefd
last updates
AdrianPerezSalinas Dec 18, 2020
3601132
runner
AdrianPerezSalinas Dec 18, 2020
a5c1328
merging
AdrianPerezSalinas Dec 18, 2020
d1ebc87
running tests in Christmas Eve
AdrianPerezSalinas Dec 24, 2020
2b78997
problem with folders solved
AdrianPerezSalinas Dec 24, 2020
37464e0
problem with folders solved 2
AdrianPerezSalinas Dec 24, 2020
3d6a330
results titan only summary
AdrianPerezSalinas Dec 26, 2020
d053fa8
results only summary
AdrianPerezSalinas Dec 28, 2020
b545201
final results
AdrianPerezSalinas Dec 28, 2020
e26296d
chapa y pintura
AdrianPerezSalinas Jan 11, 2021
1a71faa
painter experimental
AdrianPerezSalinas Jan 11, 2021
74da30f
Clean version
AdrianPerezSalinas Jan 26, 2021
da298fb
Merge pull request #2 from UB-Quantic/benchmark_functions_2D
AdrianPerezSalinas Jan 26, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
Binary file modified Algorithm.labber
Binary file not shown.
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# How it works

Sorry, it seems it was not properly uploaded the first time

This code works only for the class Approximant_NN, that is the equivalent to the simulation performed in the experiment
There are three main files

- classes/Approximant_NN:
- This class represents the function, and there are several functions
- __init__: initialize some important parameters: domain, function, layers, parameters to encode the function
- update_parameters: modify the parameters
- run_complete: run the circuit for all points and creates the variables final_states or sampling, depending on whether noise is True or False
- run: run the circuit for one batch and returns the results (noisy is also available)
- _minim_function: compute chi
- _minim_function_noisy: compute chi with sampling
- find_optimal_parameters: this function performs the minimization. It calls functions in opt_algorithms. Now only minimize and adam_spsa_optimizer are functional
- other functions are auxiliary functions

- opt_algorithms:
- Several optimizations algorithms
- Right now the only working algorithm is adam_spsa_optimizer (and auxiliary functions)

- opt:
- Example file, contains example for minimization and testing of parameters
369 changes: 369 additions & 0 deletions qibo_sim/chi2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,369 @@
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

df = pd.read_csv('summary.csv')
color={'True': 'red', 'False':'blue', 'Experiment':'green'}
line={'False':'--', 'True':':', 'Experiment':'-.'}
marker = {'UAT':'X', 'Fourier':'^', 'Experiment':'+'}

functions = ['tanh', 'step', 'poly', 'relu']
#functions = ['tanh', 'relu']
ansatze={'UAT':'Weighted', 'Fourier':'Fourier'}

titles = {'tanh': r'f(x) = $\tanh(5 x)$','poly':r'$f(x) = {\rm poly}(x)$', 'step': r'$f(x) = {\rm step}(x)$', 'relu':r'$f(x) = {\rm ReLU}(x)$'}


def step(x):
step.name = 'step'
return 0.5 * (np.sign(x) + 1)

def cosine(x):
cosine.name = 'cosine'
return np.cos(2*np.pi*x)

def sigmoid(x, a=10):
sigmoid.name = 'sigmoid'
return 1 / (1 + np.exp(-a * x))

def tanh(x, a=5):
tanh.name = 'tanh'
return np.tanh(a * x)


def angulator(x):
return 2 * np.pi * x

def zero(x):
tanh.name = 'zero'
#return 0.5 * (np.tanh(x) + 1)
return 0

def tanh_2(x):
tanh.name = 'tanh'
#return 0.5 * (np.tanh(x) + 1)
return (np.tanh(np.linalg.norm(x))**2)

def relu(x):
relu.name = 'relu'
return x * (x > 0)

def poly(x):
poly.name= 'poly'
return np.abs(3*x**3 * (1 - x**4))

def himmelblau(x):
himmelblau.name = 'himmelblau'
for x_ in x:
yield (x_[0]**2 + x_[1] - 11)**2 + (x_[0] + x_[1]**2 - 7)**2

def brent(x):
brent.name = 'brent'
for x_ in x:
yield np.linalg.norm(x_ / 2)**2 + np.exp(-np.linalg.norm(x_/2 - 5)**2)

def threehump(x):
threehump.name = 'threehump'
for x_ in x * 2 / 5:
yield 2 * x_[0]**2 - 1.05 * x_[0]**4 + 1/6 * x_[0]**6 + x_[0] * x_[1] + x_[1]**2

def adjiman(x):
adjiman.name = 'adjiman'
for x_ in x:
yield np.cos(x_[0]) * np.sin(x_[1]) - x_[0] / (x_[1]**2 + 1)

def rosenbrock(x):
rosenbrock.name = 'rosenbrock'
for x_ in x:
yield (1 - .4*x_[0])**2 + 100 * (x_[1] - (.4*x_[0])**2)**2


L = 6
fig, axs = plt.subplots(nrows=4, sharex=True, sharey=False, figsize=(9, 18))
handles = []
i = 0
for function, ax in zip(functions, axs.flatten()):
for ansatz in ['UAT', 'Fourier']:
for quantum in [True, False]:
chi = []
for layers in range(1, L + 1):
chi_ = df[(df['function'] == function) & (df['ansatz'] == ansatze[ansatz]) & (df['quantum'] == quantum) & (df['layers'] == layers)]['chi2'].min()
chi.append(min(float(chi_), 1))
ax.plot(list(range(1, L + 1)), chi, color=color[str(quantum)],
linestyle=line[str(quantum)],
marker=marker[ansatz], markersize=15)

quantum = 'Experiment'
chi = []
for layers in range(1, L + 1):
file_exp = 'results/experiment/' + ansatze[ansatz] + '/' + function + '/%s_layers/results.txt' % layers
x, y = np.loadtxt(file_exp)
y = 2*y - 1
from classes.ApproximantNN import Approximant_real as App

func = globals()[f"{function}"]
C = App(layers, x, ansatze[ansatz], func)
chi_ = np.mean(np.abs(y - C.target) ** 2)
chi.append(min(float(chi_), 1))
ax.plot(list(range(1, L + 1)), chi, color=color[str(quantum)],
linestyle=line[str(quantum)],
marker=marker[ansatz], markersize=15)
ax.grid(True)
pos = ax.get_position()
pos.x0 += 0.02
pos.x1 += 0.02
pos.y1 = 1 - 0.025 - i * 0.2250
pos.y0 = pos.y1 - 0.19
i += 1
ax.set_position(pos)
ax.tick_params(axis='both', which='major', labelsize=18)
ax.set_title(titles[function], fontsize=22)
ax.set(yscale='log')
ax.set_ylabel(ylabel=r'$\chi^2$', fontsize=24)
ax.grid(True)

ax.set_xlabel('Layers', fontsize=24)

import matplotlib.lines as mlines

for ansatz in ['Fourier', 'UAT']:
for quantum in [False, True]:

if quantum:
q = 'Simulation'
else:
q = 'Classical'
handles.append(mlines.Line2D([], [], color=color[str(quantum)],
linestyle=line[str(quantum)],
marker=marker[ansatz],
markersize=10, label= q + ' ' + ansatz))

quantum='Experiment'
handles.append(mlines.Line2D([], [], color=color[str(quantum)],
linestyle=line[str(quantum)],
marker=marker[ansatz],
markersize=10, label= quantum + ' ' + ansatz))

fig.legend(handles = handles, bbox_to_anchor=(0.18, 0.002, 0.75, .4), loc='lower left', borderaxespad=0., mode='expand',
ncol=2, prop={'size': 18})
fig.savefig('chi_real.pdf')


L = 6
fig, axs = plt.subplots(nrows=4, ncols=4, sharex=True, sharey=False, figsize=(20, 14))
handles = []

titles = {'tanh': r'$\tanh(5 x)$','poly':r'${\rm poly}(x)$', 'step': r'${\rm step}(x)$', 'relu':r'${\rm ReLU}(x)$'}

i = 0
for i, function1 in enumerate(functions):
fig.text(.02, 1 - i * 0.85 / 4 - .2, r'$\mathbf{X} = $' + titles[function1], rotation='vertical', fontsize=24)
for j, function2 in enumerate(functions):
if i == 0:
fig.text(0.15 + j * 0.92 / 4, 0.98, r'$\mathbf{Y} = $' + titles[function2],
fontsize=24)
function = function1 + '_' + function2
ax = axs.flatten()[4 * i + j]
for ansatz in ['UAT', 'Fourier']:
for quantum in [True, False]:
chi = []
for layers in range(1, L + 1):
chi_ = df[(df['function'] == function) & (df['ansatz'] == ansatze[ansatz]) & (df['quantum'] == quantum) & (df['layers'] == layers)]['chi2'].min()
chi.append(min(float(chi_), 1))
ax.plot(list(range(1, L + 1)), chi, color=color[str(quantum)],
linestyle=line[str(quantum)],
marker=marker[ansatz], markersize=10)

try:
quantum = 'Experiment'
chi = []
for layers in range(1, L + 1):
file_exp_x = 'results/experiment/' + ansatze[ansatz] + '/' + function + '/%s_layers/results_x.txt' % layers
domain, x = np.loadtxt(file_exp_x)
x = 2 * x - 1

file_exp_y = 'results/experiment/' + ansatze[
ansatz] + '/' + function + '/%s_layers/results_y.txt' % layers
domain, y = np.loadtxt(file_exp_y)
y = 2 * y - 1
from classes.ApproximantNN import Approximant_real as App

func1 = globals()[f"{function1}"]
func2 = globals()[f"{function2}"]
from classes.ApproximantNN import Approximant_complex as App
C = App(layers, domain, ansatze[ansatz], func1, func2)
chi_ = np.mean(np.abs(x + 1j * y - C.target) ** 2)
chi.append(min(float(chi_), 1))
ax.plot(list(range(1, L + 1)), chi, color=color[str(quantum)],
linestyle=line[str(quantum)],
marker=marker[ansatz], markersize=10)
except:pass

ax.grid(True)


function_ = function.split('_')
#tit = titles[function_[0]] + r'$\; + \; i \,$' + titles[function_[1]]
ax.set(yscale='log')
pos = ax.get_position()
pos.x0 = 0.1 + j * 0.92 / 4
pos.x1 = pos.x0 + 0.19
pos.y0 = 0.12 + 0.85 / 4 * (3 - i)
pos.y1 = pos.y0 + 0.2
ax.set_position(pos)
ax.tick_params(axis='both', which='major', labelsize=18)
#ax.set_title(tit, fontsize=10)
ax.set(yscale='log')
if j == 0:
ax.set_ylabel(ylabel=r'$\chi^2$', fontsize=24)
ax.tick_params(axis='both', which='major', labelsize=15)
else:
ax.tick_params(axis='both', which='major', labelsize=15)
ax.grid(True)

axs.flatten()[12].set_xlabel('Layers', fontsize=20)
axs.flatten()[13].set_xlabel('Layers', fontsize=20)
axs.flatten()[15].set_xlabel('Layers', fontsize=20)
axs.flatten()[14].set_xlabel('Layers', fontsize=20)

axs.flatten()[0].set_ylabel(r'$\chi^2$', fontsize=20)
axs.flatten()[4].set_ylabel(r'$\chi^2$', fontsize=20) # ylabel=r'$\chi^2$',
axs.flatten()[8].set_ylabel(r'$\chi^2$', fontsize=20)
axs.flatten()[12].set_ylabel(r'$\chi^2$', fontsize=20)


import matplotlib.lines as mlines
ansatz = 'Fourier'
for quantum in [False, True]:

if quantum:
q = 'Simulation'
else:
q = 'Classical'
handles.append(mlines.Line2D([], [], color=color[str(quantum)],
linestyle=line[str(quantum)],
marker=marker[ansatz],
markersize=10, label= q + ' ' + ansatz))

quantum='Experiment'
handles.append(mlines.Line2D([], [], color=color[str(quantum)],
linestyle=line[str(quantum)],
marker=marker[ansatz],
markersize=10, label= quantum + ' ' + ansatz))

fig.legend(handles = handles, bbox_to_anchor=(0.23, 0.002, 0.165, .4), loc='lower left', borderaxespad=0., mode='expand',
ncol=1, prop={'size': 18})

ansatz = 'UAT'
handles=[]
for quantum in [False, True]:

if quantum:
q = 'Simulation'
else:
q = 'Classical'
handles.append(mlines.Line2D([], [], color=color[str(quantum)],
linestyle=line[str(quantum)],
marker=marker[ansatz],
markersize=10, label= q + ' ' + ansatz))

quantum='Experiment'
handles.append(mlines.Line2D([], [], color=color[str(quantum)],
linestyle=line[str(quantum)],
marker=marker[ansatz],
markersize=10, label= quantum + ' ' + ansatz))

fig.legend(handles = handles, bbox_to_anchor=(0.47, 0.002, 0.15, .4), loc='lower left', borderaxespad=0., mode='expand',
ncol=1, prop={'size': 18})

fig.savefig('chi_complex.pdf')


color={'True': 'red', 'False':'blue', 'Experiment':'green'}
line={'False':'--', 'True':':', 'Experiment':'-.'}
marker = {'UAT':'X', 'Fourier':'^', 'Experiment':'+'}

functions = ['himmelblau', 'brent', 'threehump', 'adjiman']

ansatze={'UAT':'Weighted_2D', 'Fourier':'Fourier_2D'}

titles = {'adjiman': r'${\rm Adjiman(x, y)}$','threehump':r'${\rm Threehump(x, y)}$', 'brent': r'${\rm Brent(x, y)}$', 'himmelblau':r'${\rm Himmelblau(x, y)}$'}

L = 6
fig, axs = plt.subplots(nrows=4, sharex=True, sharey=False, figsize=(9, 18))
handles = []
i = 0
for function, ax in zip(functions, axs.flatten()):
for ansatz in ['UAT']:
for quantum in [True, False]:
chi = []
for layers in range(1, L + 1):
chi_ = df[(df['function'] == function) & (df['ansatz'] == ansatze[ansatz]) & (df['quantum'] == quantum) & (df['layers'] == layers)]['chi2'].min()
chi.append(min(float(chi_), 1))
ax.plot(list(range(1, L + 1)), chi, color=color[str(quantum)],
linestyle=line[str(quantum)],
marker=marker[ansatz], markersize=15)

try:
quantum = 'Experiment'
x_0 = np.linspace(-5, 5, 25)
x_1 = np.linspace(-5, 5, 25)
from itertools import product

x = np.array(list(product(x_0, x_1)))
chi = []
for layers in range(1, L + 1):
file_exp = 'results/experiment/' + ansatze[ansatz] + '/' + function + '/%s_layers/results.txt' % layers
y = np.loadtxt(file_exp)
y = y.transpose()
y = 2 * y.flatten() - 1
from classes.ApproximantNN import Approximant_real_2D as App

func = globals()[f"{function}"]
C = App(layers, x, func, ansatze[ansatz])
chi_ = np.mean(np.abs(y - C.target) ** 2)
chi.append(min(float(chi_), 1))
ax.plot(list(range(1, L + 1)), chi, color=color[str(quantum)],
linestyle=line[str(quantum)],
marker=marker[ansatz], markersize=15)
except:pass
ax.grid(True)

pos = ax.get_position()
pos.x0 += 0.02
pos.x1 += 0.02
pos.y1 = 1 - 0.025 - i * 0.2250
pos.y0 = pos.y1 - 0.19
i += 1
ax.set_position(pos)
ax.tick_params(axis='both', which='major', labelsize=18)
ax.set_title(titles[function], fontsize=22)
ax.set(yscale='log')
ax.set_ylabel(ylabel=r'$\chi^2$', fontsize=24)
ax.grid(True)

ax.set_xlabel('Layers', fontsize=24)

import matplotlib.lines as mlines

for ansatz in ['UAT']:
for quantum in [False, True]:
if quantum:
q = 'Simulation'
else:
q = 'Classical'
handles.append(mlines.Line2D([], [], color=color[str(quantum)],
linestyle=line[str(quantum)],
marker=marker[ansatz],
markersize=10, label= q + ' ' + ansatz))

quantum = 'Experiment'
handles.append(mlines.Line2D([], [], color=color[str(quantum)],
linestyle=line[str(quantum)],
marker=marker[ansatz],
markersize=10, label=quantum + ' ' + ansatz))

fig.legend(handles = handles, bbox_to_anchor=(0.63, 0.01, 0.35, .35), loc='lower left', borderaxespad=0., mode='expand',
ncol=1, prop={'size': 18})
fig.savefig('chi_2D.pdf')

Loading