Skip to content

Commit 0b04952

Browse files
add templates submodule; add extra large vqe example
1 parent 25cbaed commit 0b04952

File tree

11 files changed

+232
-4
lines changed

11 files changed

+232
-4
lines changed

check_all.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ mypy tensorcircuit
77
echo "pylint check"
88
pylint tensorcircuit tests
99
echo "pytest check"
10-
pytest --cov=tensorcircuit -vv -W ignore::DeprecationWarning
10+
pytest -n 4 --cov=tensorcircuit -vv -W ignore::DeprecationWarning
1111
echo "sphinx check"
1212
cd docs && make html
13-
echo "all checks passed, congratulates! 💐"
13+
echo "all checks passed, congratulates! 💐"

examples/vqe_extra.py

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
"""
2+
demonstration of TFIM VQE on V100 with lager qubit number counts
3+
"""
4+
5+
import logging
6+
import sys
7+
import numpy as np
8+
9+
logger = logging.getLogger("tensorcircuit")
10+
logger.setLevel(logging.INFO)
11+
ch = logging.StreamHandler()
12+
ch.setLevel(logging.DEBUG)
13+
logger.addHandler(ch)
14+
15+
sys.setrecursionlimit(10000)
16+
17+
import tensorflow as tf
18+
import tensorcircuit as tc
19+
from tensorcircuit import keras
20+
import cotengra as ctg
21+
22+
optr = ctg.ReusableHyperOptimizer(
23+
methods=["greedy", "kahypar"],
24+
parallel=True,
25+
minimize="flops",
26+
max_time=120,
27+
max_repeats=4096,
28+
progbar=True,
29+
)
30+
tc.set_contractor("custom", optimizer=optr, preprocessing=True)
31+
# tc.set_contractor("custom_stateful", optimizer=oem.RandomGreedy, max_time=60, max_repeats=128, minimize="size")
32+
tc.set_dtype("complex64")
33+
tc.set_backend("tensorflow")
34+
dtype = np.complex64
35+
36+
import time
37+
38+
nwires, nlayers = 50, 7
39+
40+
41+
def vqe_forward(param, structures):
42+
split_conf = {
43+
"max_singular_values": 2,
44+
"fixed_choice": 1,
45+
}
46+
structuresc = tc.backend.cast(structures, dtype="complex64")
47+
paramc = tc.backend.cast(param, dtype="complex64")
48+
c = tc.Circuit(nwires, split=split_conf)
49+
for i in range(nwires):
50+
c.H(i)
51+
for j in range(nlayers):
52+
for i in range(0, nwires - 1):
53+
c.exp1(
54+
i,
55+
(i + 1) % nwires,
56+
theta=paramc[2 * j, i],
57+
unitary=tc.gates._zz_matrix,
58+
)
59+
60+
for i in range(nwires):
61+
c.rx(i, theta=paramc[2 * j + 1, i])
62+
63+
obs = []
64+
for i in range(nwires):
65+
obs.append(
66+
[
67+
tc.gates.Gate(
68+
sum(
69+
[
70+
structuresc[i, k] * g.tensor
71+
for k, g in enumerate(tc.gates.pauli_gates)
72+
]
73+
)
74+
),
75+
(i,),
76+
]
77+
)
78+
loss = c.expectation(*obs, reuse=False)
79+
return tc.backend.real(loss)
80+
81+
82+
slist = []
83+
for i in range(nwires):
84+
t = np.zeros(nwires)
85+
t[i] = 1
86+
slist.append(t)
87+
for i in range(nwires):
88+
t = np.zeros(nwires)
89+
t[i] = 3
90+
t[(i + 1) % nwires] = 3
91+
slist.append(t)
92+
structures = np.array(slist, dtype=np.int32)
93+
structures = tc.backend.onehot(structures, num=4)
94+
structures = tc.backend.reshape(structures, [-1, nwires, 4])
95+
print(structures.shape)
96+
time0 = time.time()
97+
98+
tc_vag = tc.backend.jit(
99+
tc.backend.vectorized_value_and_grad(vqe_forward, argnums=0, vectorized_argnums=1)
100+
)
101+
param = tf.Variable(tf.random.normal(stddev=0.1, shape=[2 * nlayers, nwires]))
102+
103+
print(tc_vag(param, structures[:50]))
104+
105+
time1 = time.time()
106+
print("staging time: ", time1 - time0)
107+
108+
try:
109+
keras.save_func(tc_vag, "./funcs/%s_%s_10_tfim" % (nwires, nlayers))
110+
except ValueError as e:
111+
print(e) # keras.save_func now has issues to be resolved
112+
113+
114+
def train_step(param):
115+
vag_list = []
116+
for i in range(2):
117+
vag_list.append(tc_vag(param, structures[i * nwires : i * nwires + nwires]))
118+
loss = tc.backend.sum(vag_list[0][0] - vag_list[1][0])
119+
gr = vag_list[0][1] - vag_list[1][1]
120+
return loss, gr
121+
122+
123+
if __name__ == "__main__":
124+
opt = tf.keras.optimizers.Adam(0.02)
125+
for j in range(5000):
126+
loss, gr = train_step(param)
127+
opt.apply_gradients([(gr, param)])
128+
if j % 20 == 0:
129+
print("loss", loss.numpy())

tensorcircuit/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@
1212
from .densitymatrix import DMCircuit
1313
from .densitymatrix2 import DMCircuit2
1414
from .gates import num_to_tensor, array_to_tensor
15+
from . import templates

tensorcircuit/applications/utils.py

+17
Original file line numberDiff line numberDiff line change
@@ -386,3 +386,20 @@ def repr2array(inputs: str) -> Array:
386386
o = [float(c.strip()) for c in l.split(" ") if c.strip()]
387387
outputs.append(o)
388388
return np.array(outputs)
389+
390+
391+
def TFIM1Denergy(
392+
L: int, Jzz: float = 1.0, Jx: float = 1.0, Pauli: bool = True
393+
) -> float:
394+
# PBC
395+
# nice tutorial: https://arxiv.org/pdf/2009.09208.pdf
396+
# further investigation on 1 TFIM solution structure is required
397+
# will fail on AFM phase Jzz>Jx and Jzz>0 and odd sites (frustration in boundary)
398+
e = 0
399+
if Pauli:
400+
Jx *= 2
401+
Jzz *= 4
402+
for i in range(L):
403+
q = np.pi * (2 * i - (1 + (-1) ** L) / 2) / L
404+
e -= np.abs(Jx) / 2 * np.sqrt(1 + Jzz ** 2 / 4 / Jx ** 2 - Jzz / Jx * np.cos(q))
405+
return e

tensorcircuit/backends/jax_backend.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def _svd_jax(
4545
max_truncation_error: Optional[float] = None,
4646
relative: Optional[bool] = False,
4747
) -> Tuple[Tensor, Tensor, Tensor, Tensor]:
48-
from .ops import adaware_svd
48+
from .ops import adaware_svd_jit as adaware_svd
4949

5050
left_dims = tensor.shape[:pivot_axis]
5151
right_dims = tensor.shape[pivot_axis:]

tensorcircuit/backends/ops.py

+2
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,5 @@ def jaxsvd_bwd(r: Sequence[Array], tangents: Sequence[Array]) -> Tuple[Array]:
6767

6868

6969
adaware_svd.defvjp(jaxsvd_fwd, jaxsvd_bwd)
70+
71+
adaware_svd_jit = jax.jit(adaware_svd)

tensorcircuit/keras.py

+4
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ def save_func(f: Callable[..., Any], path: str) -> None:
141141
tf.saved_model.save(m, path)
142142

143143

144+
# TODO(@refraction-ray): sometimes, save_func complains about ``return tuple(tensor.shape.as_list())``
145+
# ``ValueError: as_list() is not defined on an unknown TensorShape.``
146+
147+
144148
def load_func(
145149
*path: str, fallback: Optional[Callable[..., Any]] = None
146150
) -> Callable[..., Any]:

tensorcircuit/simplify.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def _split_two_qubit_gate(
7878
if (s1 >= 4) and (s2 >= 4):
7979
# jax jit unspport split_node with trun_err anyway
8080
# tf function doesn't work either, though I believe it may work on tf side
81-
# TODO(@refraction-ray): tf.function version with trun_err set
81+
# CANNOT DONE(@refraction-ray): tf.function version with trun_err set
8282
return None
8383
if s1 <= s2: # equal is necessary for max values to pick on unswap one
8484
return n1, n2, False # no swap

tensorcircuit/templates/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import measurements
+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
"""
2+
shortcuts for measurement patterns on circuit
3+
"""
4+
5+
from typing import Any
6+
7+
from ..circuit import Circuit
8+
from ..cons import backend, dtypestr
9+
from .. import gates
10+
11+
Tensor = Any
12+
13+
14+
def any_measurements(c: Circuit, structures: Tensor, onehot: bool = False) -> Tensor:
15+
"""
16+
This measurements pattern is specifically suitable for vmap. Parameterize the Pauli string
17+
to be measured
18+
19+
:param c: [description]
20+
:type c: Circuit
21+
:param structures: parameter tensors determines what Pauli string to be measured,
22+
shape is [nwires, 4] if onehot is False.
23+
:type structures: Tensor
24+
:param onehot: [description], defaults to False
25+
:type onehot: bool, optional
26+
:return: [description]
27+
:rtype: Tensor
28+
"""
29+
if onehot is True:
30+
structuresc = backend.cast(structures, dtype="int32")
31+
structuresc = backend.onehot(structuresc, num=4)
32+
structuresc = backend.cast(structuresc, dtype=dtypestr)
33+
else:
34+
structuresc = structures
35+
nwires = c._nqubits
36+
obs = []
37+
for i in range(nwires):
38+
obs.append(
39+
[
40+
gates.Gate(
41+
sum(
42+
[
43+
structuresc[i, k] * g.tensor
44+
for k, g in enumerate(gates.pauli_gates)
45+
]
46+
)
47+
),
48+
(i,),
49+
]
50+
)
51+
loss = c.expectation(*obs, reuse=False) # type: ignore
52+
# TODO(@refraction-ray): is reuse=True in this setup has user case?
53+
return backend.real(loss)

tests/test_templates.py

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import sys
2+
import os
3+
import numpy as np
4+
5+
thisfile = os.path.abspath(__file__)
6+
modulepath = os.path.dirname(os.path.dirname(thisfile))
7+
8+
sys.path.insert(0, modulepath)
9+
import tensorcircuit as tc
10+
11+
12+
def test_any_measurement():
13+
c = tc.Circuit(2)
14+
c.H(0)
15+
c.H(1)
16+
mea = np.array([1, 1])
17+
r = tc.templates.measurements.any_measurements(c, mea, onehot=True)
18+
np.testing.assert_allclose(r, 1.0, atol=1e-5)
19+
mea2 = np.array([3, 0])
20+
r2 = tc.templates.measurements.any_measurements(c, mea2, onehot=True)
21+
np.testing.assert_allclose(r2, 0.0, atol=1e-5)

0 commit comments

Comments
 (0)