import numpy as np
from blueqat import Circuit
from blueqat.pauli import X, Y, Z, I
from blueqat.pauli import qubo_bit as q
from blueqat.vqe import AnsatzBase, Vqe
def an(index):
return 0.5 * X[index] + 0.5j * Y[index]
def cr(index):
return 0.5 * X[index] - 0.5j * Y[index]
op1 = (cr(1) * an(0) + cr(0) * an(1)).to_expr().simplify()
op2 = (cr(3) * an(2) + cr(2) * an(3)).to_expr().simplify()
class QaoaQaoaAnsatz(AnsatzBase):
def __init__(self, hamiltonian, step=1, init_circuit=None):
super().__init__(hamiltonian, step * 2)
self.hamiltonian = hamiltonian.to_expr().simplify()
if not self.check_hamiltonian():
raise ValueError("Hamiltonian terms are not commutable")
self.step = step
self.n_qubits = self.hamiltonian.max_n() + 1
if init_circuit:
self.init_circuit = init_circuit
if init_circuit.n_qubits > self.n_qubits:
self.n_qubits = init_circuit.n_qubits
else:
self.init_circuit = Circuit(self.n_qubits).h[:]
self.init_circuit.make_cache()
self.time_evolutions = [term.get_time_evolution() for term in self.hamiltonian]
self.time_evolutions1 = [term.get_time_evolution() for term in op1]
self.time_evolutions2 = [term.get_time_evolution() for term in op2]
def check_hamiltonian(self):
"""Check hamiltonian is commutable. This condition is required for QaoaAnsatz"""
return self.hamiltonian.is_all_terms_commutable()
def get_circuit(self, params):
c = self.init_circuit.copy()
betas = params[:self.step]
gammas = params[self.step:]
for beta, gamma in zip(betas, gammas):
beta *= np.pi
gamma *= 2 * np.pi
for evo in self.time_evolutions:
evo(c, gamma)
for evo1 in self.time_evolutions1:
evo1(c, beta)
for evo2 in self.time_evolutions2:
evo2(c, beta)
return c
h = 4*q(0)+4*q(1)+4*q(2)+4*q(3)+4*q(0)*q(1)+4*q(0)*q(2)+8*q(1)*q(2)+2*q(1)*q(3)+2*q(2)*q(3)
h = h.to_expr().simplify()
runner = Vqe(QaoaQaoaAnsatz(h,4,Circuit().h[0].cx[0,1].x[0].h[2].cx[2,3].x[2]))
result = runner.run()
# get probability
print(result.most_common(12))
print('Result by QAOA')
print(runner.ansatz.get_energy(result.circuit, runner.sampler))
# Hamiltonian to matrix
mat = h.to_matrix()
# Calculate by numpy
print('Result by numpy')
print(np.linalg.eigh(mat)[0][0])