QuLab 2.3.4__cp310-cp310-win_amd64.whl → 2.3.5__cp310-cp310-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {QuLab-2.3.4.dist-info → QuLab-2.3.5.dist-info}/METADATA +1 -1
- {QuLab-2.3.4.dist-info → QuLab-2.3.5.dist-info}/RECORD +13 -13
- {QuLab-2.3.4.dist-info → QuLab-2.3.5.dist-info}/WHEEL +1 -1
- qulab/fun.cp310-win_amd64.pyd +0 -0
- qulab/scan/optimize.py +1 -1
- qulab/scan/scan.py +199 -245
- qulab/scan/server.py +6 -5
- qulab/scan/space.py +18 -3
- qulab/scan/utils.py +58 -0
- qulab/version.py +1 -1
- {QuLab-2.3.4.dist-info → QuLab-2.3.5.dist-info}/LICENSE +0 -0
- {QuLab-2.3.4.dist-info → QuLab-2.3.5.dist-info}/entry_points.txt +0 -0
- {QuLab-2.3.4.dist-info → QuLab-2.3.5.dist-info}/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
qulab/__init__.py,sha256=vkFybY8YSsQilYdThPRD83-btPAR41sy_WCXiM-6mME,141
|
|
2
2
|
qulab/__main__.py,sha256=V7iokU7awstgjCeiF_hoOdFyrqJwC_4QetiLe7cWvOQ,454
|
|
3
|
-
qulab/fun.cp310-win_amd64.pyd,sha256=
|
|
4
|
-
qulab/version.py,sha256=
|
|
3
|
+
qulab/fun.cp310-win_amd64.pyd,sha256=kQuRgdvK9lRtsFCBDRU6U9Ujcd1KTbrsozcQCkZoYL4,31744
|
|
4
|
+
qulab/version.py,sha256=ctNy09QkNipfMu2fxyFBsAXtRoAHMP1bEKHsc3zRmkk,21
|
|
5
5
|
qulab/monitor/__init__.py,sha256=xEVDkJF8issrsDeLqQmDsvtRmrf-UiViFcGTWuzdlFU,43
|
|
6
6
|
qulab/monitor/__main__.py,sha256=k2H1H5Zf9LLXTDLISJkbikLH-z0f1e5i5i6wXXYPOrE,105
|
|
7
7
|
qulab/monitor/config.py,sha256=y_5StMkdrbZO1ziyKBrvIkB7Jclp9RCPK1QbsOhCxnY,785
|
|
@@ -16,13 +16,13 @@ qulab/scan/__init__.py,sha256=RR_0NQcr8Mi3vpWdypydbijQ1rXA0D3DEidQ7xjNslM,133
|
|
|
16
16
|
qulab/scan/curd.py,sha256=yaTglGiS6mlk0GqDHi_w8T02XGBMvDZtXSdML7zDywk,7117
|
|
17
17
|
qulab/scan/expression.py,sha256=l7TYBmcJIo0M5GJm1TtrkrMFj5mCmrfLOMCILKbOivU,20712
|
|
18
18
|
qulab/scan/models.py,sha256=ZvXkJEt5Yz3Sjx0JKzYka-q2Uo-w_iVzHgH8A6DbjF0,18236
|
|
19
|
-
qulab/scan/optimize.py,sha256=
|
|
19
|
+
qulab/scan/optimize.py,sha256=zOR4Wp96bLarTSiPJ-cTAfT-V_MU-YEgB-XqYsBhS30,2637
|
|
20
20
|
qulab/scan/query.py,sha256=RM8bG4Tcx_PaNk8tv9HdlTZ1dGuuSr3sZVkYVq2BtfQ,12183
|
|
21
21
|
qulab/scan/record.py,sha256=MVmxhIzwmOju7eWxJEWsqJZlVgrDeRXGMfNvXImj7Ms,21883
|
|
22
|
-
qulab/scan/scan.py,sha256=
|
|
23
|
-
qulab/scan/server.py,sha256=
|
|
24
|
-
qulab/scan/space.py,sha256=
|
|
25
|
-
qulab/scan/utils.py,sha256=
|
|
22
|
+
qulab/scan/scan.py,sha256=p7LZvmjDSnUHeszgILlEXFIspHVPLk9Rt2dVqFtNsaQ,40645
|
|
23
|
+
qulab/scan/server.py,sha256=iT9wMEUQ2Pz_5nioHA7nII1MBPpQi-rCFbEJnRdWkDg,20487
|
|
24
|
+
qulab/scan/space.py,sha256=t8caa_gKlnhaAIEksJyxINUTecOS7lMWAz1HDKlVcds,6909
|
|
25
|
+
qulab/scan/utils.py,sha256=YXFA19HEakHB5TaPOU9CjQ1Lc3GUJaSIGOtiWjAWsG4,6353
|
|
26
26
|
qulab/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
27
|
qulab/storage/__main__.py,sha256=6-EjN0waX1yfcMPJXqpIr9UlrIEsSCFApm5G-ZeaPMQ,1742
|
|
28
28
|
qulab/storage/base_dataset.py,sha256=28y3-OZrqJ52p5sbirEpUgjb7hqwLLpd38KU9DCkD24,12217
|
|
@@ -78,9 +78,9 @@ qulab/visualization/plot_layout.py,sha256=yAnMONOms7_szCdng-8wPpUMPis5UnbaNNzV4K
|
|
|
78
78
|
qulab/visualization/plot_seq.py,sha256=h9D0Yl_yO64IwlvBgzMu9EBKr9gg6y8QE55gu2PfTns,2783
|
|
79
79
|
qulab/visualization/qdat.py,sha256=HubXFu4nfcA7iUzghJGle1C86G6221hicLR0b-GqhKQ,5887
|
|
80
80
|
qulab/visualization/widgets.py,sha256=HcYwdhDtLreJiYaZuN3LfofjJmZcLwjMfP5aasebgDo,3266
|
|
81
|
-
QuLab-2.3.
|
|
82
|
-
QuLab-2.3.
|
|
83
|
-
QuLab-2.3.
|
|
84
|
-
QuLab-2.3.
|
|
85
|
-
QuLab-2.3.
|
|
86
|
-
QuLab-2.3.
|
|
81
|
+
QuLab-2.3.5.dist-info/LICENSE,sha256=b4NRQ-GFVpJMT7RuExW3NwhfbrYsX7AcdB7Gudok-fs,1086
|
|
82
|
+
QuLab-2.3.5.dist-info/METADATA,sha256=CUbsOaCfpAwZ7tf7MIywKpb0DuidIos4u6sMgE2PXKs,3735
|
|
83
|
+
QuLab-2.3.5.dist-info/WHEEL,sha256=tF77PxuEGG-2kyJBah3Kgju_42iEyT5AcvsT_0Dgcj0,101
|
|
84
|
+
QuLab-2.3.5.dist-info/entry_points.txt,sha256=ohBzutEnQimP_BZWiuXdSliu4QAYSHHcN0PZD8c7ZCY,46
|
|
85
|
+
QuLab-2.3.5.dist-info/top_level.txt,sha256=3T886LbAsbvjonu_TDdmgxKYUn939BVTRPxPl9r4cEg,6
|
|
86
|
+
QuLab-2.3.5.dist-info/RECORD,,
|
qulab/fun.cp310-win_amd64.pyd
CHANGED
|
Binary file
|
qulab/scan/optimize.py
CHANGED
qulab/scan/scan.py
CHANGED
|
@@ -6,9 +6,7 @@ import itertools
|
|
|
6
6
|
import lzma
|
|
7
7
|
import os
|
|
8
8
|
import pickle
|
|
9
|
-
import platform
|
|
10
9
|
import re
|
|
11
|
-
import subprocess
|
|
12
10
|
import sys
|
|
13
11
|
import uuid
|
|
14
12
|
from concurrent.futures import ProcessPoolExecutor
|
|
@@ -26,7 +24,8 @@ from .optimize import NgOptimizer
|
|
|
26
24
|
from .record import Record
|
|
27
25
|
from .server import default_record_port
|
|
28
26
|
from .space import Optimizer, OptimizeSpace, Space
|
|
29
|
-
from .utils import async_zip, call_function, dump_dict, dump_globals
|
|
27
|
+
from .utils import (async_zip, call_function, dump_dict, dump_globals,
|
|
28
|
+
get_installed_packages, get_system_info, yapf_reformat)
|
|
30
29
|
|
|
31
30
|
try:
|
|
32
31
|
from tqdm.notebook import tqdm
|
|
@@ -58,57 +57,34 @@ else:
|
|
|
58
57
|
default_executor = default_server
|
|
59
58
|
|
|
60
59
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
import isort
|
|
64
|
-
import yapf.yapflib.yapf_api
|
|
65
|
-
|
|
66
|
-
fname = f"f{uuid.uuid1().hex}"
|
|
67
|
-
|
|
68
|
-
def wrap(source):
|
|
69
|
-
lines = [f"async def {fname}():"]
|
|
70
|
-
for line in source.split('\n'):
|
|
71
|
-
lines.append(" " + line)
|
|
72
|
-
return '\n'.join(lines)
|
|
60
|
+
class Promise():
|
|
61
|
+
__slots__ = ['task', 'key', 'attr']
|
|
73
62
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
continue
|
|
79
|
-
lines.append(line[4:])
|
|
80
|
-
return '\n'.join(lines)
|
|
63
|
+
def __init__(self, task, key=None, attr=None):
|
|
64
|
+
self.task = task
|
|
65
|
+
self.key = key
|
|
66
|
+
self.attr = attr
|
|
81
67
|
|
|
82
|
-
|
|
83
|
-
reformated_text = unwrap(
|
|
84
|
-
yapf.yapflib.yapf_api.FormatCode(wrap(isort.code(cell_text)))[0])
|
|
85
|
-
return re.sub('^#%#', '%', reformated_text, flags=re.M)
|
|
86
|
-
except:
|
|
87
|
-
return cell_text
|
|
68
|
+
def __await__(self):
|
|
88
69
|
|
|
70
|
+
async def _getitem(task, key):
|
|
71
|
+
return (await task)[key]
|
|
89
72
|
|
|
90
|
-
def
|
|
91
|
-
|
|
92
|
-
stdout=subprocess.PIPE,
|
|
93
|
-
text=True)
|
|
73
|
+
async def _getattr(task, attr):
|
|
74
|
+
return getattr(await task, attr)
|
|
94
75
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
76
|
+
if self.key is not None:
|
|
77
|
+
return _getitem(self.task, self.key).__await__()
|
|
78
|
+
elif self.attr is not None:
|
|
79
|
+
return _getattr(self.task, self.attr).__await__()
|
|
80
|
+
else:
|
|
81
|
+
return self.task.__await__()
|
|
101
82
|
|
|
83
|
+
def __getitem__(self, key):
|
|
84
|
+
return Promise(self.task, key, None)
|
|
102
85
|
|
|
103
|
-
def
|
|
104
|
-
|
|
105
|
-
'OS': platform.uname()._asdict(),
|
|
106
|
-
'Python': sys.version,
|
|
107
|
-
'PythonExecutable': sys.executable,
|
|
108
|
-
'PythonPath': sys.path,
|
|
109
|
-
'packages': get_installed_packages()
|
|
110
|
-
}
|
|
111
|
-
return info
|
|
86
|
+
def __getattr__(self, attr):
|
|
87
|
+
return Promise(self.task, None, attr)
|
|
112
88
|
|
|
113
89
|
|
|
114
90
|
def current_notebook():
|
|
@@ -170,39 +146,185 @@ def _get_depends(func: Callable):
|
|
|
170
146
|
return args
|
|
171
147
|
|
|
172
148
|
|
|
173
|
-
|
|
174
|
-
|
|
149
|
+
def _run_function_in_process(buf):
|
|
150
|
+
func, args, kwds = dill.loads(buf)
|
|
151
|
+
return func(*args, **kwds)
|
|
175
152
|
|
|
176
|
-
def __init__(self, task, key=None, attr=None):
|
|
177
|
-
self.task = task
|
|
178
|
-
self.key = key
|
|
179
|
-
self.attr = attr
|
|
180
153
|
|
|
181
|
-
|
|
154
|
+
async def update_variables(variables: dict[str, Any], updates: dict[str, Any],
|
|
155
|
+
setters: dict[str, Callable]):
|
|
156
|
+
coros = []
|
|
157
|
+
for name, value in updates.items():
|
|
158
|
+
if name in setters:
|
|
159
|
+
coro = setters[name](value)
|
|
160
|
+
if inspect.isawaitable(coro):
|
|
161
|
+
coros.append(coro)
|
|
162
|
+
variables[name] = value
|
|
163
|
+
if coros:
|
|
164
|
+
await asyncio.gather(*coros)
|
|
182
165
|
|
|
183
|
-
async def _getitem(task, key):
|
|
184
|
-
return (await task)[key]
|
|
185
166
|
|
|
186
|
-
|
|
187
|
-
|
|
167
|
+
async def _iter_level(variables,
|
|
168
|
+
iters: list[tuple[str, Iterable | Expression | Callable
|
|
169
|
+
| OptimizeSpace]],
|
|
170
|
+
order: list[list[str]],
|
|
171
|
+
functions: dict[str, Callable | Expression],
|
|
172
|
+
optimizers: dict[str, Optimizer],
|
|
173
|
+
setters: dict[str, Callable] = {},
|
|
174
|
+
getters: dict[str, Callable] = {}):
|
|
175
|
+
iters_d = {}
|
|
176
|
+
env = Env()
|
|
177
|
+
env.variables = variables
|
|
178
|
+
opts = {}
|
|
188
179
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
180
|
+
for name, iter in iters:
|
|
181
|
+
if isinstance(iter, OptimizeSpace):
|
|
182
|
+
if iter.optimizer.name not in opts:
|
|
183
|
+
opts[iter.optimizer.name] = iter.optimizer.create()
|
|
184
|
+
elif isinstance(iter, Expression):
|
|
185
|
+
iters_d[name] = iter.eval(env)
|
|
186
|
+
elif isinstance(iter, Space):
|
|
187
|
+
iters_d[name] = iter.toarray()
|
|
188
|
+
elif callable(iter):
|
|
189
|
+
iters_d[name] = await call_function(iter, variables)
|
|
193
190
|
else:
|
|
194
|
-
|
|
191
|
+
iters_d[name] = iter
|
|
195
192
|
|
|
196
|
-
|
|
197
|
-
|
|
193
|
+
maxiter = 0xffffffff
|
|
194
|
+
for name, opt in opts.items():
|
|
195
|
+
opt_cfg = optimizers[name]
|
|
196
|
+
maxiter = min(maxiter, opt_cfg.maxiter)
|
|
198
197
|
|
|
199
|
-
|
|
200
|
-
|
|
198
|
+
async for args in async_zip(*iters_d.values(), range(maxiter)):
|
|
199
|
+
await update_variables(variables, dict(zip(iters_d.keys(), args[:-1])),
|
|
200
|
+
setters)
|
|
201
|
+
for name, opt in opts.items():
|
|
202
|
+
args = opt.ask()
|
|
203
|
+
opt_cfg = optimizers[name]
|
|
204
|
+
await update_variables(variables, {
|
|
205
|
+
n: v
|
|
206
|
+
for n, v in zip(opt_cfg.dimensions.keys(), args)
|
|
207
|
+
}, setters)
|
|
208
|
+
|
|
209
|
+
await update_variables(
|
|
210
|
+
variables, await call_many_functions(order, functions, variables),
|
|
211
|
+
setters)
|
|
201
212
|
|
|
213
|
+
yield variables
|
|
202
214
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
215
|
+
variables.update(await call_many_functions(order, getters, variables))
|
|
216
|
+
|
|
217
|
+
if opts:
|
|
218
|
+
for key in list(variables.keys()):
|
|
219
|
+
if key.startswith('*') or ',' in key:
|
|
220
|
+
await _unpack(key, variables)
|
|
221
|
+
|
|
222
|
+
for name, opt in opts.items():
|
|
223
|
+
opt_cfg = optimizers[name]
|
|
224
|
+
args = [variables[n] for n in opt_cfg.dimensions.keys()]
|
|
225
|
+
|
|
226
|
+
if name not in variables:
|
|
227
|
+
raise ValueError(f'{name} not in variables.')
|
|
228
|
+
fun = variables[name]
|
|
229
|
+
if inspect.isawaitable(fun):
|
|
230
|
+
fun = await fun
|
|
231
|
+
if opt_cfg.minimize:
|
|
232
|
+
opt.tell(args, fun)
|
|
233
|
+
else:
|
|
234
|
+
opt.tell(args, -fun)
|
|
235
|
+
|
|
236
|
+
if opts:
|
|
237
|
+
for name, opt in opts.items():
|
|
238
|
+
opt_cfg = optimizers[name]
|
|
239
|
+
result = opt.get_result()
|
|
240
|
+
await update_variables(
|
|
241
|
+
variables, {
|
|
242
|
+
name: value
|
|
243
|
+
for name, value in zip(opt_cfg.dimensions.keys(), result.x)
|
|
244
|
+
}, setters)
|
|
245
|
+
|
|
246
|
+
yield variables
|
|
247
|
+
|
|
248
|
+
variables.update(await call_many_functions(order, getters, variables))
|
|
249
|
+
|
|
250
|
+
for key in list(variables.keys()):
|
|
251
|
+
if key.startswith('*') or ',' in key:
|
|
252
|
+
await _unpack(key, variables)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
async def call_many_functions(order: list[list[str]],
|
|
256
|
+
functions: dict[str, Callable],
|
|
257
|
+
variables: dict[str, Any]) -> dict[str, Any]:
|
|
258
|
+
ret = {}
|
|
259
|
+
for group in order:
|
|
260
|
+
waited = []
|
|
261
|
+
coros = []
|
|
262
|
+
for name in group:
|
|
263
|
+
if name in functions:
|
|
264
|
+
waited.append(name)
|
|
265
|
+
coros.append(call_function(functions[name], variables | ret))
|
|
266
|
+
if coros:
|
|
267
|
+
results = await asyncio.gather(*coros)
|
|
268
|
+
ret.update(dict(zip(waited, results)))
|
|
269
|
+
return ret
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
async def _unpack(key, variables):
|
|
273
|
+
x = variables[key]
|
|
274
|
+
if inspect.isawaitable(x):
|
|
275
|
+
x = await x
|
|
276
|
+
if key.startswith('**'):
|
|
277
|
+
assert isinstance(
|
|
278
|
+
x, dict), f"Should promise a dict for `**` symbol. {key}"
|
|
279
|
+
if "{key}" in key:
|
|
280
|
+
for k, v in x.items():
|
|
281
|
+
variables[key[2:].format(key=k)] = v
|
|
282
|
+
else:
|
|
283
|
+
variables.update(x)
|
|
284
|
+
elif key.startswith('*'):
|
|
285
|
+
assert isinstance(
|
|
286
|
+
x, (list, tuple,
|
|
287
|
+
np.ndarray)), f"Should promise a list for `*` symbol. {key}"
|
|
288
|
+
for i, v in enumerate(x):
|
|
289
|
+
k = key[1:].format(i=i)
|
|
290
|
+
variables[k] = v
|
|
291
|
+
elif ',' in key:
|
|
292
|
+
keys1, keys2 = [], []
|
|
293
|
+
args = None
|
|
294
|
+
for k in key.split(','):
|
|
295
|
+
if k.startswith('*'):
|
|
296
|
+
if args is None:
|
|
297
|
+
args = k
|
|
298
|
+
else:
|
|
299
|
+
raise ValueError(f'Only one `*` symbol is allowed. {key}')
|
|
300
|
+
elif args is None:
|
|
301
|
+
keys1.append(k)
|
|
302
|
+
else:
|
|
303
|
+
keys2.append(k)
|
|
304
|
+
assert isinstance(
|
|
305
|
+
x,
|
|
306
|
+
(list, tuple,
|
|
307
|
+
np.ndarray)), f"Should promise a list for multiple symbols. {key}"
|
|
308
|
+
if args is None:
|
|
309
|
+
assert len(keys1) == len(
|
|
310
|
+
x), f"Length of keys and values should be equal. {key}"
|
|
311
|
+
for k, v in zip(keys1, x):
|
|
312
|
+
variables[k] = v
|
|
313
|
+
else:
|
|
314
|
+
assert len(keys1) + len(keys2) <= len(
|
|
315
|
+
x), f"Too many values for unpacking. {key}"
|
|
316
|
+
for k, v in zip(keys1, x[:len(keys1)]):
|
|
317
|
+
variables[k] = v
|
|
318
|
+
end = -len(keys2) if keys2 else None
|
|
319
|
+
for i, v in enumerate(x[len(keys1):end]):
|
|
320
|
+
k = args[1:].format(i=i)
|
|
321
|
+
variables[k] = v
|
|
322
|
+
if keys2:
|
|
323
|
+
for k, v in zip(keys2, x[end:]):
|
|
324
|
+
variables[k] = v
|
|
325
|
+
else:
|
|
326
|
+
return
|
|
327
|
+
del variables[key]
|
|
206
328
|
|
|
207
329
|
|
|
208
330
|
class Scan():
|
|
@@ -232,6 +354,7 @@ class Scan():
|
|
|
232
354
|
self.id = task_uuid()
|
|
233
355
|
self.record = None
|
|
234
356
|
self.config = {} if config is None else copy.deepcopy(config)
|
|
357
|
+
self._raw_config_copy = copy.deepcopy(self.config)
|
|
235
358
|
self.description = {
|
|
236
359
|
'app': app,
|
|
237
360
|
'tags': tags,
|
|
@@ -252,7 +375,7 @@ class Scan():
|
|
|
252
375
|
'filters': {},
|
|
253
376
|
'total': {},
|
|
254
377
|
'database': database,
|
|
255
|
-
'hiden': ['self', 'config', r'^__.*', r'.*__$'],
|
|
378
|
+
'hiden': ['self', 'config', r'^__.*', r'.*__$', r'^#.*'],
|
|
256
379
|
'entry': {
|
|
257
380
|
'system': get_system_info(),
|
|
258
381
|
'env': {},
|
|
@@ -386,7 +509,7 @@ class Scan():
|
|
|
386
509
|
|
|
387
510
|
if self.config:
|
|
388
511
|
self.description['config'] = await create_config(
|
|
389
|
-
self.
|
|
512
|
+
self._raw_config_copy, self.description['database'], self._sock)
|
|
390
513
|
if current_notebook() is None:
|
|
391
514
|
await create_notebook('untitle', self.description['database'],
|
|
392
515
|
self._sock)
|
|
@@ -464,9 +587,9 @@ class Scan():
|
|
|
464
587
|
if depends:
|
|
465
588
|
self.add_depends(name, depends)
|
|
466
589
|
s = ','.join(depends)
|
|
467
|
-
self.description['functions'][f'
|
|
590
|
+
self.description['functions'][f'#{name}'] = value
|
|
468
591
|
self.description['functions'][name] = eval(
|
|
469
|
-
f"lambda self, {s}: self.description['functions']['
|
|
592
|
+
f"lambda self, {s}: self.description['functions']['#{name}']({s})"
|
|
470
593
|
)
|
|
471
594
|
else:
|
|
472
595
|
self.add_depends(name, _get_depends(value))
|
|
@@ -646,7 +769,7 @@ class Scan():
|
|
|
646
769
|
await self._run()
|
|
647
770
|
else:
|
|
648
771
|
if self.config:
|
|
649
|
-
self.description['config'] =
|
|
772
|
+
self.description['config'] = self._raw_config_copy
|
|
650
773
|
async with self._send_msg_and_update_bar() as background_tasks:
|
|
651
774
|
self._background_tasks = background_tasks
|
|
652
775
|
await self._run()
|
|
@@ -1040,173 +1163,4 @@ def assymbly(description):
|
|
|
1040
1163
|
_make_axis(description)
|
|
1041
1164
|
|
|
1042
1165
|
return description
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
async def update_variables(variables: dict[str, Any], updates: dict[str, Any],
|
|
1046
|
-
setters: dict[str, Callable]):
|
|
1047
|
-
coros = []
|
|
1048
|
-
for name, value in updates.items():
|
|
1049
|
-
if name in setters:
|
|
1050
|
-
coro = setters[name](value)
|
|
1051
|
-
if inspect.isawaitable(coro):
|
|
1052
|
-
coros.append(coro)
|
|
1053
|
-
variables[name] = value
|
|
1054
|
-
if coros:
|
|
1055
|
-
await asyncio.gather(*coros)
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
async def _iter_level(variables,
|
|
1059
|
-
iters: list[tuple[str, Iterable | Expression | Callable
|
|
1060
|
-
| OptimizeSpace]],
|
|
1061
|
-
order: list[list[str]],
|
|
1062
|
-
functions: dict[str, Callable | Expression],
|
|
1063
|
-
optimizers: dict[str, Optimizer],
|
|
1064
|
-
setters: dict[str, Callable] = {},
|
|
1065
|
-
getters: dict[str, Callable] = {}):
|
|
1066
|
-
iters_d = {}
|
|
1067
|
-
env = Env()
|
|
1068
|
-
env.variables = variables
|
|
1069
|
-
opts = {}
|
|
1070
|
-
|
|
1071
|
-
for name, iter in iters:
|
|
1072
|
-
if isinstance(iter, OptimizeSpace):
|
|
1073
|
-
if iter.optimizer.name not in opts:
|
|
1074
|
-
opts[iter.optimizer.name] = iter.optimizer.create()
|
|
1075
|
-
elif isinstance(iter, Expression):
|
|
1076
|
-
iters_d[name] = iter.eval(env)
|
|
1077
|
-
elif isinstance(iter, Space):
|
|
1078
|
-
iters_d[name] = iter.toarray()
|
|
1079
|
-
elif callable(iter):
|
|
1080
|
-
iters_d[name] = await call_function(iter, variables)
|
|
1081
|
-
else:
|
|
1082
|
-
iters_d[name] = iter
|
|
1083
|
-
|
|
1084
|
-
maxiter = 0xffffffff
|
|
1085
|
-
for name, opt in opts.items():
|
|
1086
|
-
opt_cfg = optimizers[name]
|
|
1087
|
-
maxiter = min(maxiter, opt_cfg.maxiter)
|
|
1088
|
-
|
|
1089
|
-
async for args in async_zip(*iters_d.values(), range(maxiter)):
|
|
1090
|
-
await update_variables(variables, dict(zip(iters_d.keys(), args[:-1])),
|
|
1091
|
-
setters)
|
|
1092
|
-
for name, opt in opts.items():
|
|
1093
|
-
args = opt.ask()
|
|
1094
|
-
opt_cfg = optimizers[name]
|
|
1095
|
-
await update_variables(variables, {
|
|
1096
|
-
n: v
|
|
1097
|
-
for n, v in zip(opt_cfg.dimensions.keys(), args)
|
|
1098
|
-
}, setters)
|
|
1099
|
-
|
|
1100
|
-
await update_variables(
|
|
1101
|
-
variables, await call_many_functions(order, functions, variables),
|
|
1102
|
-
setters)
|
|
1103
|
-
|
|
1104
|
-
yield variables
|
|
1105
|
-
|
|
1106
|
-
variables.update(await call_many_functions(order, getters, variables))
|
|
1107
|
-
|
|
1108
|
-
if opts:
|
|
1109
|
-
for key in list(variables.keys()):
|
|
1110
|
-
if key.startswith('*') or ',' in key:
|
|
1111
|
-
await _unpack(key, variables)
|
|
1112
|
-
|
|
1113
|
-
for name, opt in opts.items():
|
|
1114
|
-
opt_cfg = optimizers[name]
|
|
1115
|
-
args = [variables[n] for n in opt_cfg.dimensions.keys()]
|
|
1116
|
-
|
|
1117
|
-
if name not in variables:
|
|
1118
|
-
raise ValueError(f'{name} not in variables.')
|
|
1119
|
-
fun = variables[name]
|
|
1120
|
-
if inspect.isawaitable(fun):
|
|
1121
|
-
fun = await fun
|
|
1122
|
-
if opt_cfg.minimize:
|
|
1123
|
-
opt.tell(args, fun)
|
|
1124
|
-
else:
|
|
1125
|
-
opt.tell(args, -fun)
|
|
1126
|
-
|
|
1127
|
-
for name, opt in opts.items():
|
|
1128
|
-
opt_cfg = optimizers[name]
|
|
1129
|
-
result = opt.get_result()
|
|
1130
|
-
await update_variables(
|
|
1131
|
-
variables, {
|
|
1132
|
-
name: value
|
|
1133
|
-
for name, value in zip(opt_cfg.dimensions.keys(), result.x)
|
|
1134
|
-
}, setters)
|
|
1135
|
-
variables[name] = result.fun
|
|
1136
|
-
if opts:
|
|
1137
|
-
yield variables
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
async def call_many_functions(order: list[list[str]],
|
|
1141
|
-
functions: dict[str, Callable],
|
|
1142
|
-
variables: dict[str, Any]) -> dict[str, Any]:
|
|
1143
|
-
ret = {}
|
|
1144
|
-
for group in order:
|
|
1145
|
-
waited = []
|
|
1146
|
-
coros = []
|
|
1147
|
-
for name in group:
|
|
1148
|
-
if name in functions:
|
|
1149
|
-
waited.append(name)
|
|
1150
|
-
coros.append(call_function(functions[name], variables | ret))
|
|
1151
|
-
if coros:
|
|
1152
|
-
results = await asyncio.gather(*coros)
|
|
1153
|
-
ret.update(dict(zip(waited, results)))
|
|
1154
|
-
return ret
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
async def _unpack(key, variables):
|
|
1158
|
-
x = variables[key]
|
|
1159
|
-
if inspect.isawaitable(x):
|
|
1160
|
-
x = await x
|
|
1161
|
-
if key.startswith('**'):
|
|
1162
|
-
assert isinstance(
|
|
1163
|
-
x, dict), f"Should promise a dict for `**` symbol. {key}"
|
|
1164
|
-
if "{key}" in key:
|
|
1165
|
-
for k, v in x.items():
|
|
1166
|
-
variables[key[2:].format(key=k)] = v
|
|
1167
|
-
else:
|
|
1168
|
-
variables.update(x)
|
|
1169
|
-
elif key.startswith('*'):
|
|
1170
|
-
assert isinstance(
|
|
1171
|
-
x, (list, tuple,
|
|
1172
|
-
np.ndarray)), f"Should promise a list for `*` symbol. {key}"
|
|
1173
|
-
for i, v in enumerate(x):
|
|
1174
|
-
k = key[1:].format(i=i)
|
|
1175
|
-
variables[k] = v
|
|
1176
|
-
elif ',' in key:
|
|
1177
|
-
keys1, keys2 = [], []
|
|
1178
|
-
args = None
|
|
1179
|
-
for k in key.split(','):
|
|
1180
|
-
if k.startswith('*'):
|
|
1181
|
-
if args is None:
|
|
1182
|
-
args = k
|
|
1183
|
-
else:
|
|
1184
|
-
raise ValueError(f'Only one `*` symbol is allowed. {key}')
|
|
1185
|
-
elif args is None:
|
|
1186
|
-
keys1.append(k)
|
|
1187
|
-
else:
|
|
1188
|
-
keys2.append(k)
|
|
1189
|
-
assert isinstance(
|
|
1190
|
-
x,
|
|
1191
|
-
(list, tuple,
|
|
1192
|
-
np.ndarray)), f"Should promise a list for multiple symbols. {key}"
|
|
1193
|
-
if args is None:
|
|
1194
|
-
assert len(keys1) == len(
|
|
1195
|
-
x), f"Length of keys and values should be equal. {key}"
|
|
1196
|
-
for k, v in zip(keys1, x):
|
|
1197
|
-
variables[k] = v
|
|
1198
|
-
else:
|
|
1199
|
-
assert len(keys1) + len(keys2) <= len(
|
|
1200
|
-
x), f"Too many values for unpacking. {key}"
|
|
1201
|
-
for k, v in zip(keys1, x[:len(keys1)]):
|
|
1202
|
-
variables[k] = v
|
|
1203
|
-
end = -len(keys2) if keys2 else None
|
|
1204
|
-
for i, v in enumerate(x[len(keys1):end]):
|
|
1205
|
-
k = args[1:].format(i=i)
|
|
1206
|
-
variables[k] = v
|
|
1207
|
-
if keys2:
|
|
1208
|
-
for k, v in zip(keys2, x[end:]):
|
|
1209
|
-
variables[k] = v
|
|
1210
|
-
else:
|
|
1211
|
-
return
|
|
1212
|
-
del variables[key]
|
|
1166
|
+
return description
|
qulab/scan/server.py
CHANGED
|
@@ -73,14 +73,15 @@ def clear_cache():
|
|
|
73
73
|
return
|
|
74
74
|
|
|
75
75
|
logger.debug(f"clear_cache record_cache: {len(record_cache)}")
|
|
76
|
-
for k, (t,
|
|
77
|
-
|
|
76
|
+
for (k, (t, r),
|
|
77
|
+
i) in zip(sorted(record_cache.items(), key=lambda x: x[1][0]),
|
|
78
|
+
range(len(record_cache) - CACHE_SIZE)):
|
|
78
79
|
del record_cache[k]
|
|
79
80
|
|
|
80
81
|
logger.debug(f"clear_cache buffer_list_cache: {len(buffer_list_cache)}")
|
|
81
|
-
for k, (t,
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
for (k, (t, r),
|
|
83
|
+
i) in zip(sorted(buffer_list_cache.items(), key=lambda x: x[1][0]),
|
|
84
|
+
range(len(buffer_list_cache) - CACHE_SIZE)):
|
|
84
85
|
del buffer_list_cache[k]
|
|
85
86
|
logger.debug(f"clear_cache done.")
|
|
86
87
|
|
qulab/scan/space.py
CHANGED
|
@@ -25,12 +25,27 @@ class Space():
|
|
|
25
25
|
|
|
26
26
|
@classmethod
|
|
27
27
|
def fromarray(cls, space):
|
|
28
|
-
if isinstance(space, Space):
|
|
28
|
+
if isinstance(space, (Space, range, enumerate, tuple)):
|
|
29
29
|
return space
|
|
30
|
-
if isinstance(space,
|
|
31
|
-
|
|
30
|
+
if isinstance(space, list):
|
|
31
|
+
if isinstance(space[0], int):
|
|
32
|
+
try:
|
|
33
|
+
if all(i == j for i, j in zip(
|
|
34
|
+
space,
|
|
35
|
+
range(space[0], space[-1] + 1, space[1] -
|
|
36
|
+
space[0]))):
|
|
37
|
+
return range(space[0], space[-1] + 1,
|
|
38
|
+
space[1] - space[0])
|
|
39
|
+
except:
|
|
40
|
+
return space
|
|
41
|
+
elif isinstance(space[0], (float, complex, np.ndarray)):
|
|
42
|
+
array = np.array(space)
|
|
43
|
+
else:
|
|
44
|
+
return space
|
|
32
45
|
elif isinstance(space, np.ndarray):
|
|
33
46
|
array = space
|
|
47
|
+
else:
|
|
48
|
+
return space
|
|
34
49
|
try:
|
|
35
50
|
a = np.linspace(array[0], array[-1], len(array), dtype=array.dtype)
|
|
36
51
|
if np.allclose(a, array):
|
qulab/scan/utils.py
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import ast
|
|
2
2
|
import asyncio
|
|
3
3
|
import inspect
|
|
4
|
+
import platform
|
|
5
|
+
import re
|
|
6
|
+
import subprocess
|
|
7
|
+
import sys
|
|
8
|
+
import uuid
|
|
4
9
|
import warnings
|
|
5
10
|
from typing import Any, Callable
|
|
6
11
|
|
|
@@ -169,3 +174,56 @@ async def call_function(func: Callable | Expression, variables: dict[str,
|
|
|
169
174
|
if inspect.isawaitable(ret):
|
|
170
175
|
ret = await ret
|
|
171
176
|
return ret
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def yapf_reformat(cell_text):
|
|
180
|
+
try:
|
|
181
|
+
import isort
|
|
182
|
+
import yapf.yapflib.yapf_api
|
|
183
|
+
|
|
184
|
+
fname = f"f{uuid.uuid1().hex}"
|
|
185
|
+
|
|
186
|
+
def wrap(source):
|
|
187
|
+
lines = [f"async def {fname}():"]
|
|
188
|
+
for line in source.split('\n'):
|
|
189
|
+
lines.append(" " + line)
|
|
190
|
+
return '\n'.join(lines)
|
|
191
|
+
|
|
192
|
+
def unwrap(source):
|
|
193
|
+
lines = []
|
|
194
|
+
for line in source.split('\n'):
|
|
195
|
+
if line.startswith(f"async def {fname}():"):
|
|
196
|
+
continue
|
|
197
|
+
lines.append(line[4:])
|
|
198
|
+
return '\n'.join(lines)
|
|
199
|
+
|
|
200
|
+
cell_text = re.sub('^%', '#%#', cell_text, flags=re.M)
|
|
201
|
+
reformated_text = unwrap(
|
|
202
|
+
yapf.yapflib.yapf_api.FormatCode(wrap(isort.code(cell_text)))[0])
|
|
203
|
+
return re.sub('^#%#', '%', reformated_text, flags=re.M)
|
|
204
|
+
except:
|
|
205
|
+
return cell_text
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def get_installed_packages():
|
|
209
|
+
result = subprocess.run([sys.executable, '-m', 'pip', 'freeze'],
|
|
210
|
+
stdout=subprocess.PIPE,
|
|
211
|
+
text=True)
|
|
212
|
+
|
|
213
|
+
lines = result.stdout.split('\n')
|
|
214
|
+
packages = []
|
|
215
|
+
for line in lines:
|
|
216
|
+
if line:
|
|
217
|
+
packages.append(line)
|
|
218
|
+
return packages
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def get_system_info():
|
|
222
|
+
info = {
|
|
223
|
+
'OS': platform.uname()._asdict(),
|
|
224
|
+
'Python': sys.version,
|
|
225
|
+
'PythonExecutable': sys.executable,
|
|
226
|
+
'PythonPath': sys.path,
|
|
227
|
+
'packages': get_installed_packages()
|
|
228
|
+
}
|
|
229
|
+
return info
|
qulab/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "2.3.
|
|
1
|
+
__version__ = "2.3.5"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|