QuLab 2.0.1__cp312-cp312-win_amd64.whl → 2.0.3__cp312-cp312-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.0.1.dist-info → QuLab-2.0.3.dist-info}/METADATA +5 -1
- {QuLab-2.0.1.dist-info → QuLab-2.0.3.dist-info}/RECORD +20 -18
- qulab/__main__.py +2 -0
- qulab/fun.cp312-win_amd64.pyd +0 -0
- qulab/scan/__init__.py +2 -3
- qulab/scan/curd.py +144 -0
- qulab/scan/expression.py +34 -1
- qulab/scan/models.py +540 -0
- qulab/scan/optimize.py +69 -0
- qulab/scan/query_record.py +361 -0
- qulab/scan/recorder.py +447 -0
- qulab/scan/scan.py +693 -0
- qulab/scan/utils.py +80 -34
- qulab/sys/rpc/zmq_socket.py +209 -0
- qulab/version.py +1 -1
- qulab/visualization/_autoplot.py +11 -5
- qulab/scan/base.py +0 -548
- qulab/scan/dataset.py +0 -0
- qulab/scan/scanner.py +0 -270
- qulab/scan/transforms.py +0 -16
- {QuLab-2.0.1.dist-info → QuLab-2.0.3.dist-info}/LICENSE +0 -0
- {QuLab-2.0.1.dist-info → QuLab-2.0.3.dist-info}/WHEEL +0 -0
- {QuLab-2.0.1.dist-info → QuLab-2.0.3.dist-info}/entry_points.txt +0 -0
- {QuLab-2.0.1.dist-info → QuLab-2.0.3.dist-info}/top_level.txt +0 -0
qulab/scan/scanner.py
DELETED
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
import ast
|
|
2
|
-
import itertools
|
|
3
|
-
|
|
4
|
-
import numpy as np
|
|
5
|
-
|
|
6
|
-
from .base import scan_iters
|
|
7
|
-
from .expression import Env, Expression, Symbol, _empty
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def is_valid_identifier(s: str) -> bool:
|
|
11
|
-
try:
|
|
12
|
-
ast.parse(f"f({s}=0)")
|
|
13
|
-
return True
|
|
14
|
-
except SyntaxError:
|
|
15
|
-
return False
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class Atom():
|
|
19
|
-
__slots__ = ('value', )
|
|
20
|
-
|
|
21
|
-
def __init__(self, value):
|
|
22
|
-
self.value = value
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
class MappedSymbol(Symbol):
|
|
26
|
-
pass
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class OptimizeSpace():
|
|
30
|
-
|
|
31
|
-
def __init__(self, optimizer, space):
|
|
32
|
-
self.optimizer = optimizer
|
|
33
|
-
self.space = space
|
|
34
|
-
self.name = None
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
class Optimizer():
|
|
38
|
-
|
|
39
|
-
def __init__(self, cls, *args, **kwds):
|
|
40
|
-
self.cls = cls
|
|
41
|
-
self.args = args
|
|
42
|
-
self.kwds = kwds
|
|
43
|
-
self.dimensions = {}
|
|
44
|
-
self.function = None
|
|
45
|
-
|
|
46
|
-
def Categorical(self, *args, **kwds):
|
|
47
|
-
from skopt.space import Categorical
|
|
48
|
-
return OptimizeSpace(self, Categorical(*args, **kwds))
|
|
49
|
-
|
|
50
|
-
def Integer(self, *args, **kwds):
|
|
51
|
-
from skopt.space import Integer
|
|
52
|
-
return OptimizeSpace(self, Integer(*args, **kwds))
|
|
53
|
-
|
|
54
|
-
def Real(self, *args, **kwds):
|
|
55
|
-
from skopt.space import Real
|
|
56
|
-
return OptimizeSpace(self, Real(*args, **kwds))
|
|
57
|
-
|
|
58
|
-
@property
|
|
59
|
-
def target(self):
|
|
60
|
-
return None
|
|
61
|
-
|
|
62
|
-
@target.setter
|
|
63
|
-
def target(self, fun):
|
|
64
|
-
if isinstance(fun, Symbol):
|
|
65
|
-
self.function = fun.name
|
|
66
|
-
elif isinstance(fun, Expression):
|
|
67
|
-
self.function = fun
|
|
68
|
-
else:
|
|
69
|
-
raise ValueError("Invalid function")
|
|
70
|
-
|
|
71
|
-
def create_optimizer(self):
|
|
72
|
-
dimensions = list(self.dimensions.values())
|
|
73
|
-
return tuple(self.dimensions.keys()), self.cls(dimensions, *self.args,
|
|
74
|
-
**self.kwds)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
class Action():
|
|
78
|
-
|
|
79
|
-
__slots__ = ('name', 'args', 'kwds')
|
|
80
|
-
|
|
81
|
-
def __init__(self, name, *args, **kwds):
|
|
82
|
-
self.name = name
|
|
83
|
-
self.args = args
|
|
84
|
-
self.kwds = kwds
|
|
85
|
-
|
|
86
|
-
def __repr__(self):
|
|
87
|
-
return f"Action({self.name!r}, {self.args}, {self.kwds})"
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
class Scan():
|
|
91
|
-
|
|
92
|
-
def __new__(cls, *args, mixin=None, **kwds):
|
|
93
|
-
if mixin is None:
|
|
94
|
-
return super().__new__(cls)
|
|
95
|
-
for k in dir(mixin):
|
|
96
|
-
if not hasattr(cls, k):
|
|
97
|
-
try:
|
|
98
|
-
setattr(cls, k, getattr(mixin, k))
|
|
99
|
-
except:
|
|
100
|
-
pass
|
|
101
|
-
return super().__new__(cls)
|
|
102
|
-
|
|
103
|
-
def __init__(self, name, *args, env=None, mixin=None, **kwds):
|
|
104
|
-
super().__init__(*args, **kwds)
|
|
105
|
-
self._name = name.replace(' ', '_')
|
|
106
|
-
self.env = Env() if env is None else env
|
|
107
|
-
self.functions = {}
|
|
108
|
-
self.consts = {}
|
|
109
|
-
self.loops = {}
|
|
110
|
-
self.mapping = {}
|
|
111
|
-
self.optimizers = {}
|
|
112
|
-
self._mapping_i = 0
|
|
113
|
-
self.filter = None
|
|
114
|
-
self.scan_info = {'loops': {}}
|
|
115
|
-
self._tmp = {}
|
|
116
|
-
self.actions = {}
|
|
117
|
-
self.iteration = 0
|
|
118
|
-
|
|
119
|
-
@property
|
|
120
|
-
def name(self):
|
|
121
|
-
return f"Scan.{self._name}"
|
|
122
|
-
|
|
123
|
-
def get(self, key, default=_empty):
|
|
124
|
-
if key in self.consts:
|
|
125
|
-
return self.consts[key]
|
|
126
|
-
if key in self.functions:
|
|
127
|
-
return self.functions[key]
|
|
128
|
-
if default is _empty:
|
|
129
|
-
raise KeyError(f"Key {key} not found")
|
|
130
|
-
return default
|
|
131
|
-
|
|
132
|
-
def set(self, key, value):
|
|
133
|
-
self.add_action(Action('set', key, value))
|
|
134
|
-
|
|
135
|
-
def _mapping(self, key, value):
|
|
136
|
-
tmpkey = f"__tmp_{self._mapping_i}__"
|
|
137
|
-
self._mapping_i += 1
|
|
138
|
-
self.__setitem(tmpkey, value)
|
|
139
|
-
self.mapping[key] = tmpkey
|
|
140
|
-
|
|
141
|
-
def __setitem__(self, key, value):
|
|
142
|
-
if is_valid_identifier(key):
|
|
143
|
-
if isinstance(value, Atom):
|
|
144
|
-
self.consts[key] = value.value
|
|
145
|
-
return
|
|
146
|
-
elif isinstance(value, (str, int, float, complex, tuple)):
|
|
147
|
-
self.consts[key] = value
|
|
148
|
-
return
|
|
149
|
-
|
|
150
|
-
if isinstance(value, Expression):
|
|
151
|
-
env = Env()
|
|
152
|
-
env.consts = self.consts
|
|
153
|
-
value = value.value(env)
|
|
154
|
-
if not isinstance(value, Expression):
|
|
155
|
-
self.__setitem__(key, value)
|
|
156
|
-
return
|
|
157
|
-
|
|
158
|
-
self._tmp[key] = value
|
|
159
|
-
|
|
160
|
-
def __setitem(self, key, value):
|
|
161
|
-
if not is_valid_identifier(key):
|
|
162
|
-
self._mapping(key, value)
|
|
163
|
-
return
|
|
164
|
-
if isinstance(value, Expression) or callable(value):
|
|
165
|
-
self.functions[key] = value
|
|
166
|
-
elif isinstance(value, OptimizeSpace):
|
|
167
|
-
self.optimizers[key] = value.optimizer
|
|
168
|
-
value.name = key
|
|
169
|
-
value.optimizer.dimensions[key] = value.space
|
|
170
|
-
self.loops[key] = value.optimizer
|
|
171
|
-
elif isinstance(value, (np.ndarray, list, range)):
|
|
172
|
-
self.loops[key] = value
|
|
173
|
-
elif isinstance(value, Atom):
|
|
174
|
-
self.consts[key] = value.value
|
|
175
|
-
else:
|
|
176
|
-
self.consts[key] = value
|
|
177
|
-
|
|
178
|
-
def __getitem__(self, key):
|
|
179
|
-
if key in self.consts:
|
|
180
|
-
return self.consts[key]
|
|
181
|
-
if is_valid_identifier(key):
|
|
182
|
-
return Symbol(key)
|
|
183
|
-
else:
|
|
184
|
-
if key in self.mapping:
|
|
185
|
-
return Symbol(self.mapping[key])
|
|
186
|
-
return MappedSymbol(key)
|
|
187
|
-
|
|
188
|
-
def assemble(self):
|
|
189
|
-
for key, value in self._tmp.items():
|
|
190
|
-
self.__setitem(key, value)
|
|
191
|
-
|
|
192
|
-
variables = {}
|
|
193
|
-
loops = {}
|
|
194
|
-
|
|
195
|
-
for k, v in self.functions.items():
|
|
196
|
-
if isinstance(v, MappedSymbol):
|
|
197
|
-
variables[k] = eval(
|
|
198
|
-
f"lambda {self.mapping[k]}: {self.mapping[k]}")
|
|
199
|
-
elif isinstance(v, Expression):
|
|
200
|
-
args = v.symbols()
|
|
201
|
-
for x in args:
|
|
202
|
-
if x in self.mapping:
|
|
203
|
-
args.remove(x)
|
|
204
|
-
v = v.value({x: Symbol(self.mapping[x])})
|
|
205
|
-
x = self.mapping[x]
|
|
206
|
-
if x in self.consts:
|
|
207
|
-
args.remove(x)
|
|
208
|
-
v = v.value({x: self.consts[x]})
|
|
209
|
-
if args:
|
|
210
|
-
variables[k] = eval(
|
|
211
|
-
f"lambda {','.join(args)}: expr.value({{{','.join([f'{x!r}:{x}' for x in args])}}})",
|
|
212
|
-
{'expr': v})
|
|
213
|
-
else:
|
|
214
|
-
self.consts[k] = v
|
|
215
|
-
else:
|
|
216
|
-
variables[k] = v
|
|
217
|
-
|
|
218
|
-
for key, value in self.loops.items():
|
|
219
|
-
if isinstance(value, Optimizer):
|
|
220
|
-
#variables[key] = value.create_optimizer()
|
|
221
|
-
pass
|
|
222
|
-
else:
|
|
223
|
-
loops[key] = value
|
|
224
|
-
|
|
225
|
-
self.scan_info = {
|
|
226
|
-
'loops': loops,
|
|
227
|
-
'functions': variables,
|
|
228
|
-
'constants': self.consts
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
if self.filter is not None:
|
|
232
|
-
self.scan_info['filter'] = self.filter
|
|
233
|
-
|
|
234
|
-
def main(self):
|
|
235
|
-
self.assemble()
|
|
236
|
-
for step in self.scan():
|
|
237
|
-
for k, v in self.mapping.items():
|
|
238
|
-
if v in set(
|
|
239
|
-
itertools.chain.from_iterable(
|
|
240
|
-
step.vars[step.unchanged:])
|
|
241
|
-
) or step.iteration == 0:
|
|
242
|
-
self.set(k, step.kwds[v])
|
|
243
|
-
self.process(step)
|
|
244
|
-
|
|
245
|
-
def process(self, step):
|
|
246
|
-
for k, v in step.kwds.items():
|
|
247
|
-
if not k.startswith('__tmp_') and not k.startswith('__'):
|
|
248
|
-
self.add_action(Action('write', k, v))
|
|
249
|
-
|
|
250
|
-
def scan(self):
|
|
251
|
-
for step in scan_iters(**self.scan_info):
|
|
252
|
-
for k, v in self.mapping.items():
|
|
253
|
-
step.kwds[k] = step.kwds[v]
|
|
254
|
-
yield step
|
|
255
|
-
self.iteration += 1
|
|
256
|
-
|
|
257
|
-
def add_action(self, action: Action):
|
|
258
|
-
self.actions.setdefault(self.iteration, []).append(action)
|
|
259
|
-
|
|
260
|
-
def run(self, dry_run=False):
|
|
261
|
-
pass
|
|
262
|
-
|
|
263
|
-
def plot(self,
|
|
264
|
-
result=None,
|
|
265
|
-
fig=None,
|
|
266
|
-
axis=None,
|
|
267
|
-
data='population',
|
|
268
|
-
T=False,
|
|
269
|
-
**kwds):
|
|
270
|
-
pass
|
qulab/scan/transforms.py
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|