Skip to content

Commit b1e42e1

Browse files
authored
Merge pull request #23 from mihsamusev/Add_single_run
Add single run method
2 parents 8669933 + 82ce0fc commit b1e42e1

File tree

3 files changed

+126
-64
lines changed

3 files changed

+126
-64
lines changed

docs/source/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Welcome to strategoutil's documentation!
66
provides an interface to perform model-predictive control or online-control.
77

88
.. toctree::
9-
:maxdepth: 3
9+
:maxdepth: 2
1010
:caption: Contents:
1111

1212
installation

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[metadata]
22
name = strategoutil
3-
version = 0.0.5
3+
version = 0.0.6
44
author = Mihhail Samusev, Martijn Goorden
55
author_email = [email protected]
66
description = Python utility functions library for UPPAAL Stratego

strategoutil.py

Lines changed: 124 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ def extract_state(text, var, controlperiod):
4343
:type text: str
4444
:param var: The variable name.
4545
:type var: str
46-
:param controlperiod: The interval duration after which the controller can change the control setting,
47-
given in Uppaal Stratego time units.
46+
:param controlperiod: The interval duration after which the controller can change the control
47+
setting, given in Uppaal Stratego time units.
4848
:type controlperiod: int
4949
:return: The value of the variable at the end of *controlperiod*.
5050
:rtype: float
@@ -112,7 +112,8 @@ def array_to_stratego(arr):
112112
113113
:param arr: The array string to convert.
114114
:type arr: str
115-
:return: An array string where ``"["`` and ``"]"`` are replaced by ``"{"`` and ``"}"``, respectively.
115+
:return: An array string where ``"["`` and ``"]"`` are replaced by ``"{"`` and ``"}"``,
116+
respectively.
116117
:rtype: str
117118
"""
118119
arrstr = str(arr)
@@ -158,15 +159,15 @@ def run_stratego(modelfile, queryfile="", learning_args=None, verifyta_command="
158159
Run command line version of Uppaal Stratego.
159160
160161
:param modelfile: The file name of the model.
161-
:type model_file: str
162+
:type modelfile: str
162163
:param queryfile: The file name of the query.
163164
:type queryfile: str
164165
:param learning_args: Dictionary containing the learning parameters and their values. The
165166
learning parameter names should be those used in the command line interface of Uppaal
166167
Stratego. You can also include non-learning command line parameters in this dictionary.
167168
If a non-learning command line parameter does not take any value, include the empty
168169
string ``""`` as value.
169-
:type learning_arg: dict
170+
:type learning_args: dict
170171
:param verifyta_command: The command name for running Uppaal Stratego at the user's machine.
171172
:type verifyta_command: str
172173
:return: The output as produced by Uppaal Stratego.
@@ -201,7 +202,7 @@ def successful_result(text):
201202
return result is not None
202203

203204

204-
def print_progress_bar(i, max, postText):
205+
def print_progress_bar(i, max, post_text):
205206
"""
206207
Print a progress bar to sys.stdout.
207208
@@ -214,13 +215,13 @@ def print_progress_bar(i, max, postText):
214215
:type i: int
215216
:param max: The maximum number of steps for process to be completed.
216217
:type max: int
217-
:param postText: The text to display after the progress bar.
218-
:type postText: str
218+
:param post_text: The text to display after the progress bar.
219+
:type post_text: str
219220
"""
220221
n_bar = 20 # Size of progress bar.
221222
j = i / max
222223
sys.stdout.write('\r')
223-
sys.stdout.write(f"[{'=' * int(n_bar * j):{n_bar}s}] {int(100 * j)}% {postText}")
224+
sys.stdout.write(f"[{'=' * int(n_bar * j):{n_bar}s}] {int(100 * j)}% {post_text}")
224225
sys.stdout.flush()
225226

226227

@@ -247,7 +248,7 @@ class StrategoController:
247248
def __init__(self, modeltemplatefile, model_cfg_dict, cleanup=True):
248249
self.templatefile = modeltemplatefile
249250
self.simulationfile = modeltemplatefile.replace(".xml", "_sim.xml")
250-
self.cleanup = cleanup # TODO: this variable seems to be not used. Can it be safely removed?
251+
self.cleanup = cleanup # TODO: this variable seems to be not used. Can it be safely removed?
251252
self.states = model_cfg_dict.copy()
252253
self.tagRule = "//TAG_{}"
253254

@@ -344,7 +345,7 @@ def run(self, queryfile="", learning_args=None, verifyta_command="verifyta"):
344345
Stratego. You can also include non-learning command line parameters in this dictionary.
345346
If a non-learning command line parameter does not take any value, include the empty
346347
string ``""`` as value.
347-
:type learning_arg: dict
348+
:type learning_args: dict
348349
:param verifyta_command: The command name for running Uppaal Stratego at the user's machine.
349350
:type verifyta_command: str
350351
:return: The output generated by Uppaal Stratego.
@@ -373,9 +374,9 @@ class MPCsetup:
373374
:param learning_args: Dictionary containing the learning parameters and their values. The
374375
learning parameter names should be those used in the command line interface of Uppaal
375376
Stratego. You can also include non-learning command line parameters in this dictionary. If
376-
a non-learning command line parameter does not take any value, include the empty string ``""``
377-
as value.
378-
:type learning_arg: dict
377+
a non-learning command line parameter does not take any value, include the empty string
378+
``""`` as value.
379+
:type learning_args: dict
379380
:param verifyta_command: The command name for running Uppaal Stratego at the user's machine.
380381
:type verifyta_command: str
381382
:param external_simulator: Whether an external simulator is used to obtain the true state after
@@ -402,11 +403,83 @@ def __init__(self, modeltemplatefile, output_file_path=None, queryfile="", model
402403
self.learning_args = {} if learning_args is None else learning_args
403404
self.verifyta_command = verifyta_command
404405
self.external_simulator = external_simulator
405-
if external_simulator: assert(action_variable in model_cfg_dict.keys())
406+
if external_simulator:
407+
assert (action_variable in model_cfg_dict.keys())
406408
self.action_variable = action_variable
407409
self.debug = debug
408410
self.controller = StrategoController(self.modeltemplatefile, self.model_cfg_dict)
409411

412+
def step_without_sim(self, controlperiod, horizon, duration, step, **kwargs):
413+
"""
414+
Perform a step in the basic MPC scheme without the simulation of the synthesized strategy.
415+
416+
:param controlperiod: The interval duration after which the controller can change the
417+
control setting, given in Uppaal Stratego time units.
418+
:type controlperiod: int
419+
:param horizon: The inval duration for which Uppaal stratego synthesizes a control strategy
420+
each MPC step. Is given in the number of control periods.
421+
:type horizon: int
422+
:param duration: The number of times (steps) the MPC scheme should be performed, given as
423+
the number of control periods. Is only forwarded to
424+
:meth:`~MPCsetup.perform_at_start_iteration`.
425+
:type duration: int
426+
:param step: The current iteration step in the basic MPC loop.
427+
:type step: int
428+
:param kwargs: Any additional parameters are forwarded to
429+
:meth:`~MPCsetup.perform_at_start_iteration`.
430+
:return: The output generated by Uppaal Stratego.
431+
:rtype: str
432+
"""
433+
# Perform some customizable preprocessing at each step.
434+
self.perform_at_start_iteration(controlperiod, horizon, duration, step, **kwargs)
435+
436+
# At each MPC step we want a clean template copy to insert variables.
437+
self.controller.init_simfile()
438+
439+
# Insert current state into simulation template.
440+
self.controller.insert_state()
441+
442+
# To debug errors from verifyta one can save intermediate simulation file.
443+
if self.debug:
444+
self.controller.debug_copy(self.modeltemplatefile.replace(".xml", "_debug.xml"))
445+
446+
# Create the new query file for the next step.
447+
final = horizon * controlperiod + self.controller.get_state("t")
448+
self.create_query_file(horizon, controlperiod, final)
449+
450+
# Run a verifyta query to simulate optimal strategy.
451+
result = self.run_verifyta(horizon, controlperiod, final)
452+
453+
return result
454+
455+
def run_single(self, controlperiod, horizon, **kwargs):
456+
"""
457+
Run the basic MPC scheme a single step where a single controller strategy is calculated,
458+
where the strategy synthesis looks the horizon ahead, and continues for the duration of the
459+
experiment.
460+
461+
The control period is in Uppaal Stratego time units. Horizon have control period as time
462+
unit.
463+
464+
:param controlperiod: The interval duration after which the controller can change the
465+
control setting, given in Uppaal Stratego time units.
466+
:type controlperiod: int
467+
:param horizon: The inval duration for which Uppaal stratego synthesizes a control strategy
468+
each MPC step. Is given in the number of control periods.
469+
:type horizon: int
470+
:param `**kwargs`: Any additional parameters are forwarded to
471+
:meth:`~MPCsetup.perform_at_start_iteration`.
472+
:return: The control action chosen for the first control period.
473+
"""
474+
if not check_tool_existance(self.verifyta_command):
475+
raise RuntimeError(
476+
"Cannot find the supplied verifyta command: " + self.verifyta_command)
477+
478+
result = self.step_without_sim(controlperiod, horizon, 1, 0, **kwargs)
479+
chosen_action = self.extract_control_action_from_stratego(result)
480+
481+
return chosen_action
482+
410483
def run(self, controlperiod, horizon, duration, **kwargs):
411484
"""
412485
Run the basic MPC scheme where the controller can changes its strategy once every period,
@@ -416,14 +489,14 @@ def run(self, controlperiod, horizon, duration, **kwargs):
416489
The control period is in Uppaal Stratego time units. Both horizon and duration have control
417490
period as time unit.
418491
419-
:param controlperiod: The interval duration after which the controller can change the control setting,
420-
given in Uppaal Stratego time units.
492+
:param controlperiod: The interval duration after which the controller can change the
493+
control setting, given in Uppaal Stratego time units.
421494
:type controlperiod: int
422495
:param horizon: The inval duration for which Uppaal stratego synthesizes a control strategy
423496
each MPC step. Is given in the number of control periods.
424497
:type horizon: int
425-
:param duration: The number of times (steps) the MPC scheme should be performed, given as the
426-
number of control periods.
498+
:param duration: The number of times (steps) the MPC scheme should be performed, given as
499+
the number of control periods.
427500
:type duration: int
428501
:param `**kwargs`: Any additional parameters are forwarded to
429502
:meth:`~MPCsetup.perform_at_start_iteration`.
@@ -433,50 +506,36 @@ def run(self, controlperiod, horizon, duration, **kwargs):
433506
self.print_state()
434507

435508
if not check_tool_existance(self.verifyta_command):
436-
raise RuntimeError("Cannot find the supplied verifyta command: " + self.verifyta_command)
509+
raise RuntimeError(
510+
"Cannot find the supplied verifyta command: " + self.verifyta_command)
437511

438512
for step in range(duration):
439513
# Only print progress to stdout if results are printed to a file.
440-
if (self.output_file_path): print_progress_bar(step, duration, "progress")
514+
if self.output_file_path:
515+
print_progress_bar(step, duration, "progress")
441516

442-
# Perform some customizable preprocessing at each step.
443-
self.perform_at_start_iteration(controlperiod, horizon, duration, step, **kwargs)
444-
445-
# At each MPC step we want a clean template copy to insert variables.
446-
self.controller.init_simfile()
447-
448-
# Insert current state into simulation template.
449-
self.controller.insert_state()
450-
451-
# To debug errors from verifyta one can save intermediate simulation file.
452-
if self.debug:
453-
self.controller.debug_copy(self.modeltemplatefile.replace(".xml", "_debug.xml"))
454-
455-
# Create the new query file for the next step.
456-
final = horizon * controlperiod + self.controller.get_state("t")
457-
self.create_query_file(horizon, controlperiod, final)
458-
459-
# Run a verifyta query to simulate optimal strategy.
460-
result = self.run_verifyta(horizon, controlperiod, final)
517+
result = self.step_without_sim(controlperiod, horizon, duration, step, **kwargs)
461518

462519
if self.external_simulator:
463520
# An external simulator is used to generate the new 'true' state.
464-
chosen_action = self.extract_control_action_from_Stratego(result)
465-
new_state = self.run_external_simulator(chosen_action, controlperiod, step, **kwargs)
521+
chosen_action = self.extract_control_action_from_stratego(result)
522+
new_state = self.run_external_simulator(chosen_action, controlperiod, step,
523+
**kwargs)
466524
self.controller.update_state(new_state)
467525

468526
else:
469527
# Extract the state from Uppaal results. This requires that the query file also
470528
# includes a simulate query (see default query generator).
471-
self.extract_states_from_Stratego(result, controlperiod)
529+
self.extract_states_from_stratego(result, controlperiod)
472530

473531
# Print output.
474532
self.print_state()
475-
if(self.output_file_path): print_progress_bar(duration, duration, "finished")
533+
if self.output_file_path:
534+
print_progress_bar(duration, duration, "finished")
476535

477536
def perform_at_start_iteration(self, *args, **kwargs):
478537
"""
479-
Performs some customizable preprocessing steps at the start of each MPC iteration. This
538+
Perform some customizable preprocessing steps at the start of each MPC iteration. This
480539
method can be overritten for specific models.
481540
"""
482541
pass
@@ -491,8 +550,8 @@ def create_query_file(self, horizon, period, final):
491550
:param horizon: The inval duration for which Uppaal stratego synthesizes a control strategy
492551
each MPC step. Is given in the number of periods.
493552
:type horizon: int
494-
:param period: The interval duration after which the controller can change the control setting,
495-
given in Uppaal Stratego time units.
553+
:param period: The interval duration after which the controller can change the control
554+
setting, given in Uppaal Stratego time units.
496555
:type period: int
497556
:param final: The time that should be reached by the synthesized strategy, given in Uppaal
498557
Stratego time units. Most likely this will be current time + *horizon* x *period*.
@@ -513,24 +572,26 @@ def run_verifyta(self, *args, **kwargs):
513572
:meth:`~SafeMPCSetup.run_verifyta` in :class:`~SafeMPCSetup`.
514573
:param `**kwargs`: Is not used in this method; it is used in the overriding method
515574
:meth:`~SafeMPCSetup.run_verifyta` in :class:`~SafeMPCSetup`.
575+
:return: The output generated by Uppaal Stratego.
576+
:rtype: str
516577
"""
517578
result = self.controller.run(queryfile=self.queryfile, learning_args=self.learning_args,
518-
verifyta_path=self.verifyta_command)
579+
verifyta_command=self.verifyta_command)
519580

520581
if self.controller.cleanup:
521582
self.controller.remove_simfile()
522583
return result
523584

524-
def extract_states_from_Stratego(self, result, controlperiod):
585+
def extract_states_from_stratego(self, result, controlperiod):
525586
"""
526587
Extract the new state values from the simulation output of Stratego.
527588
528589
The extracted values are directly saved in the :attr:`~MPCsetup.controller`.
529590
530591
:param result: The output as generated by Uppaal Stratego.
531592
:type result: str
532-
:param controlperiod: The interval duration after which the controller can change the control setting,
533-
given in Uppaal Stratego time units.
593+
:param controlperiod: The interval duration after which the controller can change the
594+
control setting, given in Uppaal Stratego time units.
534595
:type controlperiod: int
535596
"""
536597
new_state = {}
@@ -541,21 +602,22 @@ def extract_states_from_Stratego(self, result, controlperiod):
541602
new_state[var] = new_value
542603
self.controller.update_state(new_state)
543604

544-
def extract_control_action_from_Stratego(self, result):
605+
def extract_control_action_from_stratego(self, result):
545606
"""
546607
Extract the chosen control action for the first control period from the simulation output
547608
of Stratego.
548609
549610
:param result: The output as generated by Uppaal Stratego.
550611
:type result: str
551612
:return: The control action chosen for the first control period.
613+
:rtype: float
552614
"""
553615
float_re = r"[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?"
554616
pattern = self.action_variable + r":\n\[0\]:( \(" + float_re + "," + float_re + r"\))*"
555617
result = re.search(pattern, result)
556618
float_tuples = get_float_tuples(result.group())
557619
lastvalue = 0.0
558-
620+
559621
# The last tuple at time 0 represents the chosen control action.
560622
for t in float_tuples:
561623
if t[0] == 0:
@@ -588,7 +650,7 @@ def print_state_vars(self):
588650
printed to the standard output.
589651
"""
590652
content = self.controller.get_var_names_as_string() + "\n"
591-
if(self.output_file_path is None):
653+
if self.output_file_path is None:
592654
sys.stdout.write(content)
593655
else:
594656
with open(self.output_file_path, "w") as f:
@@ -600,7 +662,7 @@ def print_state(self):
600662
standard output.
601663
"""
602664
content = self.controller.get_state_as_string() + "\n"
603-
if(self.output_file_path is None):
665+
if self.output_file_path is None:
604666
sys.stdout.write(content)
605667
else:
606668
with open(self.output_file_path, "a") as f:
@@ -628,14 +690,14 @@ def run_verifyta(self, horizon, controlperiod, final, *args, **kwargs):
628690
:param horizon: The inval duration for which Uppaal stratego synthesizes a control strategy
629691
each MPC step. Is given in the number of periods.
630692
:type horizon: int
631-
:param period: The interval duration after which the controller can change the control setting,
632-
given in Uppaal Stratego time units.
633-
:type period: int
693+
:param controlperiod: The interval duration after which the controller can change the
694+
control setting, given in Uppaal Stratego time units.
695+
:type controlperiod: int
634696
:param final: The time that should be reached by the synthesized strategy, given in Uppaal
635697
Stratego time units. Most likely this will be current time + *horizon* x *period*.
636698
:type final: int
637-
:param `*args`: Is not used in this method; it is included here to safely override the original
638-
method.
699+
:param `*args`: Is not used in this method; it is included here to safely override the
700+
original method.
639701
:param `**kwargs`: Is not used in this method; it is included here to safely override the
640702
original method.
641703
"""
@@ -659,8 +721,8 @@ def create_alternative_query_file(self, horizon, period, final):
659721
:param horizon: The inval duration for which Uppaal stratego synthesizes a control strategy
660722
each MPC step. Is given in the number of periods.
661723
:type horizon: int
662-
:param period: The interval duration after which the controller can change the control setting,
663-
given in Uppaal Stratego time units.
724+
:param period: The interval duration after which the controller can change the control
725+
setting, given in Uppaal Stratego time units.
664726
:type period: int
665727
:param final: The time that should be reached by the synthesized strategy, given in Uppaal
666728
Stratego time units. Most likely this will be current time + *horizon* x *period*.

0 commit comments

Comments
 (0)