Skip to content

Commit

Permalink
fix precommit
Browse files Browse the repository at this point in the history
  • Loading branch information
donghufeng committed Dec 2, 2024
1 parent f1cff53 commit 4661383
Show file tree
Hide file tree
Showing 27 changed files with 221 additions and 402 deletions.
21 changes: 10 additions & 11 deletions examples/quantum_rl/search/quantum_evolution_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@
import sys

sys.path.insert(0, " ")
import time
from functools import reduce
import time # noqa: E402
from functools import reduce # noqa: E402

import cirq
import numpy as np
from misc.utils import create_exp_dir
from pymoo.optimize import minimize
from pymop.problem import Problem
from search import nsganet as engine
from search import quantum_encoding, quantum_train_search
import cirq # noqa: E402
import numpy as np # noqa: E402
from misc.utils import create_exp_dir # noqa: E402
from pymoo.optimize import minimize # noqa: E402
from pymop.problem import Problem # noqa: E402
from search import nsganet as engine # noqa: E402
from search import quantum_encoding, quantum_train_search # noqa: E402

parser = argparse.ArgumentParser("Multi-objetive Genetic Algorithm for quantum NAS")
parser.add_argument("--save", type=str, default="quantumGA", help="experiment name")
Expand Down Expand Up @@ -176,15 +176,14 @@ def main(qubits, n_actions, observables):
# configure the nsga-net method
method = engine.nsganet(pop_size=args.pop_size, n_offsprings=args.n_offspring, eliminate_duplicates=True)

return minimize(
return minimize(
problem,
method,
callback=do_every_generations,
termination=("n_gen", args.n_gens),
)



if __name__ == "__main__":
n_qubits = 4 # Dimension of the state vectors in CartPole
n_actions = 2 # Number of actions in CartPole
Expand Down
2 changes: 1 addition & 1 deletion examples/quantum_rl/search/quantum_train_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import numpy as np
import tensorflow as tf
from misc.utils import compute_returns, create_exp_dir, gather_episodes
from models.quantum_models import generate_model_policy as Network
from models.quantum_models import generate_model_policy as Network # noqa: N812
from search import quantum_encoding


Expand Down
27 changes: 10 additions & 17 deletions examples/quantum_rl/validation/quantum_train.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,14 @@
import sys

sys.path.insert(0, " ")
import time
from functools import reduce
import time # noqa: E402
from functools import reduce # noqa: E402

import cirq
import gym
import models.quantum_genotypes as genotypes
import numpy as np
import tensorflow as tf
from misc.utils import compute_returns, create_exp_dir, gather_episodes
from models.quantum_models import generate_model_policy as Network
import cirq # noqa: E402
import numpy as np # noqa: E402
import tensorflow as tf # noqa: E402
from misc.utils import compute_returns, create_exp_dir, gather_episodes # noqa: E402
from models.quantum_models import generate_model_policy as Network # noqa: E402,N812

parser = argparse.ArgumentParser("Quantum RL Training")
parser.add_argument("--save", type=str, default="qEXP-quafu18_6", help="experiment name")
Expand Down Expand Up @@ -82,16 +80,10 @@ def main(qubits, genotype, observables):
# Assign the model parameters to each optimizer
w_in, w_var, w_out = 1, 0, 2

# best_reward = 0
for epoch in range(n_epochs):
logging.info("epoch %d", epoch)

reward_his = train(model, optimizer_in, optimizer_var, optimizer_out, w_in, w_var, w_out)
# valid_reward = infer(model)

# if np.mean(valid_reward) >= best_reward:
# model.save_weights(os.path.join(args.save, 'weights_id97_quafu.h5'))
# best_reward = np.mean(valid_reward)
train(model, optimizer_in, optimizer_var, optimizer_out, w_in, w_var, w_out)


# Training
Expand Down Expand Up @@ -170,9 +162,10 @@ def reinforce_update(states, actions, returns, logits2, model):
break
return episode_reward_history


if __name__ == "__main__":
qubits = cirq.GridQubit.rect(1, args.n_qubits)
genotype = eval("genotypes.%s" % args.arch)
genotype = eval("genotypes.%s" % args.arch) # noqa:SCS101
ops = [cirq.Z(q) for q in qubits]
observables = [reduce((lambda x, y: x * y), ops)] # Z_0*Z_1*Z_2*Z_3

Expand Down
22 changes: 10 additions & 12 deletions examples/quantum_rl/visualization/plot_gif.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,16 @@
import sys

sys.path.insert(0, " ")
from functools import reduce
from functools import reduce # noqa: E402

import cirq
import gym
import models.quantum_genotypes as genotypes
import numpy as np
import tensorflow as tf
from misc.utils import get_obs_policy, get_quafu_exp
from models.quantum_models import generate_circuit
from models.quantum_models import generate_model_policy as Network
from models.quantum_models import get_model_circuit_params
from PIL import Image
import cirq # noqa: E402
import gym # noqa: E402
import numpy as np # noqa: E402
from misc.utils import get_obs_policy, get_quafu_exp # noqa: E402
from models.quantum_models import generate_circuit # noqa: E402
from models.quantum_models import generate_model_policy as Network # noqa:N812,E402
from models.quantum_models import get_model_circuit_params # noqa: E402
from PIL import Image # noqa: E402

parser = argparse.ArgumentParser("Plot gif of pre-trained quantum models on quafu cloud platform")
parser.add_argument("--env_name", type=str, default="CartPole-v1", help="environment name")
Expand All @@ -40,7 +38,7 @@

if __name__ == "__main__":
qubits = cirq.GridQubit.rect(1, args.n_qubits)
genotype = eval("genotypes.%s" % args.arch)
genotype = eval("genotypes.%s" % args.arch) # noqa:SCS101
ops = [cirq.Z(q) for q in qubits]
observables = [reduce((lambda x, y: x * y), ops)] # Z_0*Z_1*Z_2*Z_3
model = Network(qubits, genotype, args.n_actions, args.beta, observables, args.env_name)
Expand Down
2 changes: 0 additions & 2 deletions quafu/algorithms/ansatz.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ class QAOAAnsatz(Ansatz):

def __init__(self, hamiltonian: Hamiltonian, num_qubits: int, num_layers: int = 1):
"""Instantiate a QAOAAnsatz"""
# self._pauli_list = hamiltonian.pauli_list
# self._coeffs = hamiltonian.coeffs
self._h = hamiltonian
self._num_layers = num_layers
self._evol = ProductFormula()
Expand Down
84 changes: 39 additions & 45 deletions quafu/algorithms/estimator.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,45 +95,44 @@ def _run_real_machine(self, observables: Hamiltonian, cache_key: Optional[str] =
res = self._measure_obs(self._circ)
return res, []

for obs in obslist:
for p in obs[1]:
if p not in measures:
raise CircuitError("Qubit %d in observer %s is not measured." % (p, obs[0]))

measure_basis, targlist = merge_measure(obslist)
print("Job start, need measured in ", measure_basis)

exec_res = []
if cache_key is not None and cache_key in self._exp_cache:
# try to retrieve exe results from cache
exec_res = self._exp_cache[cache_key]
else:
for obs in obslist:
for p in obs[1]:
if p not in measures:
raise CircuitError("Qubit %d in observer %s is not measured." % (p, obs[0]))

measure_basis, targlist = merge_measure(obslist)
print("Job start, need measured in ", measure_basis)

exec_res = []
if cache_key is not None and cache_key in self._exp_cache:
# try to retrieve exe results from cache
exec_res = self._exp_cache[cache_key]
else:
# send tasks to cloud platform
lst_task_id = []
for measure_base in measure_basis:
res = self._measure_obs(self._circ, measure_base=measure_base)
self._circ.gates = copy.deepcopy(inputs)
lst_task_id.append(res.taskid)

for tid in lst_task_id:
# retrieve task results
while True:
res = self._task.retrieve(tid)
if res.task_status == "Completed":
exec_res.append(res)
break
time.sleep(0.2)

if cache_key is not None:
# put into cache
self._exp_cache[cache_key] = exec_res

measure_results = []
for obi in range(len(obslist)):
obs = obslist[obi]
rpos = [measures.index(p) for p in obs[1]]
measure_results.append(exec_res[targlist[obi]].calculate_obs(rpos))
# send tasks to cloud platform
lst_task_id = []
for measure_base in measure_basis:
res = self._measure_obs(self._circ, measure_base=measure_base)
self._circ.gates = copy.deepcopy(inputs)
lst_task_id.append(res.taskid)

for tid in lst_task_id:
# retrieve task results
while True:
res = self._task.retrieve(tid)
if res.task_status == "Completed":
exec_res.append(res)
break
time.sleep(0.2)

if cache_key is not None:
# put into cache
self._exp_cache[cache_key] = exec_res

measure_results = []
for obi in range(len(obslist)):
obs = obslist[obi]
rpos = [measures.index(p) for p in obs[1]]
measure_results.append(exec_res[targlist[obi]].calculate_obs(rpos))

return sum(measure_results)

Expand Down Expand Up @@ -188,14 +187,9 @@ def run(
Returns:
Expectation value
"""
res = None
if params is not None:
self._circ._update_params(params)

if self._backend == "sim":
res = self._run_simulation(observables)
else:
# currently cache only work for real machine (cloud systems)
res = self._run_real_machine(observables, cache_key=cache_key)

return res
return self._run_simulation(observables)
return self._run_real_machine(observables, cache_key=cache_key)
45 changes: 17 additions & 28 deletions quafu/algorithms/gradients/gradiant.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,7 @@ def grad_para_shift(qc: QuantumCircuit, hamiltonian, backend=SVSimulator()):

for i, op in enumerate(qc.gates):
if len(op.paras) > 0:
if isinstance(op.paras[0], Parameter) or isinstance(
op.paras[0], ParameterExpression
):
if isinstance(op.paras[0], Parameter) or isinstance(op.paras[0], ParameterExpression):
if op.name not in ["RX", "RY", "RZ"]:
raise CircuitError(
"It seems the circuit can not apply parameter-shift rule to calculate gradient."
Expand Down Expand Up @@ -90,7 +88,7 @@ def grad_gate(op):
circ << QuantumGate("projCtrl", op.ctrls, [], proj_mat)
return circ.wrap()

elif op._targ_name == "RY":
if op._targ_name == "RY":
circ = QuantumCircuit(max(op.pos) + 1)
deriv_mat = -0.5j * YMatrix @ op._get_targ_matrix()
circ << QuantumGate("dRY", op.targs, [], deriv_mat)
Expand All @@ -100,7 +98,7 @@ def grad_gate(op):
circ << QuantumGate("projCtrl", op.ctrls, [], proj_mat)
return circ.wrap()

elif op._targ_name == "RZ":
if op._targ_name == "RZ":
circ = QuantumCircuit(max(op.pos) + 1)
deriv_mat = -0.5j * ZMatrix @ op._get_targ_matrix()
circ << QuantumGate("dRZ", op.targs, [], deriv_mat)
Expand All @@ -109,21 +107,18 @@ def grad_gate(op):
proj_mat[cdim - 1, cdim - 1] = 1.0
circ << QuantumGate("projCtrl", op.ctrls, [], proj_mat)
return circ.wrap()
else:
raise NotImplementedError

else:
if op.name == "RX":
deriv_mat = -0.5j * XMatrix @ op.matrix
return QuantumGate("dRX", op.pos, [], deriv_mat)
elif op.name == "RY":
deriv_mat = -0.5j * YMatrix @ op.matrix
return QuantumGate("dRY", op.pos, [], deriv_mat)
elif op.name == "RZ":
deriv_mat = -0.5j * ZMatrix @ op.matrix
return QuantumGate("dRZ", op.pos, [], deriv_mat)
else:
raise NotImplementedError
raise NotImplementedError

if op.name == "RX":
deriv_mat = -0.5j * XMatrix @ op.matrix
return QuantumGate("dRX", op.pos, [], deriv_mat)
if op.name == "RY":
deriv_mat = -0.5j * YMatrix @ op.matrix
return QuantumGate("dRY", op.pos, [], deriv_mat)
if op.name == "RZ":
deriv_mat = -0.5j * ZMatrix @ op.matrix
return QuantumGate("dRZ", op.pos, [], deriv_mat)
raise NotImplementedError


def grad_adjoint(qc, hamiltonian, psi_in=np.array([], dtype=complex)):
Expand All @@ -139,20 +134,14 @@ def grad_adjoint(qc, hamiltonian, psi_in=np.array([], dtype=complex)):
end = len(qc.gates)
gate_grads = [[] for _ in range(end)]
for i, op in enumerate(qc.gates):
if len(op.paras) > 0 and (
isinstance(op.paras[0], Parameter)
or isinstance(op.paras[0], ParameterExpression)
):
if len(op.paras) > 0 and (isinstance(op.paras[0], Parameter) or isinstance(op.paras[0], ParameterExpression)):
begin = i
break

for i in range(begin, end)[::-1]:
op = qc.gates[i]
phi = backend._apply_op(op.dagger(), phi)
if len(op.paras) > 0 and (
isinstance(op.paras[0], Parameter)
or isinstance(op.paras[0], ParameterExpression)
):
if len(op.paras) > 0 and (isinstance(op.paras[0], Parameter) or isinstance(op.paras[0], ParameterExpression)):
mu = np.copy(phi)
mu = backend._apply_op(grad_gate(op), mu)
gate_grads[i].append(np.real(2.0 * np.inner(lam.conj(), mu)))
Expand Down
3 changes: 1 addition & 2 deletions quafu/algorithms/gradients/param_shift.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,7 @@ def grad(self, obs: Hamiltonian, params: List[float], cache_key: Optional[str] =
res[i] = self._est.run(obs, shifted_params, cache_key=final_cache_key)

num_shift_params = len(res)
grads = (res[: num_shift_params // 2] - res[num_shift_params // 2 :]) / 2
return grads
return (res[: num_shift_params // 2] - res[num_shift_params // 2 :]) / 2

def new_grad(self, obs: Hamiltonian, params: List[float]):
"""Calculate the gradients of given the circuit based on the parameter shift rule
Expand Down
6 changes: 3 additions & 3 deletions quafu/algorithms/gradients/vjp.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,9 @@ def compute_vjp(jac: np.ndarray, dy: np.ndarray):
.. math::
\begin{bmatrix}
\frac{\partial y_1}{\partial x_1} & \cdots & \frac{\partial y_1}{x_n} \\
\vdots & \ddots & \vdots \\
\frac{\partial y_m}{\partial x_1} & \cdots & \frac{\partial y_m}{x_n}
\frac{\partial y_1}{\partial x_1} & \cdots & \frac{\partial y_1}{x_n} \\
\vdots & \ddots & \vdots \\
\frac{\partial y_m}{\partial x_1} & \cdots & \frac{\partial y_m}{x_n}
\end{bmatrix}
`dy` is actually the vjp of dependent node
Expand Down
4 changes: 1 addition & 3 deletions quafu/algorithms/templates/amplitude.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
import quafu.elements.element_gates as qeg
from quafu.elements import QuantumGate

# from .basic_entangle import BasicEntangleLayers


class AmplitudeEmbedding:
def __init__(self, state, num_qubits, pad_with=None, normalize=False):
Expand Down Expand Up @@ -62,7 +60,7 @@ def __radd__(self, other):

def _preprocess(self, state, num_qubits, pad_with, normalize):
batched = np.ndim(state) > 1
##TODO(qtzhuang): If state are batched, additional processing is required
# TODO(qtzhuang): If state are batched, additional processing is required
if batched:
raise ValueError("Currently not support batched state.")
state_batch = state if batched else [state]
Expand Down
Loading

0 comments on commit 4661383

Please sign in to comment.