Skip to content

Commit

Permalink
Merge pull request #94 from Blueqat/vqe-sparse
Browse files Browse the repository at this point in the history
ENH: Implement sparse matrix expectation for VQE
  • Loading branch information
gyu-don authored May 20, 2020
2 parents 80425de + b84351a commit 23c822a
Showing 1 changed file with 44 additions and 5 deletions.
49 changes: 44 additions & 5 deletions blueqat/vqe.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ def __init__(self, hamiltonian, n_params):
self.hamiltonian = hamiltonian
self.n_params = n_params
self.n_qubits = self.hamiltonian.max_n() + 1
self.sparse = None

def make_sparse(self, fmt='csc', make_method=None):
"""Make sparse matrix. This method may be changed in the future release."""
if make_method:
self.sparse = make_method(self.hamiltonian)
else:
self.sparse = self.hamiltonian.to_matrix(sparse=fmt)

def get_circuit(self, params):
"""Make a circuit from parameters."""
Expand All @@ -51,13 +59,27 @@ def get_energy(self, circuit, sampler):
val += prob * meas.coeff
return val.real

def get_objective(self, sampler):
def get_energy_sparse(self, circuit):
"""Get energy using sparse matrix. This method may be changed in the future release."""
return sparse_expectation(self.sparse, circuit.run())

def get_objective(self, sampler=None):
"""Get an objective function to be optimized."""
def objective(params):
circuit = self.get_circuit(params)
circuit.make_cache()
return self.get_energy(circuit, sampler)
return objective

def obj_expect(params):
circuit = self.get_circuit(params)
circuit.make_cache()
return self.get_energy_sparse(circuit)

if sampler is not None:
return objective
if self.sparse is None:
self.make_sparse()
return obj_expect

class QaoaAnsatz(AnsatzBase):
"""Ansatz for QAOA."""
Expand Down Expand Up @@ -140,7 +162,11 @@ def get_probs(self, sampler=None, rerun=None, store=True):
return self._probs
if sampler is None:
sampler = self.vqe.sampler
probs = sampler(self.circuit, range(self.circuit.n_qubits))

if sampler is None:
probs = expect(self.circuit.run(returns="statevector"), range(self.circuit.n_qubits))
else:
probs = sampler(self.circuit, range(self.circuit.n_qubits))
if store:
self._probs = probs
return probs
Expand All @@ -153,8 +179,7 @@ def __init__(self, ansatz, minimizer=None, sampler=None):
method="Powell",
options={"ftol": 5.0e-2, "xtol": 5.0e-2, "maxiter": 1000}
)
self.sampler = sampler or non_sampling_sampler
self._result = None
self.sampler = sampler

def run(self, verbose=False):
objective = self.ansatz.get_objective(self.sampler)
Expand Down Expand Up @@ -291,3 +316,17 @@ def sampling(circuit, meas):
return {k: v / shots for k, v in counts.items()}

return sampling


def sparse_expectation(mat, vec):
"""Calculate expectation value <vec|mat|vec>.
Args:
mat (scipy sparse matrix): Sparse matrix
vec (numpy array): Vector
Returns:
(Real part of) expectation value <vec|mat|vec>.
Remarks: when mat is Hermitian, <vec|mat|vec> is real.
"""
return np.vdot(vec, mat.dot(vec)).real

0 comments on commit 23c822a

Please sign in to comment.