Skip to content

Commit 686a49f

Browse files
refactor vqnhe code a bit
1 parent 4b642b2 commit 686a49f

File tree

3 files changed

+46
-24
lines changed

3 files changed

+46
-24
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66

77
- add gradient free scipy interface for optimization
88

9+
### Changed
10+
11+
- futher refactor VQNHE code in applications
12+
913
## 0.0.220311
1014

1115
### Added

examples/vqnhe_h6.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,18 @@
77
import numpy as np
88

99
import tensorcircuit as tc
10-
from tensorcircuit.applications.vqes import VQNHE, JointSchedule
10+
from tensorcircuit.applications.vqes import VQNHE, JointSchedule, construct_matrix_v3
1111

1212
tc.set_backend("tensorflow")
1313
tc.set_dtype("complex128")
1414

1515
h6h = np.load("./H6_hamiltonian.npy") # reported in 0.99 A
16+
hamiltonian = construct_matrix_v3(h6h.tolist())
17+
1618

1719
vqeinstance = VQNHE(
1820
10,
19-
h6h.tolist(),
21+
hamiltonian,
2022
{"width": 16, "stddev": 0.001, "choose": "complex-rbm"}, # model parameter
2123
{"filled_qubit": [0, 1, 3, 4, 5, 6, 8, 9], "epochs": 2}, # circuit parameter
2224
shortcut=True, # enable shortcut for full Hamiltonian matrix evaluation

tensorcircuit/applications/vqes.py

+38-22
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,11 @@ def construct_matrix_v2(ham: List[List[float]], dtype: Any = tf.complex128) -> T
103103

104104
def construct_matrix_v3(ham: List[List[float]], dtype: Any = tf.complex128) -> Tensor:
105105
from ..quantum import PauliStringSum2COO
106-
from ..cons import backend
107106

108107
sparsem = PauliStringSum2COO([h[1:] for h in ham], [h[0] for h in ham]) # type: ignore
109-
densem = backend.to_dense(sparsem)
110-
return tf.cast(densem, dtype)
108+
return sparsem
109+
# densem = backend.to_dense(sparsem)
110+
# return tf.cast(densem, dtype)
111111

112112

113113
def vqe_energy(c: Circuit, h: List[List[float]], reuse: bool = True) -> Tensor:
@@ -130,15 +130,9 @@ def vqe_energy(c: Circuit, h: List[List[float]], reuse: bool = True) -> Tensor:
130130

131131

132132
def vqe_energy_shortcut(c: Circuit, h: Tensor) -> Tensor:
133-
w = c.wavefunction()
134-
e = (tf.math.conj(tf.reshape(w, [1, -1])) @ h @ tf.reshape(w, [-1, 1]))[0, 0]
135-
return e
133+
from ..templates.measurements import operator_expectation
136134

137-
138-
def vqe_energy_shortcut_sparse(c: Circuit, h: Tensor) -> Tensor:
139-
from ..templates.measurememts import sparse_expectation
140-
141-
return sparse_expectation(c, h)
135+
return operator_expectation(c, h)
142136

143137

144138
class Linear(tf.keras.layers.Layer): # type: ignore
@@ -232,24 +226,20 @@ def __init__(
232226
circuit_params = {"epochs": 2, "stddev": 0.1}
233227
self.epochs = circuit_params.get("epochs", 2)
234228
self.circuit_stddev = circuit_params.get("stddev", 0.1)
229+
self.channel = circuit_params.get("channel", 2)
235230

236231
self.circuit_variable = tf.Variable(
237232
tf.random.normal(
238233
mean=0.0,
239234
stddev=self.circuit_stddev,
240-
shape=[2 * self.epochs, self.n],
235+
shape=[self.epochs, self.n, self.channel],
241236
dtype=tf.float64,
242237
)
243238
)
244239
self.circuit = self.create_circuit(**circuit_params)
245240
self.base = tf.constant(list(product(*[[0, 1] for _ in range(n)])))
246241
self.hamiltonian = hamiltonian
247242
self.shortcut = shortcut
248-
if shortcut:
249-
hmatrix = construct_matrix_v3(self.hamiltonian)
250-
self.hop = hmatrix
251-
# self.hop = tf.constant(hmatrix, dtype=tf.complex128)
252-
# self.hop = G.any(hmatrix.copy().reshape([2 for _ in range(2 * n)]))
253243

254244
def assign(
255245
self, c: Optional[List[Tensor]] = None, q: Optional[Tensor] = None
@@ -369,6 +359,8 @@ def create_circuit(
369359
) -> Callable[[Tensor], Tensor]:
370360
if choose == "hea":
371361
return self.create_hea_circuit(**kws)
362+
if choose == "hea2":
363+
return self.create_hea2_circuit(**kws)
372364
if choose == "hn":
373365
return self.create_hn_circuit(**kws)
374366
raise ValueError("no such choose option: %s" % choose)
@@ -395,15 +387,39 @@ def circuit(a: Tensor) -> Tensor:
395387
c.X(i) # type: ignore
396388
for epoch in range(epochs):
397389
for i in range(self.n):
398-
c.rx(i, theta=tf.cast(a[2 * epoch, i], dtype=dtype)) # type: ignore
390+
c.rx(i, theta=a[epoch, i, 0]) # type: ignore
399391
for i in range(self.n):
400-
c.rz(i, theta=tf.cast(a[2 * epoch + 1, i], dtype=dtype)) # type: ignore
392+
c.rz(i, theta=a[epoch, i, 1]) # type: ignore
401393
for i in range(self.n - 1):
402394
c.cnot(i, (i + 1)) # type: ignore
403395
return c
404396

405397
return circuit
406398

399+
def create_hea2_circuit(
400+
self, epochs: int = 2, filled_qubit: Optional[List[int]] = None, **kws: Any
401+
) -> Callable[[Tensor], Tensor]:
402+
if filled_qubit is None:
403+
filled_qubit = [0]
404+
405+
def circuit(a: Tensor) -> Tensor:
406+
c = Circuit(self.n)
407+
if filled_qubit:
408+
for i in filled_qubit:
409+
c.X(i) # type: ignore
410+
for epoch in range(epochs):
411+
for i in range(self.n):
412+
c.rx(i, theta=a[epoch, i, 0]) # type: ignore
413+
for i in range(self.n):
414+
c.rz(i, theta=a[epoch, i, 1]) # type: ignore
415+
for i in range(self.n):
416+
c.rx(i, theta=a[epoch, i, 2]) # type: ignore
417+
for i in range(self.n - 1):
418+
c.exp1(i, (i + 1), theta=a[epoch, i, 3], unitary=G._zz_matrix) # type: ignore
419+
return c
420+
421+
return circuit
422+
407423
@tf.function # type: ignore
408424
def evaluation(self, cv: Tensor) -> Tuple[Tensor, Tensor, Tensor]:
409425
"""
@@ -426,7 +442,7 @@ def evaluation(self, cv: Tensor) -> Tuple[Tensor, Tensor, Tensor]:
426442
if not self.shortcut:
427443
loss = tf.math.real(vqe_energy(c2, self.hamiltonian))
428444
else:
429-
loss = tf.math.real(vqe_energy_shortcut(c2, self.hop))
445+
loss = tf.math.real(vqe_energy_shortcut(c2, self.hamiltonian))
430446
grad = tape.gradient(loss, [cv, self.model.variables])
431447
for i, gr in enumerate(grad):
432448
if gr is None:
@@ -452,7 +468,7 @@ def plain_evaluation(self, cv: Tensor) -> Tensor:
452468
if not self.shortcut:
453469
loss = tf.math.real(vqe_energy(c, self.hamiltonian))
454470
else:
455-
loss = tf.math.real(vqe_energy_shortcut(c, self.hop))
471+
loss = tf.math.real(vqe_energy_shortcut(c, self.hamiltonian))
456472
grad = tape.gradient(loss, cv)
457473
return loss, grad
458474

@@ -558,7 +574,7 @@ def multi_training(
558574
tf.random.normal(
559575
mean=0.0,
560576
stddev=self.circuit_stddev,
561-
shape=[2 * self.epochs, self.n],
577+
shape=[self.epochs, self.n, self.channel],
562578
dtype=tf.float64,
563579
)
564580
)

0 commit comments

Comments
 (0)