6. Code generation and exporting of controllers¶
Besides the various routines for analysis and execution of controllers constructed with TuLiP, it is also possible to automatically generate implementations in formats appropriate for use in other contexts. We refer to this process as exporting. Here we provide descriptions and examples of the various exporting routines available.
6.1. python_case
¶
Given a Mealy machine (Sec. 3.3 in [LS11]) as would be obtained, for example, from an invocation of
tulip.synth.synthesize
, the function python_case
in tulip.dumpsmach
generates an implementation as a standalone Python class. The class implements
the machine by
tracking the current state of the machine and
providing a
move
method that accepts the input of the machine and returns the appropriate output as a dictionary in which the output variable names are keys.
Calls to move
cause the internal state to transition. The machine can be
reset to its initial state by manually calling the __init__
method or
effectively by creating a new instance. Note that the internal state is entirely
represented by the attribute state
. Thus it is possible to save a copy of
the current state of the machine and return to it later. E.g., the output that
would be obtained if some inputs were applied can be discovered by the following
idiom.
import copy
saved_state = copy.copy(M.state)
sample_outputs = M.move(**sample_inputs)
M.state = saved_state
The generated code does not depend on tulip
; that is, it can run without
TuLiP being installed. As such, we refer to it as being “standalone”.
6.1.1. Example¶
Consider the script examples/robot_planning/gr1.py
as distributed with
TuLiP. At the end of the script, there is an object named ctrl
that is an
instance of MealyMachine
. It represents the controller that was constructed
automatically (or “synthesized”) according to the specification. Append the
following code to the end of the script gr1.py
. (Alternatively, if IPython
is installed, then first run ipython -i gr1.py
, and then enter the
following.)
from tulip import dumpsmach
dumpsmach.write_python_case("gr1controller.py", ctrl, classname="ExampleCtrl")
The first line merely loads the dumpsmach
module. The second line calls a
function that, in turn, calls python_case
and saves the result to a file
named “gr1controller.py”. That file contains a class named “ExampleCtrl” that
implements ctrl
, as demonstrated by the following script.
from __future__ import print_function
from gr1controller import ExampleCtrl
M = ExampleCtrl()
print('In order, the input variables: '+', '.join(M.input_vars))
for i in range(10):
input_values = {"park": 0}
print(M.move(**input_values))
Alternatively, the above code can be modified by calling M.move
with the
input variable names as keyword parameters:
print(M.move(park=0))