def test_synthesize(self): self.f_un.sys_safety = [] # Make it realizable g = gr1c.synthesize(self.f_un, init_option="ALL_ENV_EXIST_SYS_INIT") assert g is not None assert len(g.env_vars) == 1 and 'x' in g.env_vars assert len(g.sys_vars) == 1 and 'y' in g.sys_vars g = gr1c.synthesize(self.dcounter, init_option="ALL_ENV_EXIST_SYS_INIT") assert g is not None assert len(g.env_vars) == 0 assert len(g.sys_vars) == 1 and 'y' in g.sys_vars assert len(g) == 2 # In the notation of gr1c SYSINIT: True;, so the strategy must # account for every initial state, i.e., for y=0, y=1, y=2, ... self.dcounter.sys_init = [] g = gr1c.synthesize(self.dcounter, init_option="ALL_INIT") assert g is not None print g assert len(g.env_vars) == 0 assert len(g.sys_vars) == 1 and 'y' in g.sys_vars assert len(g) == 6
def test_synthesize(self): self.f_un.sys_safety = list() # Make it realizable g = gr1c.synthesize(self.f_un) assert g is not None assert len(g.env_vars) == 1 and 'x' in g.env_vars assert len(g.sys_vars) == 1 and 'y' in g.sys_vars g = gr1c.synthesize(self.dcounter) assert g is not None assert len(g.env_vars) == 0 assert len(g.sys_vars) == 1 and 'y' in g.sys_vars assert len(g) == 2 # In the notation of gr1c SYSINIT: True;, so the strategy must # account for every initial state, i.e., for y=0, y=1, y=2, ... self.dcounter.qinit = '\A \A' self.dcounter.sys_init = list() g = gr1c.synthesize(self.dcounter) assert g is not None print g assert len(g.env_vars) == 0 assert len(g.sys_vars) == 1 and 'y' in g.sys_vars assert len(g) == 6, len(g)
def test_synthesize(self): self.f_un.sys_safety = list() # Make it realizable g = gr1c.synthesize(self.f_un) assert g is not None assert len(g.env_vars) == 1 and 'x' in g.env_vars assert len(g.sys_vars) == 1 and 'y' in g.sys_vars g = gr1c.synthesize(self.dcounter) assert g is not None assert len(g.env_vars) == 0 assert len(g.sys_vars) == 1 and 'y' in g.sys_vars assert len(g) == 2 # In the notation of gr1c SYSINIT: True;, so the strategy must # account for every initial state, i.e., for y=0, y=1, y=2, ... self.dcounter.qinit = '\A \A' self.dcounter.sys_init = list() g = gr1c.synthesize(self.dcounter) assert g is not None print(g) assert len(g.env_vars) == 0 assert len(g.sys_vars) == 1 and 'y' in g.sys_vars assert len(g) == 6, len(g)
def synthesize( option, specs, env=None, sys=None, ignore_env_init=False, ignore_sys_init=False, bool_states=False, action_vars=None, bool_actions=False ): """Function to call the appropriate synthesis tool on the specification. Beware! This function provides a generic interface to a variety of routines. Being under active development, the types of arguments supported and types of objects returned may change without notice. @param option: Magic string that declares what tool to invoke, what method to use, etc. Currently recognized forms: - C{"gr1c"}: use gr1c for GR(1) synthesis via L{interfaces.gr1c}. - C{"jtlv"}: use JTLV for GR(1) synthesis via L{interfaces.jtlv}. @type specs: L{spec.GRSpec} @param env: A transition system describing the environment: - states controlled by environment - input: sys_actions - output: env_actions - initial states constrain the environment This constrains the transitions available to the environment, given the outputs from the system. Note that an L{OpenFTS} with only sys_actions is equivalent to an L{FTS} for the environment. @type env: L{transys.FTS} or L{transys.OpenFTS} @param sys: A transition system describing the system: - states controlled by the system - input: env_actions - output: sys_actions - initial states constrain the system Note that an OpenFTS with only sys_actions is equivalent to an FTS for the system. @type sys: L{transys.FTS} L{transys.OpenFTS} @param ignore_sys_init: Ignore any initial state information contained in env. @type ignore_sys_init: bool @param ignore_env_init: Ignore any initial state information contained in sys. @type ignore_env_init: bool @param bool_states: if True, then use one bool variable for each state. Otherwise use a single int variable for all states. Currently int state implemented only for gr1c. @type bool_states: bool @param action_vars: for the integer variables modeling environment and system actions in GR(1). Effective only when >2 actions for each player. @type action_vars: 2-tuple of str: (env_action_var_name, sys_action_var_name) Default: ('eact', 'act') (must be valid variable name) @param bool_actions: model actions using bool variables @type bool_actions: bool @return: If spec is realizable, then return a Mealy machine implementing the strategy. Otherwise return None. @rtype: L{transys.MealyMachine} or None """ bool_states, action_vars, bool_actions = _check_solver_options( option, bool_states, action_vars, bool_actions ) specs = spec_plus_sys(specs, env, sys, ignore_env_init, ignore_sys_init, bool_states, action_vars, bool_actions) if option == 'gr1c': ctrl = gr1c.synthesize(specs) elif option == 'jtlv': ctrl = jtlv.synthesize(specs) else: raise Exception('Undefined synthesis option. '+\ 'Current options are "jtlv" and "gr1c"') try: logger.debug('Mealy machine has: n = ' + str(len(ctrl.states) ) +' states.') except: logger.debug('No Mealy machine returned.') # no controller found ? # exploring unrealizability with counterexamples or other means # can be done by calling a dedicated other function, not this if not isinstance(ctrl, transys.MealyMachine): return None return ctrl
def synth_init_illegal_check(init_option): spc = GRSpec(moore=False, plus_one=False, qinit=init_option) gr1c.synthesize(spc)
def synth_init_illegal_check(init_option): spc = GRSpec() gr1c.synthesize(spc, init_option=init_option)
def synthesize_many(specs, ts=None, ignore_init=None, bool_actions=None, solver='gr1c'): """Synthesize from logic specs and multiple transition systems. The transition systems are composed synchronously, i.e., they all have to take a transition at each time step. The synchronous composition is obtained by taking the conjunction of the formulas describing each transition system. The states of each transition system can be either: - all integers, or - all strings In either case the transition system state will be represented in logic with a single variable, that ranges over a finite set of integers or strings, respectively. The keys of C{ts} are used to name each state variable. So the logic formula for C{ts['name']} will be C{'name'}. Who controls this state variable is determined from the attribute C{FTS.owner} that can take the values: - C{'env'} - C{'sys'} For example: >>> ts.states.add_from(xrange(4)) >>> ts['door'].owner = 'env' will result in a logic formula with an integer variable C{'door'} controlled by the environment and taking values over C{{0, 1, 2, 3}}. The example: >>> ts.states.add_from(['a', 'b', 'c']) >>> ts['door'].owner = 'sys' will instead result in a string variable C{'door'} controlled by the system and taking values over C{{'a', 'b', 'c'}}. @type specs: L{GRSpec} @type ts: C{dict} of L{FiniteTransitionSystem} @type ignore_init: C{set} of keys from C{ts} @type bool_actions: C{set} of keys from C{ts} @param solver: 'gr1c' or 'slugs' or 'jtlv' @type solver: str """ assert isinstance(ts, dict) for name, t in ts.iteritems(): assert isinstance(t, transys.FiniteTransitionSystem) ignore = name in ignore_init bool_act = name in bool_actions statevar = name if t.owner == 'sys': specs |= sys_to_spec(t, ignore, statevar, bool_actions=bool_act) elif t.owner == 'env': specs |= env_to_spec(t, ignore, statevar, bool_actions=bool_act) if solver == 'gr1c': ctrl = gr1c.synthesize(specs) elif solver == 'slugs': if slugs is None: raise ValueError('Import of slugs interface failed. ' + 'Please verify installation of "slugs".') ctrl = slugs.synthesize(specs) elif solver == 'jtlv': ctrl = jtlv.synthesize(specs) else: raise Exception('Unknown solver: ' + str(solver) + '. ' 'Available solvers: "jtlv", "gr1c", and "slugs"') try: logger.debug('Mealy machine has: n = ' + str(len(ctrl.states)) + ' states.') except: logger.debug('No Mealy machine returned.') # no controller found ? # counterstrategy not constructed by synthesize if not isinstance(ctrl, transys.MealyMachine): return None ctrl.remove_deadends() return ctrl
def synthesize( option, specs, env=None, sys=None, ignore_env_init=False, ignore_sys_init=False, bool_states=False, bool_actions=False, rm_deadends=True ): """Function to call the appropriate synthesis tool on the specification. The states of the transition system can be either: - all integers, or - all strings For more details of how the transition system is represented in logic look at L{synthesize_many}. Beware! ======= This function provides a generic interface to a variety of routines. Being under active development, the types of arguments supported and types of objects returned may change without notice. @param option: Magic string that declares what tool to invoke, what method to use, etc. Currently recognized forms: - C{"gr1c"}: use gr1c for GR(1) synthesis via L{interfaces.gr1c}. - C{"slugs"}: use slugs for GR(1) synthesis via L{interfaces.slugs}. - C{"jtlv"}: use JTLV for GR(1) synthesis via L{interfaces.jtlv}. @type specs: L{spec.GRSpec} @param env: A transition system describing the environment: - states controlled by environment - input: sys_actions - output: env_actions - initial states constrain the environment This constrains the transitions available to the environment, given the outputs from the system. @type env: L{FTS} @param sys: A transition system describing the system: - states controlled by the system - input: env_actions - output: sys_actions - initial states constrain the system @type sys: L{FTS} @param ignore_env_init: Ignore any initial state information contained in env. @type ignore_env_init: bool @param ignore_sys_init: Ignore any initial state information contained in sys. @type ignore_sys_init: bool @param bool_states: deprecated as inefficient if True, then use one bool variable for each state. Otherwise use a single integer variable for all states. @type bool_states: bool @param bool_actions: model actions using bool variables, otherwise use integers. @type bool_actions: bool @param rm_deadends: return a strategy that contains no terminal states. @type rm_deadends: bool @return: If spec is realizable, then return a Mealy machine implementing the strategy. Otherwise return None. @rtype: L{MealyMachine} or None """ specs = _spec_plus_sys( specs, env, sys, ignore_env_init, ignore_sys_init, bool_states, bool_actions) if option == 'gr1c': strategy = gr1c.synthesize(specs) elif option == 'slugs': if slugs is None: raise ValueError('Import of slugs interface failed. ' + 'Please verify installation of "slugs".') strategy = slugs.synthesize(specs) elif option == 'jtlv': strategy = jtlv.synthesize(specs) else: raise Exception('Undefined synthesis option. ' + 'Current options are "jtlv", "gr1c", and "slugs"') ctrl = strategy2mealy(strategy, specs) try: logger.debug('Mealy machine has: n = ' + str(len(ctrl.states)) + ' states.') except: logger.debug('No Mealy machine returned.') # no controller found ? # exploring unrealizability with counterexamples or other means # can be done by calling a dedicated other function, not this if not isinstance(ctrl, transys.MealyMachine): return None if rm_deadends: ctrl.remove_deadends() return ctrl
def synth_init_illegal_test(init_option): with pytest.raises(ValueError): spc = GRSpec(moore=False, plus_one=False, qinit=init_option) gr1c.synthesize(spc)