Skip to content

Commit

Permalink
add qpu engine
Browse files Browse the repository at this point in the history
  • Loading branch information
liwt31 committed May 25, 2023
1 parent 3404845 commit 8c1afbe
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 38 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,6 @@ which is also a good introduction to the software.
## Research and Applications

### Variational basis state encoder
An efficient algorithm to encoder phonon states in electron-phonon systems for quantum computation.
An efficient algorithm to encode phonon states in electron-phonon systems for quantum computation.
See [examples](https://github.com/tencent-quantum-lab/TenCirChem/tree/master/example).
Reference paper: https://arxiv.org/pdf/2301.01442.pdf (published in PRR).
110 changes: 91 additions & 19 deletions docs/source/tutorial_jupyter/marcus.ipynb

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ pandas
jax
jaxlib
pyscf
tensorcircuit-nightly
tensorcircuit
openfermion
qiskit
pylatexenc
SciencePlots
noisyopt
renormalizer==0.0.9
renormalizer==0.0.10
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"numpy",
"scipy",
"pandas",
"tensorcircuit-nightly",
"tensorcircuit",
"pyscf",
"openfermion",
"qiskit",
Expand Down
31 changes: 30 additions & 1 deletion tencirchem/static/engine_hea.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@

import numpy as np
import tensorcircuit as tc
from tensorcircuit import DMCircuit
from tensorcircuit import Circuit, DMCircuit
from tensorcircuit.noisemodel import circuit_with_noise
from tensorcircuit.experimental import parameter_shift_grad
from tensorcircuit.cloud.wrapper import batch_expectation_ps

from tencirchem.utils.backend import jit

Expand Down Expand Up @@ -72,6 +73,23 @@ def get_energy_tensornetwork_noise_shot(params, paulis, coeffs, get_dmcircuit, n
return sample_expectation_pauli(c, paulis, coeffs, shots, noise_conf)


def get_energy_qpu(params, paulis, coeffs, get_circuit, shots: int):
c: Circuit = get_circuit(params)
pss = []
symbol_mapping = {"X": 1, "Y": 2, "Z": 3}
for pauli in paulis:
ps = [0] * c.circuit_param["nqubits"]
for idx, symbol in pauli:
ps[idx] = symbol_mapping[symbol]
pss.append(ps)
es = []
for _ in range((shots - 1) // 8192 + 1):
e = batch_expectation_ps(c, pss, device="tianxuan_s1", ws=coeffs, shots=8192)
es.append(e)
print(es)
return np.mean(es)


def _get_energy_and_grad(partial_get_energy, params, grad):
if grad == "param-shift":
e = partial_get_energy(params)
Expand Down Expand Up @@ -120,3 +138,14 @@ def get_energy_and_grad_tensornetwork_noise_shot(params, paulis, coeffs, get_dmc
shots=shots,
)
return _get_energy_and_grad(partial_get_energy, params, grad)


def get_energy_and_grad_qpu(params, paulis, coeffs, get_circuit, shots: int, grad):
partial_get_energy = partial(
get_energy_qpu,
paulis=paulis,
coeffs=coeffs,
get_circuit=get_circuit,
shots=shots,
)
return _get_energy_and_grad(partial_get_energy, params, grad)
47 changes: 34 additions & 13 deletions tencirchem/static/hea.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@
get_energy_tensornetwork_noise,
get_energy_tensornetwork_shot,
get_energy_tensornetwork_noise_shot,
get_energy_qpu,
get_energy_and_grad_tensornetwork,
get_energy_and_grad_tensornetwork_noise,
get_energy_and_grad_tensornetwork_shot,
get_energy_and_grad_tensornetwork_noise_shot,
get_energy_and_grad_qpu,
)
from tencirchem.static.hamiltonian import get_hop_from_integral
from tencirchem.utils.misc import reverse_fop_idx, scipy_opt_wrap, reverse_qop_idx
Expand Down Expand Up @@ -361,6 +363,7 @@ def get_circuit(params):
self.shots = 4096
self._grad = "param-shift"

self.scipy_minimize_options = None
self._params = None
self.opt_res = None

Expand Down Expand Up @@ -585,8 +588,14 @@ def energy(self, params: Tensor = None, engine: str = None) -> float:
self.shots,
)
else:
assert self.engine == "qpu"
assert False
assert engine == "qpu"
e = get_energy_qpu(
params,
tuple(self.h_qubit_op.terms.keys()),
list(self.h_qubit_op.terms.values()),
self.get_circuit,
self.shots,
)
return e

def energy_and_grad(self, params: Tensor = None, engine: str = None, grad: str = None) -> Tuple[float, Tensor]:
Expand Down Expand Up @@ -633,15 +642,15 @@ def energy_and_grad(self, params: Tensor = None, engine: str = None, grad: str =
raise ValueError("Must provide a gradient algorithm")

if engine == "tensornetwork":
e, grad = get_energy_and_grad_tensornetwork(params, self.h_array, self.get_circuit, grad)
e, grad_array = get_energy_and_grad_tensornetwork(params, self.h_array, self.get_circuit, grad)
elif engine == "tensornetwork-noise":
e, grad = get_energy_and_grad_tensornetwork_noise(
e, grad_array = get_energy_and_grad_tensornetwork_noise(
params, self.h_array, self.get_dmcircuit_no_noise, self.engine_conf, grad
)
elif engine == "tensornetwork-shot":
if grad == "autodiff":
raise ValueError(f"Engine {engine} is incompatible with grad method {grad}")
e, grad = get_energy_and_grad_tensornetwork_shot(
e, grad_array = get_energy_and_grad_tensornetwork_shot(
params,
tuple(self.h_qubit_op.terms.keys()),
list(self.h_qubit_op.terms.values()),
Expand All @@ -652,7 +661,7 @@ def energy_and_grad(self, params: Tensor = None, engine: str = None, grad: str =
elif engine == "tensornetwork-noise&shot":
if grad == "autodiff":
raise ValueError(f"Engine {engine} is incompatible with grad method {grad}")
e, grad = get_energy_and_grad_tensornetwork_noise_shot(
e, grad_array = get_energy_and_grad_tensornetwork_noise_shot(
params,
tuple(self.h_qubit_op.terms.keys()),
list(self.h_qubit_op.terms.values()),
Expand All @@ -662,23 +671,35 @@ def energy_and_grad(self, params: Tensor = None, engine: str = None, grad: str =
grad,
)
else:
assert self.engine == "qpu"
assert False
return e, grad
assert engine == "qpu"
if grad == "autodiff":
raise ValueError(f"Engine {engine} is incompatible with grad method {grad}")
e, grad_array = get_energy_and_grad_qpu(
params,
tuple(self.h_qubit_op.terms.keys()),
list(self.h_qubit_op.terms.values()),
self.get_circuit,
self.shots,
grad,
)
return e, grad_array

def kernel(self):
logger.info("Begin optimization")

func, stating_time = self.get_opt_function(with_time=True)

time1 = time()
if self.grad == "free":
if self.engine in ["tensornetwork", "tensornetwork-noise"]:
opt_res = minimize(func, x0=self.init_guess, method="COBYLA")
if self.engine in ["tensornetwork", "tensornetwork-noise", "qpu"]:
opt_res = minimize(func, x0=self.init_guess, method="COBYLA", options=self.scipy_minimize_options)
else:
assert self.engine in ["tensornetwork-shot", "tensornetwork-noise&shot"]
opt_res = minimizeSPSA(func, x0=self.init_guess, paired=False, niter=125)
opt_res = minimizeSPSA(func, x0=self.init_guess, paired=False, niter=100, disp=True)
else:
opt_res = minimize(func, x0=self.init_guess, jac=True, method="L-BFGS-B")
opt_res = minimize(
func, x0=self.init_guess, jac=True, method="L-BFGS-B", options=self.scipy_minimize_options
)

time2 = time()

Expand Down
2 changes: 1 addition & 1 deletion tencirchem/static/ucc.py
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,7 @@ def energy_and_grad(self, params: Tensor = None, engine: str = None) -> Tuple[fl

def apply_excitation(self, state: Tensor, ex_op: Tuple, engine: str = None) -> Tensor:
"""
Apply a given excitation operator to a give state.
Apply a given excitation operator to a given state.
Parameters
----------
Expand Down

0 comments on commit 8c1afbe

Please sign in to comment.