Beispiel #1
0
    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
Beispiel #2
0
    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)
Beispiel #3
0
    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)
Beispiel #4
0
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
Beispiel #5
0
def synth_init_illegal_check(init_option):
    spc = GRSpec(moore=False, plus_one=False, qinit=init_option)
    gr1c.synthesize(spc)
Beispiel #6
0
def synth_init_illegal_check(init_option):
    spc = GRSpec()
    gr1c.synthesize(spc, init_option=init_option)
Beispiel #7
0
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
Beispiel #8
0
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
Beispiel #9
0
def synth_init_illegal_test(init_option):
    with pytest.raises(ValueError):
        spc = GRSpec(moore=False, plus_one=False, qinit=init_option)
        gr1c.synthesize(spc)
Beispiel #10
0
def synth_init_illegal_check(init_option):
    spc = GRSpec(moore=False, plus_one=False, qinit=init_option)
    gr1c.synthesize(spc)