'''
Simulating a specific hamitonian (PauliOperator)\n
Copyright (C) Origin Quantum 2017-2018\n
Licensed Under Apache Licence 2.0
'''
from pyqpanda.Hamiltonian.PauliOperator.pyQPandaPauliOperator import PauliOperator
from pyqpanda.pyQPanda import *
from pyqpanda.utils import *
from math import pi
from pyqpanda.Algorithm.fragments import parity_check_circuit
from functools import partial
[文档]
def simulate_z_term(qubit_list, coef, t):
'''
`QPanda Algorithm API`\n
Simulating z-only term like H=coef * (Z0..Zn-1)\n
U=exp(-iHt)\n
\n
list<Qubit>, float, float -> QCircuit
Note: Z-Hamiltonian spreads over the qubit_list
'''
prog=QCircuit()
# parity-check
# RZ(theta)
# parity-check
if len(qubit_list) > 1:
prog.insert(parity_check_circuit(qubit_list))\
.insert(RZ(qubit_list[-1],coef*t))\
.insert(parity_check_circuit(qubit_list))
else:
if len(qubit_list)!=0:
prog.insert(RZ(qubit_list[0],coef*t))
return prog
[文档]
def simulate_one_term(qubit_list, hamiltonian_term, t):
'''
Simulate a single term of Hamilonian like "X0 Y1 Z2" with
coefficient and time. U=exp(-it*coef*H)
@param
qubit_list: qubit needed to simulate the hamiltonian
hamiltonian_term: tuple like ("X0 Y1 Z2",2.3)
t: time
@return: QCircuit
'''
prog=QCircuit()
if not hamiltonian_term:
return prog
actual_qlist=list()
transform=QCircuit()
for single_term in hamiltonian_term[0]:
if hamiltonian_term[0][single_term] is 'X':
transform.insert(H(qubit_list[single_term]))
actual_qlist.append(qubit_list[single_term])
elif hamiltonian_term[0][single_term] is 'Y':
transform.insert(RX(qubit_list[single_term],pi/2))
actual_qlist.append(qubit_list[single_term])
elif hamiltonian_term[0][single_term] is 'Z':
actual_qlist.append(qubit_list[single_term])
prog.insert(transform)\
.insert(simulate_z_term(actual_qlist, hamiltonian_term[1], t))\
.insert(transform.dagger())
return prog
[文档]
def simulate_pauliZ_hamiltonian(qubit_list,PauliOperator,t):
'''
Simulate hamiltonian consists of pauli-Z operators
@param
qubit_list: qubit needed to simulate the hamiltonian
PauliOperator: PauliOperator object from c++
t: time
@return: QCircuit
'''
prog=QCircuit()
if PauliOperator.isAllPauliZorI():
Hamiltonian=PauliOperator.toHamiltonian(0)
for op in Hamiltonian:
actual_qlist=[]
for single_term in op[0]:
actual_qlist.append(qubit_list[single_term])
if len(actual_qlist)!=0:
prog.insert(simulate_z_term(actual_qlist, op[1], t))
else:
throw("unmatched")
return prog
[文档]
def simulate_hamiltonian(qubit_list,PauliOperator,t,slices=3):
'''
Simulate a general case of hamiltonian by Trotter-Suzuki
approximation. U=exp(-iHt)=(exp(-i H1 t/n)*exp(-i H2 t/n))^n
@param:
qubit_list: the qubit needed to simulate the Hamiltonian
pauliOperator: the Hamiltonian (PauliOperator type)
t: time
slices: the approximate slices.
@return: QCircuit
'''
prog=QCircuit()
Hamiltonian=PauliOperator.toHamiltonian(0)
for i in range(slices):
for op in Hamiltonian:
prog.insert(simulate_one_term(qubit_list,op,t/slices))
return prog
[文档]
def adiabatic_simulation_with_configuration(qn_, Hp_, Hd_, step_, slices_, t_, shots_=1000):
'''
simulate hamiltonian with configuration and return result.
@param
qn_ : number of qubits
Hp_ : problem hamiltonian
Hd_ : driver hamiltonian
step_ : number of step in adiabatic simulation
slices_ : number of slices in trotter-suzuki approximation
t_ : total time for adiabatic simulation
shots_ : number of shots
'''
machine=init_quantum_machine(QMachineType.CPU)
prog=QProg()
q=machine.qAlloc_many(qn_)
c=machine.cAlloc_many(qn_)
prog.insert(single_gate_apply_to_all(gate=X, qubit_list=q))
prog.insert(single_gate_apply_to_all(gate=H, qubit_list=q))
for i in range(step_+1):
Ht=Hp_*(i/step_)+Hd_*((step_-i)/step_)
prog.insert(simulate_hamiltonian(q,Ht,t=t_/step_,slices=slices_))
machine.directly_run(program=prog)
result=machine.get_prob_dict(q)
destroy_quantum_machine(machine)
return result
[文档]
def ising_model(qubit_list,graph,gamma_):
prog=QCircuit()
length=len(graph)
for i in range(length):
prog.insert(CNOT(qubit_list[graph[i][0]],qubit_list[graph[i][1]]))\
.insert(RZ(qubit_list[graph[i][1]],2*gamma_*graph[i][2]))\
.insert(CNOT(qubit_list[graph[i][0]],qubit_list[graph[i][1]]))
return prog
[文档]
def pauliX_model(qubit_list,beta_):
prog=QCircuit()
length=len(qubit_list)
for i in range(length):
prog.insert(RX(qubit_list[i],2*beta_))
return prog
[文档]
def weight(graph,distribution):
sum=0
length=len(graph)
for i in range(length):
if distribution[graph[i][0]]!=distribution[graph[i][1]]:
sum=sum+graph[i][2]
return sum
[文档]
def get_qn_from_graph(graph):
max_qn=0
for edge in graph:
if edge[0]>max_qn:
max_qn=edge[0]
if edge[1]>max_qn:
max_qn=edge[1]
return max_qn+1
[文档]
def quantum_approximate_optimization_algorithm(
graph,
gamma_,
beta_,
use_prob_run=True,
use_quick_measure=True,
multiProcessing=False,
shots_=100,
dataType="list"
):
'''
quantum approximate optimization algorithm
@param
graph: origin graph
gamma_: problem hamiltonian parameter
beta_: driver hamiltonian parameter
use_prob_run : Use prob_run instead of repeatly measurement
multiProcessing: no implemented yet
shot_: execution times
(the following only enabled when "use_prob_run=True")
use_quick_measure : use quick measure instead of output probabilites
dataType : chosen data type for the prob_run
'''
step_=len(gamma_)
qn_=get_qn_from_graph(graph)
init()
prog=QProg()
q=qAlloc_many(qn_)
c=cAlloc_many(qn_)
prog.insert(single_gate_apply_to_all(gate=H, qubit_list=q))
for i in range(step_):
prog.insert(ising_model(q,graph,gamma_[i]))\
.insert(pauliX_model(q,beta_[i]))
if use_prob_run:
if use_quick_measure:
directly_run(QProg=prog)
result=quick_measure(q, shots_)
else:
result=prob_run(program=prog,noise=False,select_max=-1,qubit_list=q,dataType=dataType)
else:
prog.insert(meas_all(q,c))
result=run_with_configuration(program=prog, shots=shots_, cbit_list=c)
#print(result)
finalize()
target=0
if not multiProcessing:
for outcome in result:
if weight(graph,outcome)>target:
target=weight(graph,outcome)
else:
raise NotImplementedError()
return -target
[文档]
def binding(graph, shots):
return partial(qaoa_in_list,graph=graph,shots=shots)
[文档]
def qaoa_in_list(
arguments,
graph,
use_prob_run=True,
multiProcessing=False,
shots=100,
dataType='list',
):
#print(arguments)
step=len(arguments)//2
beta=list()
gamma=list()
for i in range(step):
beta.append(arguments[i])
gamma.append(arguments[i+step])
result= quantum_approximate_optimization_algorithm(
graph=graph,
gamma_=gamma,
beta_=beta,
use_prob_run=use_prob_run,
multiProcessing=multiProcessing,
shots_=shots,
dataType=dataType)
f=open("a.txt", 'a')
f.write(str(arguments)+' '+str(result)+'\n')
f.close()
#print(result)
return result
[文档]
def qaoa(graph,step_=1,shots_=1000, method="Nelder-Mead"):
gamma_=[]
beta_=[]
for i in range(step_):
gamma_.append(0)
beta_.append(0)
initial_guess=gamma_+beta_
result = minimize(binding(graph,shots_), initial_guess, method=method)
return result