LydiaSyft
|
LydiaSyft can be used as a C++ library that integrates with other project. In this page we will walk through each example and explain the main features supported by the library. The examples can be found in the examples/
folder.
In this example, we will see how to use the LydiaSyft C++ APIs to solve an instance of the LTLf synthesis problem in the classical setting.
The code for this example can be found in examples/01_quickstart/quickstart.cpp
. To build this example, you can run make quickstart_example
.
The content of the file quickstart.cpp
is:
The expected output of the program is:
Below we break down each step of the program. The first step is to define the LTLf formula, the set of controllable (or output) variables, and the set of uncontrollable (or input) variables:
Next, we need to parse the formula string and build the syntax tree of the formula. To do so, we rely on Lydia library that provides a parser for LTLf formulas. In particular, we instantiate the parser whitemech::lydia::parsers::ltlf::LTLfDriver
, which can be found in the header <lydia/parser/ltlf/driver.hpp>
.
We also instantiate a variable manager, i.e. an instance of the class Syft::VarMgr
. The definition of such class can be found in the header file VarMgr.h
. Essentially, Syft::VarMgr
is a wrapper of the CUDD BDD manager, and provides auxiliary fields and methods specific for LTLf synthesis. The class Syft::InputOutputPartition
is simply a container class for the input and output variables, and can be found in the header file game/InputOutputPartition.h
.
Before calling the LTLf synthesis procedure, we have to build the DFA of the input LTLf formula. To do so, we rely on the static function Syft::ExplicitStateDfa::dfa_of_formula()
, which can be found in the header file automata/ExplicitStateDfa.h
:
The output of the Lydia tool is a MONA DFA (see the MONA manual for more information). To proceed, we require to translate the MONA DFA into a DFA based on Algebraic Decision Diagrams (ADD), i.e. a DFA with explicit states (as the MONA DFA), but with the symbolic transitions represented in ADDs (instead of Shared Multi-terminal BDDs). The class that implements this DFA representation is ExplicitStateDfaAdd
, and the function Syft::ExplicitStateDfaAdd::from_dfa_mona
performs such construction. The declaration of the class Syft::ExplicitStateDfaAdd
can be found in the header file automata/ExplicitStateDfaAdd.h
:
LydiaSyft requires the DFA to be _(fully) symbolic_, i.e. with symbolic states and transitions. The class that implements the symbolic DFA representation is SymbolicStateDfa
. To build a SymbolicStateDfa
from an ExplicitStateDfaAdd
, we use the function Syft::SymbolicStateDfa::from_explicit
. The declaration of the class Syft::SymbolicStateDfa
can be found in the header file automata/SymbolicStateDfa.h
:
Finally, we are ready to perform the synthesis step. First, we setup the variable manager to partition the variables in the input and output sets:
Then, we create an instance of Syft::LTLfSynthesizer
(found in synthesizer/LTLfSynthesizer.h
), a functor class that wraps the initialization and the execution of the synthesis procedure.
The constructor of Syft::LTLfSynthesizer
takes the following parameters:
spec
: A symbolic-state DFA representing the LTLf formula.starting_player
: The player that moves first each turn.protagonist_player
: The player for which we aim to find the winning strategy.goal_states
: The set of states that the agent must reach to win.state_space
: The state space.In our case, we have that the player Agent
is both the starting player and the protagonist agent. The goal states are the final states of the DFA, and the states space is the entire DFA (hence we use the CUDD expression for "true": var_mgr->cudd_mgr()->bddOne()
).
To run the synthesis procedure, we use:
The Syft::SynthesisResult
object contains all the details of the solution found, if any:
The field realizability
is set to true
if a solution is found, false
otherwise. Then, if realizability
is true
:
winning_states
is a BDD representing the set of states that are winning;winning_moves
is a BDD representing the set of winning moves;transducer
is an instance of the class Transducer
, which represents the winning strategy;safe_states
is set only in case of GR(1)
synthesis (we can ignore it now).