umaudemc 0.17.0__py3-none-any.whl → 0.17.1__py3-none-any.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.
- umaudemc/command/sworker.py +16 -0
- umaudemc/distributed.py +51 -10
- umaudemc/simulators.py +3 -4
- umaudemc/statistical.py +25 -6
- {umaudemc-0.17.0.dist-info → umaudemc-0.17.1.dist-info}/METADATA +1 -1
- {umaudemc-0.17.0.dist-info → umaudemc-0.17.1.dist-info}/RECORD +10 -10
- {umaudemc-0.17.0.dist-info → umaudemc-0.17.1.dist-info}/WHEEL +1 -1
- {umaudemc-0.17.0.dist-info → umaudemc-0.17.1.dist-info}/entry_points.txt +0 -0
- {umaudemc-0.17.0.dist-info → umaudemc-0.17.1.dist-info}/licenses/LICENSE +0 -0
- {umaudemc-0.17.0.dist-info → umaudemc-0.17.1.dist-info}/top_level.txt +0 -0
umaudemc/command/sworker.py
CHANGED
|
@@ -99,10 +99,13 @@ class Worker:
|
|
|
99
99
|
for k, qinfo in enumerate(program.queries)
|
|
100
100
|
for idict, _ in make_parameter_dicts(qinfo, 1.0)]
|
|
101
101
|
|
|
102
|
+
# Compact arrays are used so that they can be sent through the socket
|
|
102
103
|
sums = array('d', [0.0] * len(qdata))
|
|
103
104
|
sum_sq = array('d', [0.0] * len(qdata))
|
|
104
105
|
counts = array('i', [0] * len(qdata))
|
|
105
106
|
|
|
107
|
+
converged = array('i') # to store indices of converged queries
|
|
108
|
+
|
|
106
109
|
while True:
|
|
107
110
|
|
|
108
111
|
for _ in range(block):
|
|
@@ -120,14 +123,27 @@ class Worker:
|
|
|
120
123
|
# Check whether to continue
|
|
121
124
|
answer = conn.recv(1)
|
|
122
125
|
|
|
126
|
+
# Stop command
|
|
123
127
|
if answer == b's':
|
|
124
128
|
print('Done')
|
|
125
129
|
return
|
|
126
130
|
|
|
131
|
+
# Partial convergence
|
|
132
|
+
elif answer == b'p':
|
|
133
|
+
mcount = int.from_bytes(conn.recv(4), 'big')
|
|
134
|
+
# Safety check
|
|
135
|
+
if mcount <= len(qdata):
|
|
136
|
+
converged.frombytes(conn.recv(4 * mcount))
|
|
137
|
+
# Set the converged queries to avoid recomputing them
|
|
138
|
+
for index in converged:
|
|
139
|
+
qdata[index].converged = True
|
|
140
|
+
del converged[:]
|
|
141
|
+
|
|
127
142
|
elif answer != b'c':
|
|
128
143
|
usermsgs.print_error(f'Unknown command {answer.decode()}. Stopping.')
|
|
129
144
|
return
|
|
130
145
|
|
|
146
|
+
# Reset the accumulators for the next round
|
|
131
147
|
for k in range(len(qdata)):
|
|
132
148
|
sums[k] = 0
|
|
133
149
|
sum_sq[k] = 0
|
umaudemc/distributed.py
CHANGED
|
@@ -225,7 +225,7 @@ def setup_workers(args, initial_data, dspec, constants, seen_files, stack):
|
|
|
225
225
|
input_data['block'] = block_size # if specified
|
|
226
226
|
|
|
227
227
|
input_data = json.dumps(input_data).encode()
|
|
228
|
-
sock.sendall(len(input_data).to_bytes(4) + input_data)
|
|
228
|
+
sock.sendall(len(input_data).to_bytes(4, 'big') + input_data)
|
|
229
229
|
|
|
230
230
|
# Send the relevant files
|
|
231
231
|
with sock.makefile('wb', buffering=0) as fobj:
|
|
@@ -249,6 +249,17 @@ def setup_workers(args, initial_data, dspec, constants, seen_files, stack):
|
|
|
249
249
|
return sockets
|
|
250
250
|
|
|
251
251
|
|
|
252
|
+
class WorkerData:
|
|
253
|
+
"""Relevant data for the worker"""
|
|
254
|
+
|
|
255
|
+
__attrs__ = ('index', 'block', 'name')
|
|
256
|
+
|
|
257
|
+
def __init__(self, index, block, data):
|
|
258
|
+
self.index = index
|
|
259
|
+
self.block = data.get('block', block)
|
|
260
|
+
self.name = data.get('name')
|
|
261
|
+
|
|
262
|
+
|
|
252
263
|
def distributed_check(args, initial_data, min_sim, max_sim, program, constants, seen_files):
|
|
253
264
|
"""Distributed statistical model checking"""
|
|
254
265
|
|
|
@@ -269,9 +280,10 @@ def distributed_check(args, initial_data, min_sim, max_sim, program, constants,
|
|
|
269
280
|
# Use a selector to wait for updates from any worker
|
|
270
281
|
selector = selectors.DefaultSelector()
|
|
271
282
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
sock.
|
|
283
|
+
# Use a selector to be notified of the worker answers
|
|
284
|
+
for k, (sock, data) in enumerate(zip(sockets, dspec['workers'])):
|
|
285
|
+
selector.register(sock, selectors.EVENT_READ, data=WorkerData(k, args.block, data))
|
|
286
|
+
sock.send(b'c') # continue command
|
|
275
287
|
|
|
276
288
|
buffer = array('d')
|
|
277
289
|
ibuffer = array('i')
|
|
@@ -283,6 +295,12 @@ def distributed_check(args, initial_data, min_sim, max_sim, program, constants,
|
|
|
283
295
|
nqueries = len(qdata)
|
|
284
296
|
num_sims = 0
|
|
285
297
|
|
|
298
|
+
# In order to tell the workers which queries have converged, we keep
|
|
299
|
+
# a list of indices of converged queries in cronological order and
|
|
300
|
+
# a list with the next index to be transmitted to each worker
|
|
301
|
+
converged_queries = array('i')
|
|
302
|
+
next_to_tell = [0] * len(sockets)
|
|
303
|
+
|
|
286
304
|
quantile = get_quantile_func()
|
|
287
305
|
|
|
288
306
|
while sockets:
|
|
@@ -294,35 +312,58 @@ def distributed_check(args, initial_data, min_sim, max_sim, program, constants,
|
|
|
294
312
|
|
|
295
313
|
answer = sock.recv(1)
|
|
296
314
|
|
|
315
|
+
# Block finished
|
|
297
316
|
if answer == b'b':
|
|
317
|
+
# The message is the concatenation of three arrays
|
|
318
|
+
# (sum, sum_sq, and counts) of nqueries elements each.
|
|
319
|
+
# sum and sum_sq contain 64-bit floating-point numbers
|
|
320
|
+
# and counts contains 32-bit integer numbers
|
|
298
321
|
data = sock.recv(24 * nqueries)
|
|
299
322
|
buffer.frombytes(data[:16 * nqueries])
|
|
300
323
|
ibuffer.frombytes(data[16 * nqueries:])
|
|
301
324
|
|
|
325
|
+
# Some queries may have not been evaluated because
|
|
326
|
+
# they converged, but it is easier to sum their zeros
|
|
302
327
|
for k in range(nqueries):
|
|
303
328
|
qdata[k].sum += buffer[k]
|
|
304
329
|
qdata[k].sum_sq += buffer[nqueries + k]
|
|
305
330
|
qdata[k].n += ibuffer[k]
|
|
306
331
|
|
|
307
|
-
num_sims += key.data
|
|
332
|
+
num_sims += key.data.block
|
|
308
333
|
|
|
309
334
|
del buffer[:]
|
|
310
335
|
del ibuffer[:]
|
|
311
|
-
finished.append(key
|
|
336
|
+
finished.append(key)
|
|
312
337
|
|
|
313
338
|
else:
|
|
314
|
-
usermsgs.print_error(f'Server {key.data
|
|
339
|
+
usermsgs.print_error(f'Server {key.data.name} disconnected or misbehaving')
|
|
315
340
|
selector.unregister(key.fileobj)
|
|
316
341
|
sockets.remove(key.fileobj)
|
|
317
342
|
|
|
318
343
|
# Check whether the simulation has converged
|
|
319
|
-
converged = check_interval(qdata, num_sims, min_sim, args.alpha, quantile, args.verbose)
|
|
344
|
+
converged, which = check_interval(qdata, num_sims, min_sim, args.alpha, quantile, args.verbose)
|
|
345
|
+
|
|
346
|
+
# More converged queries
|
|
347
|
+
if which:
|
|
348
|
+
converged_queries.extend(which)
|
|
320
349
|
|
|
321
350
|
if converged or max_sim and num_sims >= max_sim:
|
|
322
351
|
break
|
|
323
352
|
|
|
324
|
-
for
|
|
325
|
-
|
|
353
|
+
for key in finished:
|
|
354
|
+
index = key.data.index
|
|
355
|
+
|
|
356
|
+
# Transmit which queries have converged
|
|
357
|
+
if next_to_tell[index] != len(converged_queries):
|
|
358
|
+
# We send p followed by the number of indices and then the indices
|
|
359
|
+
key.fileobj.send(b'p'
|
|
360
|
+
+ (len(converged_queries) - next_to_tell[index]).to_bytes(4, 'big')
|
|
361
|
+
+ converged_queries[next_to_tell[index]:].tobytes())
|
|
362
|
+
next_to_tell[index] = len(converged_queries)
|
|
363
|
+
|
|
364
|
+
# Continue without change
|
|
365
|
+
else:
|
|
366
|
+
key.fileobj.send(b'c')
|
|
326
367
|
|
|
327
368
|
finished.clear()
|
|
328
369
|
|
umaudemc/simulators.py
CHANGED
|
@@ -164,9 +164,9 @@ class UmaudemcSimulator(BaseSimulator):
|
|
|
164
164
|
def __init__(self, initial, graph, assigner):
|
|
165
165
|
super().__init__(initial)
|
|
166
166
|
|
|
167
|
-
self.state_nr = 0
|
|
168
167
|
self.graph = graph
|
|
169
168
|
self.assigner = assigner
|
|
169
|
+
self.state_nr = 0
|
|
170
170
|
self.time = 0.0
|
|
171
171
|
|
|
172
172
|
def restart(self):
|
|
@@ -310,9 +310,8 @@ class PMaudeSimulator(BaseSimulator):
|
|
|
310
310
|
self.nat_kind = nat_kind
|
|
311
311
|
self.val = val
|
|
312
312
|
|
|
313
|
-
#
|
|
314
|
-
self.state =
|
|
315
|
-
self.state.rewrite()
|
|
313
|
+
# restart must be called before running
|
|
314
|
+
self.state = None
|
|
316
315
|
|
|
317
316
|
# Try to find Maude's random symbol for calculating random(1). If the
|
|
318
317
|
# PMaude specification only reduces random(0), even after resetting the
|
umaudemc/statistical.py
CHANGED
|
@@ -139,8 +139,10 @@ def check_interval(qdata, num_sims, min_sim, alpha, quantile, verbose):
|
|
|
139
139
|
|
|
140
140
|
# Whether the size of the confidence interval for all queries have converged
|
|
141
141
|
converged = True
|
|
142
|
+
# Which queries have converged
|
|
143
|
+
which = []
|
|
142
144
|
|
|
143
|
-
for query in qdata:
|
|
145
|
+
for k, query in enumerate(qdata):
|
|
144
146
|
# This query has already converged
|
|
145
147
|
if query.converged:
|
|
146
148
|
continue
|
|
@@ -164,6 +166,7 @@ def check_interval(qdata, num_sims, min_sim, alpha, quantile, verbose):
|
|
|
164
166
|
if query.h <= query.delta and query.n >= min_sim:
|
|
165
167
|
query.converged = True
|
|
166
168
|
query.discarded = num_sims - query.n
|
|
169
|
+
which.append(k)
|
|
167
170
|
else:
|
|
168
171
|
converged = False
|
|
169
172
|
|
|
@@ -174,7 +177,10 @@ def check_interval(qdata, num_sims, min_sim, alpha, quantile, verbose):
|
|
|
174
177
|
f' σ={" ".join(str(q.s) for q in qdata)}'
|
|
175
178
|
f' r={" ".join(str(q.h) for q in qdata)}')
|
|
176
179
|
|
|
177
|
-
|
|
180
|
+
for k in which:
|
|
181
|
+
print(f' Query {qdata[k].query + 1} has converged')
|
|
182
|
+
|
|
183
|
+
return converged, which
|
|
178
184
|
|
|
179
185
|
|
|
180
186
|
def run_single(program, qdata, num_sims, min_sim, max_sim, simulator, alpha, block_size,
|
|
@@ -204,7 +210,7 @@ def run_single(program, qdata, num_sims, min_sim, max_sim, simulator, alpha, blo
|
|
|
204
210
|
query.sum_sq += value * value
|
|
205
211
|
query.n += 1
|
|
206
212
|
|
|
207
|
-
converged = check_interval(qdata, num_sims, min_sim, alpha, quantile, verbose)
|
|
213
|
+
converged, _ = check_interval(qdata, num_sims, min_sim, alpha, quantile, verbose)
|
|
208
214
|
|
|
209
215
|
if converged or max_sim and num_sims >= max_sim:
|
|
210
216
|
break
|
|
@@ -215,7 +221,7 @@ def run_single(program, qdata, num_sims, min_sim, max_sim, simulator, alpha, blo
|
|
|
215
221
|
return num_sims, qdata
|
|
216
222
|
|
|
217
223
|
|
|
218
|
-
def thread_main(program, qdata, simulator, num_sims, block_size, seed, queue, barrier, more, dump=None):
|
|
224
|
+
def thread_main(program, qdata, simulator, num_sims, block_size, seed, queue, barrier, more, convergents, dump=None):
|
|
219
225
|
"""Entry point of a calculating thread"""
|
|
220
226
|
|
|
221
227
|
maude.setRandomSeed(seed)
|
|
@@ -258,6 +264,12 @@ def thread_main(program, qdata, simulator, num_sims, block_size, seed, queue, ba
|
|
|
258
264
|
if not more.value:
|
|
259
265
|
break
|
|
260
266
|
|
|
267
|
+
# Disable queries that have converged
|
|
268
|
+
for k in range(len(qdata)):
|
|
269
|
+
if convergents[k] == -1:
|
|
270
|
+
break
|
|
271
|
+
qdata[convergents[k]].converged = True
|
|
272
|
+
|
|
261
273
|
# Continue for a next block
|
|
262
274
|
block = block_size
|
|
263
275
|
|
|
@@ -284,12 +296,14 @@ def run_parallel(program, qdata, num_sims, min_sim, max_sim, simulator, alpha, b
|
|
|
284
296
|
queue = mp.Queue()
|
|
285
297
|
barrier = mp.Barrier(jobs + 1)
|
|
286
298
|
more = mp.Value('b', False, lock=False)
|
|
299
|
+
convergents = mp.Array('i', [-1] * len(qdata), lock=False)
|
|
287
300
|
|
|
288
301
|
rest, rest_block = num_sims % jobs, block_size % jobs
|
|
289
302
|
processes = [mp.Process(target=thread_main,
|
|
290
303
|
args=(program, qdata, simulator, num_sims // jobs + (k < rest),
|
|
291
304
|
block_size // jobs + (k < rest_block),
|
|
292
|
-
seeds[k], queue, barrier, more, dumps[k]))
|
|
305
|
+
seeds[k], queue, barrier, more, convergents, dumps[k]))
|
|
306
|
+
for k in range(jobs)]
|
|
293
307
|
|
|
294
308
|
# Start all processes
|
|
295
309
|
for p in processes:
|
|
@@ -305,7 +319,7 @@ def run_parallel(program, qdata, num_sims, min_sim, max_sim, simulator, alpha, b
|
|
|
305
319
|
query.sum_sq += sum_sq[k]
|
|
306
320
|
query.n += counts[k]
|
|
307
321
|
|
|
308
|
-
converged = check_interval(qdata, num_sims, min_sim, alpha, quantile, verbose)
|
|
322
|
+
converged, which = check_interval(qdata, num_sims, min_sim, alpha, quantile, verbose)
|
|
309
323
|
|
|
310
324
|
if converged or max_sim and num_sims >= max_sim:
|
|
311
325
|
break
|
|
@@ -313,6 +327,11 @@ def run_parallel(program, qdata, num_sims, min_sim, max_sim, simulator, alpha, b
|
|
|
313
327
|
num_sims += block_size
|
|
314
328
|
|
|
315
329
|
more.value = True
|
|
330
|
+
# Inform which queries have converged
|
|
331
|
+
for k, qindex in enumerate(which):
|
|
332
|
+
convergents[k] = qindex
|
|
333
|
+
convergents[len(which)] = -1
|
|
334
|
+
|
|
316
335
|
barrier.wait()
|
|
317
336
|
|
|
318
337
|
more.value = False
|
|
@@ -4,7 +4,7 @@ umaudemc/api.py,sha256=naZ5edEbvx-S-NU29yAAJtqglfYnSAYVS2RJNyxJMQQ,19893
|
|
|
4
4
|
umaudemc/backends.py,sha256=mzJkALYwcKPInT0lBiRsCxJSewKvx5j_akQsqWN1Ezo,4590
|
|
5
5
|
umaudemc/common.py,sha256=UcIf7hTpP2qjcT9u_9-UcYR0nNeosx1xRZW7wsuT2bE,7305
|
|
6
6
|
umaudemc/counterprint.py,sha256=vVqM_UjGRk_xeftFxBGI5m6cQXV7mf8KvbQ_fvAvSQk,9226
|
|
7
|
-
umaudemc/distributed.py,sha256=
|
|
7
|
+
umaudemc/distributed.py,sha256=jUxVUHtPRefwxNYZmU0ErePre6FTmH5S8RX6ADBL1vA,10611
|
|
8
8
|
umaudemc/formatter.py,sha256=nbQlIsR5Xv18OEcpJdnTDGqO9xGL_amvBGFMU2OmheU,6026
|
|
9
9
|
umaudemc/formulae.py,sha256=jZPPDhjgsb7cs5rWvitiQoO0fd8JIlK98at2SN-LzVE,12156
|
|
10
10
|
umaudemc/grapher.py,sha256=K1chKNNlEzQvfOsiFmRPJmd9OpxRIrg6OyiMW6gqOCU,4348
|
|
@@ -17,8 +17,8 @@ umaudemc/probabilistic.py,sha256=MNvFeEd84-OYedSnyksZB87UckPfwizVNJepCItgRy8,293
|
|
|
17
17
|
umaudemc/pyslang.py,sha256=ABSXYUQO2TmDq8EZ3EpVZV8NecZ0p0gERlSvLUIVAm8,87970
|
|
18
18
|
umaudemc/quatex.py,sha256=7n7ugusjFUyO5jqKeb6-O8hdH4vj2fgnc-V_Z41w-40,27271
|
|
19
19
|
umaudemc/resources.py,sha256=qKqvgLYTJVtsQHQMXFObyCLTo6-fssQeu_mG7tvVyD0,932
|
|
20
|
-
umaudemc/simulators.py,sha256=
|
|
21
|
-
umaudemc/statistical.py,sha256=
|
|
20
|
+
umaudemc/simulators.py,sha256=1_DKaO2JYxSQHcbTE2wbB_lgd_kFBi40PPjOMvqOgaE,14341
|
|
21
|
+
umaudemc/statistical.py,sha256=I_C1ymz-ue-XaX0zF7lyQUce57-BdEWhctKg6yG2c_A,11371
|
|
22
22
|
umaudemc/terminal.py,sha256=B4GWLyW4Sdymgoavj418y4TI4MnWqNu3JS4BBoSYeTc,1037
|
|
23
23
|
umaudemc/usermsgs.py,sha256=h4VPxljyKidEI8vpPcToKJA6mcLu9PtMkIh6vH3rDuA,719
|
|
24
24
|
umaudemc/webui.py,sha256=XlDV87tOOdcclHp2_oerrvHwRmCZdqAR4PppqeZm47A,11072
|
|
@@ -41,7 +41,7 @@ umaudemc/command/check.py,sha256=PyaPDMw5OnPxSIZ10U4we0b5tTrjnYKAtAeQkJh2uLE,120
|
|
|
41
41
|
umaudemc/command/graph.py,sha256=JqGzESC2sn-LBh2sqctrij03ItzwDO808s2qkNKUle0,6112
|
|
42
42
|
umaudemc/command/pcheck.py,sha256=eV4e4GcOHanP4hcIhMKd5Js22_ONac6kYj70FXun3mY,7274
|
|
43
43
|
umaudemc/command/scheck.py,sha256=mmAzCdGdIHgKbsyEi0uW-jcj9X0MSc-EEkEPR-EiB8U,6208
|
|
44
|
-
umaudemc/command/sworker.py,sha256=
|
|
44
|
+
umaudemc/command/sworker.py,sha256=uxw8gmacghUMvM0MUqM-AXX-w9xOA-10Mj-ExPWoNUI,5196
|
|
45
45
|
umaudemc/command/test.py,sha256=Ru21JXNF61F5N5jayjwxp8okIjOAvuZuAlV_5ltQ-GU,37088
|
|
46
46
|
umaudemc/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
47
47
|
umaudemc/data/opsem.maude,sha256=geDP3_RMgtS1rRmYOybJDCXn_-dyHHxg0JxfYg1ftv0,27929
|
|
@@ -52,9 +52,9 @@ umaudemc/data/smcgraph.js,sha256=iCNQNmsuGdL_GLnqVhGDisediFtedxw3C24rxSiQwx8,667
|
|
|
52
52
|
umaudemc/data/smcview.css,sha256=ExFqrMkSeaf8VxFrJXflyCsRW3FTwbv78q0Hoo2UVrM,3833
|
|
53
53
|
umaudemc/data/smcview.js,sha256=_fHum1DRU1mhco-9-c6KqTLgiC5u_cCUf61jIK7wcIQ,14509
|
|
54
54
|
umaudemc/data/templog.maude,sha256=TZ-66hVWoG6gp7gJpS6FsQn7dpBTLrr76bKo-UfHGcA,9161
|
|
55
|
-
umaudemc-0.17.
|
|
56
|
-
umaudemc-0.17.
|
|
57
|
-
umaudemc-0.17.
|
|
58
|
-
umaudemc-0.17.
|
|
59
|
-
umaudemc-0.17.
|
|
60
|
-
umaudemc-0.17.
|
|
55
|
+
umaudemc-0.17.1.dist-info/licenses/LICENSE,sha256=MrEGL32oSWfnAZ0Bq4BZNcqnq3Mhp87Q4w6-deXfFnA,17992
|
|
56
|
+
umaudemc-0.17.1.dist-info/METADATA,sha256=bW8k2ctMQZPpFsXIHJ9wiBc2HoDwqw3VZHNyPgx75qk,1654
|
|
57
|
+
umaudemc-0.17.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
58
|
+
umaudemc-0.17.1.dist-info/entry_points.txt,sha256=8rYRlLkn4orZtAoujDSeol1t_UFBrK0bfjmLTNv9B44,52
|
|
59
|
+
umaudemc-0.17.1.dist-info/top_level.txt,sha256=Yo_CF78HLGBSblk3890qLcx6XZ17zHCbGcT9iG8sfMw,9
|
|
60
|
+
umaudemc-0.17.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|