Skip to content

Commit 64ca4d7

Browse files
authored
Merge pull request #20 from quantum-programming/feature/add-config
Add config
2 parents 78b5611 + b59ee60 commit 64ca4d7

6 files changed

Lines changed: 118 additions & 152 deletions

File tree

pygridsynth/cli.py

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import argparse
22

3+
from .config import GridsynthConfig
34
from .gridsynth import gridsynth_gates
45

56
helps = {
@@ -22,28 +23,41 @@ def main():
2223

2324
parser.add_argument("theta", type=str)
2425
parser.add_argument("epsilon", type=str)
25-
parser.add_argument("--dps", type=int, default=None)
26-
parser.add_argument("--dtimeout", "-dt", type=float, default=None, help=helps["dt"])
27-
parser.add_argument("--ftimeout", "-ft", type=float, default=None, help=helps["ft"])
28-
parser.add_argument("--dloop", "-dl", type=int, default=10, help=helps["dl"])
29-
parser.add_argument("--floop", "-fl", type=int, default=10, help=helps["fl"])
30-
parser.add_argument("--seed", type=int, default=0, help=helps["seed"])
26+
parser.add_argument("--dps", type=int)
27+
parser.add_argument("--dtimeout", "-dt", type=float, help=helps["dt"])
28+
parser.add_argument("--ftimeout", "-ft", type=float, help=helps["ft"])
29+
parser.add_argument("--dloop", "-dl", type=int, help=helps["dl"])
30+
parser.add_argument("--floop", "-fl", type=int, help=helps["fl"])
31+
parser.add_argument("--seed", type=int, help=helps["seed"])
3132
parser.add_argument("--verbose", "-v", action="store_true")
3233
parser.add_argument("--time", "-t", action="store_true")
3334
parser.add_argument("--showgraph", "-g", action="store_true")
35+
parser.add_argument("--upto_phase", "-ph", action="store_true")
3436
args = parser.parse_args()
3537

36-
gates = gridsynth_gates(
37-
theta=args.theta,
38-
epsilon=args.epsilon,
39-
dps=args.dps,
40-
dtimeout=args.dtimeout,
41-
ftimeout=args.ftimeout,
42-
dloop=args.dloop,
43-
floop=args.floop,
44-
seed=args.seed,
45-
verbose=args.verbose,
46-
measure_time=args.time,
47-
show_graph=args.showgraph,
48-
)
38+
cfg_args = dict()
39+
if args.dps is not None:
40+
cfg_args["dps"] = args.dps
41+
if args.dtimeout is not None:
42+
cfg_args["dtimeout"] = args.dtimeout
43+
if args.ftimeout is not None:
44+
cfg_args["ftimeout"] = args.ftimeout
45+
if args.dloop is not None:
46+
cfg_args["dloop"] = args.dloop
47+
if args.floop is not None:
48+
cfg_args["floop"] = args
49+
if args.seed is not None:
50+
cfg_args["seed"] = args.seed
51+
if args.verbose:
52+
cfg_args["verbose"] = args.verbose
53+
if args.time:
54+
cfg_args["measure_time"] = args.time
55+
if args.showgraph:
56+
cfg_args["show_graph"] = args.showgraph
57+
if args.upto_phase:
58+
cfg_args["upto_phase"] = args.upto_phase
59+
60+
cfg = GridsynthConfig(**cfg_args)
61+
62+
gates = gridsynth_gates(theta=args.theta, epsilon=args.epsilon, cfg=cfg)
4963
return gates

pygridsynth/config.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from dataclasses import dataclass, field
2+
from typing import Optional
3+
4+
from .loop_controller import LoopController
5+
6+
7+
@dataclass
8+
class GridsynthConfig:
9+
dps: Optional[int] = None
10+
seed: int = 0
11+
dloop: int = 10
12+
floop: int = 10
13+
dtimeout: Optional[float] = None
14+
ftimeout: Optional[float] = None
15+
verbose: bool = False
16+
measure_time: bool = False
17+
show_graph: bool = False
18+
upto_phase: bool = False
19+
20+
loop_controller: LoopController = field(init=False)
21+
22+
def __post_init__(self):
23+
self.loop_controller = LoopController(
24+
dloop=self.dloop,
25+
floop=self.floop,
26+
dtimeout=self.dtimeout,
27+
ftimeout=self.ftimeout,
28+
)

pygridsynth/diophantine.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
import random
44
import warnings
55

6-
from pygridsynth.loop_controller import LoopController
7-
6+
from .loop_controller import LoopController
87
from .ring import DOmega, ZOmega, ZRootTwo
98

109
NO_SOLUTION = "no solution"
@@ -454,7 +453,8 @@ def _diophantine(xi, loop_controller: LoopController):
454453
return v * t
455454

456455

457-
def diophantine_dyadic(xi, loop_controller=None):
456+
def diophantine_dyadic(xi, seed=0, loop_controller=None):
457+
set_random_seed(seed)
458458
if loop_controller is None:
459459
loop_controller = LoopController()
460460

pygridsynth/gridsynth.py

Lines changed: 51 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33

44
import mpmath
55

6-
from .diophantine import NO_SOLUTION, diophantine_dyadic, set_random_seed
6+
from .config import GridsynthConfig
7+
from .diophantine import NO_SOLUTION, diophantine_dyadic
78
from .loop_controller import LoopController
89
from .mymath import solve_quadratic, sqrt
910
from .quantum_gate import Rz
@@ -115,15 +116,18 @@ def get_synthesized_unitary(gates):
115116
return DOmegaUnitary.from_gates(gates).to_complex_matrix
116117

117118

118-
def gridsynth(
119-
theta,
120-
epsilon,
121-
dps=None,
122-
loop_controller=None,
123-
verbose=False,
124-
measure_time=False,
125-
show_graph=False,
126-
):
119+
def gridsynth(theta, epsilon, cfg=None, **kwargs):
120+
if cfg is None:
121+
cfg = GridsynthConfig(**kwargs)
122+
elif kwargs:
123+
warnings.warn(
124+
"When 'cfg' is provided, 'kwargs' are ignored.",
125+
stacklevel=2,
126+
)
127+
128+
if cfg.dps is None:
129+
cfg.dps = _dps_for_epsilon(epsilon)
130+
127131
if isinstance(theta, float):
128132
warnings.warn(
129133
(
@@ -148,50 +152,48 @@ def gridsynth(
148152
stacklevel=2,
149153
)
150154

151-
if dps is None:
152-
dps = _dps_for_epsilon(epsilon)
153-
with mpmath.workdps(dps):
155+
with mpmath.workdps(cfg.dps):
154156
theta = mpmath.mpmathify(theta)
155157
epsilon = mpmath.mpmathify(epsilon)
156-
if loop_controller is None:
157-
loop_controller = LoopController()
158158

159159
epsilon_region = EpsilonRegion(theta, epsilon)
160160
unit_disk = UnitDisk()
161161
k = 0
162162

163-
if measure_time:
163+
if cfg.measure_time:
164164
start = time.time()
165165
transformed = to_upright_set_pair(
166-
epsilon_region, unit_disk, verbose=verbose, show_graph=show_graph
166+
epsilon_region, unit_disk, verbose=cfg.verbose, show_graph=cfg.show_graph
167167
)
168-
if measure_time:
168+
if cfg.measure_time:
169169
print(f"to_upright_set_pair: {time.time() - start} s")
170-
if verbose:
170+
if cfg.verbose:
171171
print("------------------")
172172

173173
time_of_solve_TDGP = 0
174174
time_of_diophantine_dyadic = 0
175175
while True:
176-
if measure_time:
176+
if cfg.measure_time:
177177
start = time.time()
178178
sol = solve_TDGP(
179179
epsilon_region,
180180
unit_disk,
181181
*transformed,
182182
k,
183-
verbose=verbose,
184-
show_graph=show_graph,
183+
verbose=cfg.verbose,
184+
show_graph=cfg.show_graph,
185185
)
186-
if measure_time:
186+
if cfg.measure_time:
187187
time_of_solve_TDGP += time.time() - start
188188
start = time.time()
189189

190190
for z in sol:
191191
if (z * z.conj).residue == 0:
192192
continue
193193
xi = 1 - DRootTwo.fromDOmega(z.conj * z)
194-
w = diophantine_dyadic(xi, loop_controller=loop_controller)
194+
w = diophantine_dyadic(
195+
xi, seed=cfg.seed, loop_controller=cfg.loop_controller
196+
)
195197
if w != NO_SOLUTION:
196198
z = z.reduce_denomexp()
197199
w = w.reduce_denomexp()
@@ -203,78 +205,43 @@ def gridsynth(
203205
u_approx = DOmegaUnitary(z, w, 0)
204206
else:
205207
u_approx = DOmegaUnitary(z, w.mul_by_omega(), 0)
206-
if measure_time:
208+
if cfg.measure_time:
207209
time_of_diophantine_dyadic += time.time() - start
208210
print(f"time of solve_TDGP: {time_of_solve_TDGP * 1000} ms")
209211
print(
210212
"time of diophantine_dyadic: "
211213
f"{time_of_diophantine_dyadic * 1000} ms"
212214
)
213-
if verbose:
215+
if cfg.verbose:
214216
print(f"{z=}, {w=}")
215217
print("------------------")
216218
return u_approx
217-
if measure_time:
219+
if cfg.measure_time:
218220
time_of_diophantine_dyadic += time.time() - start
219221
k += 1
220222

221223

222-
def gridsynth_circuit(
223-
theta,
224-
epsilon,
225-
wires=[0],
226-
decompose_phase_gate=True,
227-
dps=None,
228-
loop_controller=None,
229-
verbose=False,
230-
measure_time=False,
231-
show_graph=False,
232-
):
233-
if isinstance(theta, float):
224+
def gridsynth_circuit(theta, epsilon, wires=[0], cfg=None, **kwargs):
225+
if cfg is None:
226+
cfg = GridsynthConfig(**kwargs)
227+
elif kwargs:
234228
warnings.warn(
235-
(
236-
f"pygridsynth is synthesizing the angle {theta}. "
237-
"Please verify that this is the intended value. "
238-
"Using float may introduce precision errors; "
239-
"consider using mpmath.mpf for exact precision."
240-
),
241-
UserWarning,
229+
"When 'cfg' is provided, 'kwargs' are ignored.",
242230
stacklevel=2,
243231
)
244232

245-
if isinstance(epsilon, float):
246-
warnings.warn(
247-
(
248-
f"pygridsynth is using epsilon={epsilon} as the tolerance. "
249-
"Please verify that this is the intended value. "
250-
"Using float may introduce precision errors; "
251-
"consider using mpmath.mpf for exact precision."
252-
),
253-
UserWarning,
254-
stacklevel=2,
255-
)
233+
if cfg.dps is None:
234+
cfg.dps = _dps_for_epsilon(epsilon)
256235

257-
if dps is None:
258-
dps = _dps_for_epsilon(epsilon)
259-
with mpmath.workdps(dps):
260-
theta = mpmath.mpmathify(theta)
261-
epsilon = mpmath.mpmathify(epsilon)
262-
start_total = time.time() if measure_time else 0.0
263-
u_approx = gridsynth(
264-
theta=theta,
265-
epsilon=epsilon,
266-
dps=dps,
267-
loop_controller=loop_controller,
268-
verbose=verbose,
269-
measure_time=measure_time,
270-
show_graph=show_graph,
271-
)
236+
with mpmath.workdps(cfg.dps):
237+
start_total = time.time() if cfg.measure_time else 0.0
238+
u_approx = gridsynth(theta=theta, epsilon=epsilon, cfg=cfg)
272239

273-
start = time.time() if measure_time else 0.0
240+
start = time.time() if cfg.measure_time else 0.0
274241
circuit = decompose_domega_unitary(
275-
u_approx, wires=wires, decompose_phase_gate=decompose_phase_gate
242+
u_approx, wires=wires, upto_phase=cfg.upto_phase
276243
)
277-
if measure_time:
244+
if cfg.measure_time:
278245
print(
279246
f"time of decompose_domega_unitary: {(time.time() - start) * 1000} ms"
280247
)
@@ -283,65 +250,24 @@ def gridsynth_circuit(
283250
return circuit
284251

285252

286-
def gridsynth_gates(
287-
theta,
288-
epsilon,
289-
dps=None,
290-
dtimeout=None,
291-
ftimeout=None,
292-
dloop=10,
293-
floop=10,
294-
seed=0,
295-
verbose=False,
296-
measure_time=False,
297-
show_graph=False,
298-
decompose_phase_gate=True,
299-
):
300-
if isinstance(theta, float):
301-
warnings.warn(
302-
(
303-
f"pygridsynth is synthesizing the angle {theta}. "
304-
"Please verify that this is the intended value. "
305-
"Using float may introduce precision errors; "
306-
"consider using mpmath.mpf for exact precision."
307-
),
308-
UserWarning,
309-
stacklevel=2,
310-
)
311-
312-
if isinstance(epsilon, float):
253+
def gridsynth_gates(theta, epsilon, cfg=None, **kwargs):
254+
if cfg is None:
255+
cfg = GridsynthConfig(**kwargs)
256+
elif kwargs:
313257
warnings.warn(
314-
(
315-
f"pygridsynth is using epsilon={epsilon} as the tolerance. "
316-
"Please verify that this is the intended value. "
317-
"Using float may introduce precision errors; "
318-
"consider using mpmath.mpf for exact precision."
319-
),
320-
UserWarning,
258+
"When 'cfg' is provided, 'kwargs' are ignored.",
321259
stacklevel=2,
322260
)
323261

324-
set_random_seed(seed)
325-
326-
loop_controller = LoopController(
327-
dloop=dloop, floop=floop, dtimeout=dtimeout, ftimeout=ftimeout
328-
)
262+
if cfg.dps is None:
263+
cfg.dps = _dps_for_epsilon(epsilon)
329264

330-
if dps is None:
331-
dps = _dps_for_epsilon(epsilon)
332-
with mpmath.workdps(dps):
333-
theta = mpmath.mpmathify(theta)
334-
epsilon = mpmath.mpmathify(epsilon)
265+
with mpmath.workdps(cfg.dps):
335266
circuit = gridsynth_circuit(
336267
theta=theta,
337268
epsilon=epsilon,
338269
wires=[0],
339-
decompose_phase_gate=decompose_phase_gate,
340-
dps=dps,
341-
loop_controller=loop_controller,
342-
verbose=verbose,
343-
measure_time=measure_time,
344-
show_graph=show_graph,
270+
cfg=cfg,
345271
)
346272
return circuit.to_simple_str()
347273

0 commit comments

Comments
 (0)