import numpy as np
import numpy as m
# Importing standard Qiskit libraries
from qiskit import QuantumCircuit, transpile, Aer, IBMQ
from qiskit.tools.jupyter import *
from qiskit.visualization import *
from ibm_quantum_widgets import *
from qiskit.providers.aer import QasmSimulator
from qiskit import BasicAer
# Loading your IBM Quantum account(s)
provider = IBMQ.load_account()
from qiskit import ClassicalRegister, QuantumRegister, QuantumCircuit, Aer, execute
from qiskit.extensions.simulator import snapshot
from qiskit.tools.visualization import circuit_drawer
import numpy as np
import math as m
import scipy as sci
import random
import time
import matplotlib
import matplotlib.pyplot as plt
S_simulator = Aer.backends(name='statevector_simulator')[0]
M_simulator = Aer.backends(name='qasm_simulator')[0]
#===============================================
#----------- Math Operations -----------
#===============================================
def Binary(N, total, LSB):
'''
Input: N (integer) total (integer) LSB (string)
Returns the base-2 binary equivilant of N according to left or right least significant bit notation
'''
qubits = int(m.log(total,2))
b_num = np.zeros(qubits)
for i in np.arange(qubits):
if( N/((2)**(qubits-i-1)) >= 1 ):
if(LSB=='R'):
b_num[i] = 1
if(LSB=='L'):
b_num[int(qubits-(i+1))] = 1
N = N - 2**(qubits-i-1)
B = []
for j in np.arange(len(b_num)):
B.append(int(b_num[j]))
return B
def QFT(qc, q, qubits, **kwargs):
'''
Input: qc (QuantumCircuit) q (QuantumRegister) qubits (integer)
Keyword Arguments: swap (Bool) - Adds SWAP gates after all of the phase gates have been applied
Assigns all the gate operations for a Quantum Fourier Transformation
'''
R_phis = [0]
for i in np.arange(2,int(qubits+1)):
R_phis.append( 2/(2**(i)) * m.pi )
for j in np.arange(int(qubits)):
qc.h( q[int(j)] )
for k in np.arange(int(qubits-(j+1))):
qc.cu1( R_phis[k+1], q[int(j+k+1)], q[int(j)] )
if 'swap' in kwargs:
if(kwargs['swap'] == True):
for s in np.arange(m.floor(qubits/2.0)):
qc.swap( q[int(s)],q[int(qubits-1-s)] )
#==================================================
#----------- Displaying Results -----------
#==================================================
def Wavefunction(obj, **kwargs):
'''
Prints a tidier version of the array statevector corresponding to the wavefuntion of a QuantumCircuit object
Keyword Arguments: precision (integer) - the decimal precision for amplitudes
column (Bool) - prints each state in a vertical column
systems (array of integers) - seperates the qubits into different states
show_systems (array of Bools) - indictates which qubit systems to print
'''
if(type(obj) == QuantumCircuit ):
statevec = execute( obj, S_simulator, shots=1 ).result().get_statevector()
if(type(obj) == np.ndarray):
statevec = obj
sys = False
NL = False
dec = 5
if 'precision' in kwargs:
dec = int( kwargs['precision'] )
if 'column' in kwargs:
NL = kwargs['column']
if 'systems' in kwargs:
systems = kwargs['systems']
sys = True
last_sys = int(len(systems)-1)
show_systems = []
for s_chk in np.arange(len(systems)):
if( type(systems[s_chk])!=int ):
raise Exception('systems must be an array of all integers')
if 'show_systems' in kwargs:
show_systems = kwargs['show_systems']
if( len(systems)!=len(show_systems) ):
raise Exception('systems and show_systems need to be arrays of equal length')
for ls in np.arange(len(show_systems)):
if((show_systems[ls]!=True)and(show_systems[ls]!=False)):
raise Exception('show_systems must be an array of Truth Values')
if(show_systems[ls]==True):
last_sys = int(ls)
else:
for ss in np.arange(len(systems)):
show_systems.append(True)
wavefunction = ''
qubits = int(m.log(len(statevec),2))
for i, comp in enumerate(statevec): #i in np.arange( int(len(statevec)) ):
value = round(comp.real, dec) + round(comp.imag, dec) * 1j
if( (value.real != 0) or (value.imag != 0) ):
state = list( Binary(int(i), int(2**qubits) ,'L') )
state_str = ''
if( sys == True ):
k = 0
for s in np.arange(len(systems)):
if(show_systems[s]==True):
if(int(s)!=last_sys):
state.insert( int(k+systems[s]),'>|' )
k = int(k+systems[s]+1)
else:
k = int(k+systems[s])
else:
for s2 in np.arange(systems[s]):
del state[int(k)]
for j in np.arange(len(state)):
if(type(state[j])!=str):
state_str = state_str+str(int(state[j]))
else:
state_str = state_str+state[j]
if( (value.real != 0) and (value.imag != 0) ):
if( value.imag > 0):
wavefunction = wavefunction + str(value.real) + '+' + str(value.imag) + 'j |' + state_str + '> '
else:
wavefunction = wavefunction +str(value.real)+''+str(value.imag)+'j |'+state_str+'> '
if( (value.real!=0) and (value.imag==0) ):
wavefunction = wavefunction + str(value.real) + ' |' + state_str + '> '
if( (value.real==0) and (value.imag!=0) ):
wavefunction = wavefunction +str(value.imag)+'j |'+state_str+'> '
if(NL):
wavefunction = wavefunction + '\n'
print(wavefunction)
def Wavefunction_orig_modified(obj, **kwargs):
'''
Prints a tidier version of the array statevector corresponding to the wavefuntion of a QuantumCircuit object
Keyword Arguments: precision (integer) - the decimal precision for amplitudes
column (Bool) - prints each state in a vertical column
systems (array of integers) - seperates the qubits into different states
show_systems (array of Bools) - indictates which qubit systems to print
'''
if(type(obj) == QuantumCircuit ):
statevec = execute( obj, S_simulator, shots=1 ).result().get_statevector()
if(type(obj) == np.ndarray):
statevec = obj
sys = False
NL = False
dec = 5
if 'precision' in kwargs:
dec = int( kwargs['precision'] )
if 'column' in kwargs:
NL = kwargs['column']
if 'systems' in kwargs:
systems = kwargs['systems']
sys = True
last_sys = int(len(systems)-1)
show_systems = []
for s_chk in np.arange(len(systems)):
if( type(systems[s_chk])!=int ):
raise Exception('systems must be an array of all integers')
if 'show_systems' in kwargs:
show_systems = kwargs['show_systems']
if( len(systems)!=len(show_systems) ):
raise Exception('systems and show_systems need to be arrays of equal length')
for ls in np.arange(len(show_systems)):
if((show_systems[ls]!=True)and(show_systems[ls]!=False)):
raise Exception('show_systems must be an array of Truth Values')
if(show_systems[ls]==True):
last_sys = int(ls)
else:
for ss in np.arange(len(systems)):
show_systems.append(True)
wavefunction = ''
qubits = int(m.log(len(statevec),2))
for i, comp in enumerate(statevec): #i in np.arange( int(len(statevec)) ):
value = round(comp.real, dec) + round(comp.imag, dec) * 1j
if( (value.real != 0) or (value.imag != 0) ):
state = list(Binary(int(i), int(2**qubits) ,'L') )
state_str = ''
if( sys == True ):
k = 0
for s in np.arange(len(systems)):
if(show_systems[s]==True):
if(int(s)!=last_sys):
state.insert( int(k+systems[s]),'>|' )
k = int(k+systems[s]+1)
else:
k = int(k+systems[s])
else:
for s2 in np.arange(systems[s]):
del state[int(k)]
for j in np.arange(len(state)):
if(type(state[j])!=str):
state_str = state_str+str(int(state[j]))
else:
state_str = state_str+state[j]
if( (value.real != 0) and (value.imag != 0) ):
if( value.imag > 0):
wavefunction = wavefunction + str(value.real) + '+' + str(value.imag) + 'j |' + state_str + '> '
else:
wavefunction = wavefunction +str(value.real)+''+str(value.imag)+'j |'+state_str+'> '
if( (value.real!=0) and (value.imag==0) ):
wavefunction = wavefunction + str(value.real) + ' |' + state_str + '>'
if( (value.real==0) and (value.imag!=0) ):
wavefunction = wavefunction +str(value.imag)+'j |'+state_str+'> '
if(NL):
wavefunction = wavefunction + '\n'
print(wavefunction)
from qiskit import ClassicalRegister, QuantumRegister, QuantumCircuit, Aer, execute
import numpy as np
import math as m
import scipy as sci
S_simulator = Aer.backends(name='statevector_simulator')[0]
M_simulator = Aer.backends(name='qasm_simulator')[0]
#Displaying Results
def Wavefunction_new( obj , *args, **kwargs):
#Displays the waveftmction of the quantum system
if(type(obj) == QuantumCircuit ):
statevec = execute( obj, S_simulator, shots=1 ).result().get_statevector()
if(type(obj) == np.ndarray):
statevec = obj
sys = False
NL = False
dec = 5
if 'precision' in kwargs:
dec = int( kwargs['precision'] )
if 'column' in kwargs:
NL = kwargs['column']
if 'systems' in kwargs:
systems = kwargs['systems']
sys = True
last_sys = int(len(systems)-1)
show_systems = []
for s_chk in np.arange(len(systems)):
if( type(systems[s_chk]) != int ):
raise Exception('systems must be an array of all integers')
if 'show_systems' in kwargs:
show_systems = kwargs['show_systems']
if( len(systems)!= len(show_systems) ):
raise Exception('systems and show_systems need to be arrays of equal length')
for ls in np.arange(len(show_systems)):
if((show_systems[ls] != True) and (show_systems[ls] != False)):
raise Exception('show_systems must be an array of Truth Values')
if(show_systems[ls] == True):
last_sys = int(ls)
else:
for ss in np.arange(len(systems)):
show_systems.append(True)
wavefunction = ''
qubits = int(m.log(len(statevec),2))
for i, comp in enumerate(statevec): #i in np.arange( int(len(statevec)) ):
value = round(comp.real, dec) + round(comp.imag, dec) * 1j
# for i in np.arange( int(len(statevec))):
#print(wavefunction)
# value = round(statevec[i].real, dec) + round(statevec[i].imag, dec) * 1j
if( (value.real != 0) or (value.imag != 0)):
state = list(Binary(int(i),int(2**qubits)))
state.reverse()
state_str = ''
#print(state)
if( sys == True ): #Systems and SharSystems
k = 0
for s in np.arange(len(systems)):
if(show_systems[s] == True):
if(int(s) != last_sys):
state.insert(int(k + systems[s]), '>|' )
k = int(k + systems[s] + 1)
else:
k = int(k + systems[s])
else:
for s2 in np.arange(systems[s]):
del state[int(k)]
for j in np.arange(len(state)):
if(type(state[j])!= str):
state_str = state_str + str(int(state[j]))
else:
state_str = state_str + state[j]
#print(state_str)
#print(value)
if( (value.real != 0) and (value.imag != 0) ):
if( value.imag > 0):
wavefunction = wavefunction + str(value.real) + '+' + str(value.imag) + 'j |' + state_str + '> '
else:
wavefunction = wavefunction + str(value.real) + '' + str(value.imag) + 'j |' + state_str + '> '
if( (value.real !=0 ) and (value.imag ==0) ):
wavefunction = wavefunction + str(value.real) + ' |' + state_str + '> '
if( (value.real == 0) and (value.imag != 0) ):
wavefunction = wavefunction + str(value.imag) + 'j |' + state_str + '> '
if(NL):
wavefunction = wavefunction + '\n'
#print(NL)
print(wavefunction)
#return wavefunction
def QFT(qc, q, qubits, **kwargs):
'''
Input: qc (QuantumCircuit) q (QuantumRegister) qubits (integer)
Keyword Arguments: swap (Bool) - Adds SWAP gates after all of the phase gates have been applied
Assigns all the gate operations for a Quantum Fourier Transformation
'''
R_phis = [0]
for i in np.arange(2,int(qubits+1)):
R_phis.append( 2/(2**(i)) * m.pi )
for j in np.arange(int(qubits)):
qc.h( q[int(j)] )
for k in np.arange(int(qubits-(j+1))):
qc.cu1( R_phis[k+1], q[int(j+k+1)], q[int(j)] )
if 'swap' in kwargs:
if(kwargs['swap'] == True):
for s in np.arange(m.floor(qubits/2.0)):
qc.swap( q[int(s)],q[int(qubits-1-s)] )
def QFT_dgr(qc, q, qubits, **kwargs):
'''
Input: qc (QuantumCircuit) q (QuantumRegister) qubits (integer)
Keyword Arguments: swap (Bool) - Adds SWAP gates after all of the phase gates have been applied
Assigns all the gate operations for a Quantum Fourier Transformation
'''
if 'swap' in kwargs:
if(kwargs['swap'] == True):
for s in np.arange(m.floor(qubits/2.0)):
qc.swap( q[int(s)],q[int(qubits-1-s)] )
R_phis = [0]
for i in np.arange(2,int(qubits+1)):
R_phis.append( -2/(2**(i)) * m.pi )
for j in np.arange(int(qubits)):
for k in np.arange(int(j)):
qc.cu1(R_phis[int(j-k)], q[int(qubits-(k+1))], q[int(qubits-(j+1))] )
qc.h( q[int(qubits-(j+1))] )
def DFT(x, **kwargs):
'''
Input: x (array)
Keyword Arguments: inverse (Bool) - if True, performs a Inverse Discrete Fourier Transformation instead
Computes a classical Discrete Fourier Transformation on the array of values x, returning a new array of transformed val
'''
p = -1.0
if 'inverse' in kwargs:
P = kwargs['inverse']
if(P == True):
p = 1.0
L = len(x)
X = []
for i in np.arange(L):
value = 0
for j in np.arange(L):
value = value + x[j]*np.exp(p*2*m.pi*1.0j * ( int(i*j)/(L*1.0) ) )
X.append(value)
for k in np.arange(len(X)):
re = round(X[k].real,5)
im = round(X[k].imag,5)
if( (abs(im) == 0) and (abs(re) != 0) ):
X[k] = re
elif( (abs(re) == 0) and (abs(im) != 0) ):
X[k] = im*1.0j
elif( (abs(re) == 0) and (abs(im) == 0) ):
X[k] = 0
else:
X[k] = re + im*1.0j
return X
#=================================================
#----------- Custom Operations -----------
#=================================================
def X_Transformation(qc, qreg, state):
'''
Input: qc (QuantumCircuit) qreg (QuantumRegister) state (array)
Applies the neccessary X gates to transform 'state' to the state of all 1's
'''
for j in np.arange(len(state)):
if( int(state[j])==0 ):
qc.x( qreg[int(j)] )
#==========================================================
#----------- Lesson 6.1 - Quantum Adder ------------
#==========================================================
def Quantum_Adder(qc, Qa, Qb, A, B):
'''
Input: qc (QuantumCircuit) Qa (QuantumRegister) Qb (QuantumRegister) A (array) B (array)
Appends all of the gate operations for a QFT based addition of two states A and B
'''
Q = len(B)
for n in np.arange(Q):
if( A[n] == 1 ):
qc.x( Qa[int(n+1)] )
if( B[n] == 1 ):
qc.x( Qb[int(n)] )
QFT(qc,Qa,Q+1)
p = 1
for j in np.arange( Q ):
qc.cu1( m.pi/(2**p), Qb[int(j)], Qa[0] )
p = p + 1
for i in np.arange(1,Q+1):
p = 0
for jj in np.arange( i-1, Q ):
qc.cu1( m.pi/(2**p), Qb[int(jj)], Qa[int(i)] )
p = p + 1
QFT_dgr(qc,Qa,Q+1)
alpha = 2*m.pi/3
U = np.array([ [ np.cos(alpha) , np.sin(alpha) ],
[ -np.sin(alpha) , np.cos(alpha) ] ])
#---------------------------------------------------
e = 0.5*(-1+m.sqrt(3)*1.0j)
v = 1.0/m.sqrt(2)*np.array( [-1.0j,1] )
#---------------------------------------------------
print('____ Unitary Matrix ____\n',U)
print( '\n U |u> = ',np.dot(U,v))
print( 'e^{2\u03C0i\u03C6} |u> = ',e * v)
A. Y. Kitaev, "Quantum measurements and the Abelian Stabilizer Problem", arXiv:9511026 (1995)
q = QuantumRegister(3,name='q' )
qc= QuantumCircuit(q,name='qc')
#-------------------------------
qc.x( q[1] )
qc.x( q[2] )
print('____ Initial State ____')
Wavefunction(qc)
qc.swap( q[0], q[2] )
QFT_dgr( qc,q,3 )
print('\n____ After QFT\u2020 ____')
Wavefunction(qc)
#======================================
print('\n ____ QFT\u2020 Expression ____')
for k in np.arange( 8 ):
phase = 1.0/(m.sqrt(8)) * np.exp( -1.0j*m.pi*( (3*k)/4 ) )
print( 'state: ',Binary(int(k),8,'R'),' phase: ',round(phase.real,4)+round(phase.imag,4)*1.0j )
Example: 𝑗 = 6 𝑛 = 3
Measurement on this system is promised to reveal the phase with high probability !!!
n = 3
q1 = QuantumRegister(n,name='q1')
q2 = QuantumRegister(1,name='q2')
qc = QuantumCircuit(q1,q2,name='qc')
theta = 0.52
phi = 2*m.pi*theta
#---------------------------------------------------
for i in np.arange(n):
qc.h(q1[int(i)])
qc.x( q2[0] )
for j in np.arange(n):
for k in np.arange(2**j):
qc.cu1( phi, q1[int(n-1-j)], q2[0] )
print('\n___ After Control-U Operations ___')
Wavefunction( qc, systems=[n,1] )
#---------------------------------------------------
Phases = [np.exp(4.0j*phi),np.exp(2.0j*phi),np.exp(1.0j*phi)]
print(' ')
for i in np.arange(8):
state = Binary(int(i),8,'R')
phase = m.sqrt(1/8)
for j in np.arange(3):
if(state[j]==1):
phase = phase*Phases[j]
print('State: ',state,' Phase: ',round(phase.real,5)+round(phase.imag,5)*1.0j)
n = 3
q1 = QuantumRegister(n,name='q1')
q2 = QuantumRegister(1,name='q2')
c = ClassicalRegister(n,name='c')
qc = QuantumCircuit(q1,q2,c,name='qc')
theta = 0.52
#---------------------------------------------------
for i in np.arange(n):
qc.h(q1[int(i)])
qc.x( q2[0] )
phi = 2*m.pi*theta
for j in np.arange(n):
for k in np.arange(2**j):
qc.cu1( phi, q1[int(n-1-j)], q2[0] )
print('\n___ After QFT_dgr ___')
QFT_dgr( qc,q1,n,swap=True )
Wavefunction( qc, systems=[n,1] )
#---------------------------------------------------
qc.measure(q1,c)
results = execute(qc, BasicAer.get_backend('qasm_simulator'), shots=10000).result()
plot_histogram(results.get_counts())