-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
23 changed files
with
1,087 additions
and
514 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,9 @@ | ||
"""Algorithm module""" | ||
|
||
# from .ansatz import AlterLayeredAnsatz, QAOAAnsatz, QuantumNeuralNetwork | ||
# from .estimator import Estimator | ||
# from .hamiltonian import Hamiltonian | ||
# from .templates.amplitude import AmplitudeEmbedding | ||
# from .templates.angle import AngleEmbedding | ||
# from .templates.amplitude import AmplitudeEmbedding | ||
# from .templates.basic_entangle import BasicEntangleLayers | ||
from .ansatz import AlterLayeredAnsatz, QAOAAnsatz, QuantumNeuralNetwork | ||
from .estimator import Estimator | ||
from .hamiltonian import Hamiltonian | ||
from .templates.amplitude import AmplitudeEmbedding | ||
from .templates.angle import AngleEmbedding | ||
from .templates.amplitude import AmplitudeEmbedding | ||
from .templates.basic_entangle import BasicEntangleLayers |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
from ..circuits.quantum_circuit import QuantumCircuit | ||
from ..simulators.simulator import SVSimulator | ||
from ..elements import Parameter, ParameterExpression | ||
import numpy as np | ||
from ..exceptions import CircuitError | ||
from ..elements.matrices import XMatrix, YMatrix, ZMatrix | ||
from ..elements import QuantumGate, ControlledGate | ||
|
||
def assemble_grads(para_grads, gate_grads): | ||
grads = [] | ||
for var in para_grads: | ||
grad_p = para_grads[var] | ||
fullgrad = 0. | ||
for pos_g in grad_p: | ||
pos, gp = pos_g | ||
gg = gate_grads[pos[0]][pos[1]] | ||
fullgrad += gg * gp | ||
grads.append(fullgrad) | ||
|
||
return grads | ||
|
||
def grad_para_shift(qc:QuantumCircuit, hamiltonian, backend=SVSimulator()): | ||
""" | ||
Parameter shift gradients. Each gate must have one parameter | ||
""" | ||
para_grads = qc._calc_parameter_grads() | ||
gate_grads= [[] for _ in qc.gates] | ||
|
||
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 op.name not in ["RX", "RY", "RZ"]: | ||
raise CircuitError("It seems the circuit can not apply parameter-shift rule to calculate gradient.You may need compile the circuit first") | ||
op.paras[0] = op.paras[0] + np.pi/2 | ||
res1 = sum(backend.run(qc, hamiltonian=hamiltonian)["pauli_expects"]) | ||
op.paras[0] = op.paras[0] - np.pi | ||
res2 = sum(backend.run(qc, hamiltonian=hamiltonian)["pauli_expects"]) | ||
op.paras[0]._undo(2) | ||
gate_grads[i].append((res1 - res2) / 2.) | ||
|
||
return assemble_grads(para_grads, gate_grads) | ||
|
||
def grad_finit_diff(qc, hamiltonian, backend=SVSimulator()): | ||
variables = qc.variables | ||
grads = [] | ||
for v in variables: | ||
v.value += 1e-10 | ||
res1 = sum(backend.run(qc, hamiltonian=hamiltonian)["pauli_expects"]) | ||
v.value -= 2 * 1e-10 | ||
res2 = sum(backend.run(qc, hamiltonian=hamiltonian)["pauli_expects"]) | ||
v.value += 1e-10 | ||
grads.append((res1 - res2) / (2 * 1e-10)) | ||
|
||
return grads | ||
|
||
|
||
def grad_gate(op): | ||
""" | ||
TODO:support more gates | ||
""" | ||
if isinstance(op, ControlledGate): | ||
if op._targ_name == "RX": | ||
circ = QuantumCircuit(max(op.pos)+1) | ||
deriv_mat = -0.5j * XMatrix @ op._get_targ_matrix() | ||
circ << QuantumGate("dRX", op.targs, [], deriv_mat) | ||
cdim = 1 << (len(op.ctrls)) | ||
proj_mat = np.zeros((cdim, cdim)) | ||
proj_mat[cdim-1, cdim-1] = 1. | ||
circ << QuantumGate("projCtrl", op.ctrls, [], proj_mat) | ||
return circ.wrap() | ||
|
||
elif 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) | ||
cdim = 1 << (len(op.ctrls)) | ||
proj_mat = np.zeros((cdim, cdim)) | ||
proj_mat[cdim-1, cdim-1] = 1. | ||
circ << QuantumGate("projCtrl", op.ctrls, [], proj_mat) | ||
return circ.wrap() | ||
|
||
elif 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) | ||
cdim = 1 << (len(op.ctrls)) | ||
proj_mat = np.zeros((cdim, cdim)) | ||
proj_mat[cdim-1, cdim-1] = 1. | ||
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 | ||
|
||
def grad_adjoint(qc, hamiltonian, psi_in=np.array([], dtype=complex)): | ||
""" | ||
Reverse mode gradient: arXiv:2009.02823 | ||
""" | ||
para_grads = qc._calc_parameter_grads() | ||
backend = SVSimulator() | ||
lam = backend.run(qc, psi = psi_in)["statevector"] | ||
phi = np.copy(lam) | ||
lam = backend._apply_hamil(hamiltonian, lam) | ||
begin = 0 | ||
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)): | ||
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)): | ||
mu = np.copy(phi) | ||
mu = backend._apply_op(grad_gate(op), mu) | ||
gate_grads[i].append(np.real(2. * np.inner(lam.conj(), mu))) | ||
lam = backend._apply_op(op.dagger(), lam) | ||
return assemble_grads(para_grads, gate_grads) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import numpy as np | ||
|
||
def adam(func, x, gradsf, args=(), call_back=None, eta=0.01,beta1=0.9, beta2=0.999, epsilon=1e-8, maxiter=1000, tol=1e-8, verbose=False): | ||
n_para = len(x) | ||
mt = np.zeros(n_para) | ||
vt = np.zeros(n_para) | ||
|
||
traj = [] | ||
if verbose: | ||
print((" "*5).join(["step".ljust(10), "loss".ljust(10), "grad_norm".ljust(10)])) | ||
|
||
grads_norm = 0. | ||
for j in range(maxiter): | ||
traj.append(func(x, *args)) | ||
if verbose: | ||
print((" "*5).join([("%d" %j).ljust(10), ("%.5f" %traj[j]).ljust(10), ("%.5f" %grads_norm).ljust(10)])) | ||
if j > 0 and abs(traj[j]-traj[j-1]) <= tol: | ||
return x, traj[-1], traj | ||
|
||
grads = np.array(gradsf(x, *args)) | ||
grads_norm = np.linalg.norm(grads) | ||
mt = beta1 * mt + (1.-beta1) * grads | ||
vt = beta1 * vt + (1.-beta2) * grads**2 | ||
mtt = mt / (1-beta1**(j+2)) | ||
vtt = vt / (1-beta2**(j+2)) | ||
x = x - eta * mtt / (np.sqrt(vtt) + epsilon) | ||
if call_back: | ||
call_back(x, *args) | ||
traj.append(func(x, *args)) | ||
return x, traj[-1], traj | ||
|
||
|
||
def spsa_grad(func, x, k, args=(), spsa_iter=10, c=0.1, gamma=0.101): | ||
|
||
dim = len(x) | ||
ck = c/(k)**gamma | ||
gx = 0.0 | ||
for i in range(spsa_iter): | ||
Delta = 2*np.round(np.random.rand(dim))-1 | ||
x1 = x + ck*Delta | ||
x2 = x - ck*Delta | ||
y1 = func(x1, *args) | ||
y2 = func(x2, *args) | ||
gx += (y1 - y2) / (2*ck*Delta) | ||
gx = gx / spsa_iter | ||
return gx | ||
|
||
def spsa(func, x, args=(), call_back=None, spsa_iter=10, max_iter=1000, a=0.1, c=0.1, A=100, alpha=0.602, gamma=0.101, tol=1e-8, verbose=False): | ||
'''SPSA minimize | ||
c: at a level of standard deviation of func | ||
A: <=10% of max_iter ''' | ||
traj = [func(x, *args)] | ||
if verbose: | ||
print((" "*5).join(["step".ljust(10), "loss".ljust(10), "grad_norm".ljust(10)])) | ||
|
||
grads_norm = 0. | ||
for k in range(max_iter): | ||
if verbose: | ||
print((" "*5).join([("%d" %k).ljust(10), ("%.5f" %traj[k]).ljust(10), ("%.5f" %grads_norm).ljust(10)])) | ||
if k > 0 and abs(traj[k]-traj[k-1]) <= tol: | ||
return x, traj[-1], traj | ||
|
||
ak = a/(k+1+A)**alpha | ||
grads = spsa_grad(func, x, k+1, args, spsa_iter, c=c, gamma=gamma) | ||
grads_norm = np.linalg.norm(grads) | ||
x = x - ak * grads | ||
if call_back: | ||
call_back(x, *args) | ||
traj.append(func(x, *args)) | ||
|
||
return x, traj[-1], traj | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,9 @@ | ||
from .classical_element import Cif | ||
from .instruction import Barrier, Instruction, Measure, Reset | ||
from .pulses import Delay, QuantumPulse, XYResonance | ||
from .quantum_gate import ControlledGate, QuantumGate | ||
from .quantum_gate import ControlledGate, QuantumGate, CircuitWrapper, ControlledCircuitWrapper | ||
from .unitary import UnitaryDecomposer | ||
from .utils import extract_float, reorder_matrix | ||
from .oracle import OracleGate, ControlledOracle | ||
from .parameters import Parameter, ParameterExpression, ParameterType | ||
from .noise import KrausChannel, UnitaryChannel |
Oops, something went wrong.