Exemplo n.º 1
0
    def test_synthesize(self):
        mach = synthesize(self.f_un)
        assert not isinstance(mach, MealyMachine)

        mach = synthesize(self.f)
        # There is more than one possible strategy realizing this
        # specification.  Checking only for one here makes this more like
        # a regression test (fragile).  However, it is more meaningful
        # than simply checking that synthesize() returns something
        # non-None (i.e., realizability, which is tested elsewhere).
        assert mach is not None
        assert len(mach.inputs) == 1 and mach.inputs.has_key("x")
        assert len(mach.outputs) == 1 and mach.outputs.has_key("y")
        assert len(mach.states()) == 6
        assert set(mach.transitions()) == set([(0, 1), (0, 2), (1, 3), (1, 4),
                                              (2, 3), (2, 4), (3, 0), (3, 3),
                                              (4, 0), (4, 3), ("Sinit", 0)])
        label_reference = {(0, 1) : (0,0),  # value is bitvector of x,y
                           (0, 2) : (1,0),
                           (1, 3) : (0,0),
                           (1, 4) : (1,0),
                           (2, 3) : (0,0),
                           (2, 4) : (1,0),
                           (3, 0) : (1,1),
                           (3, 3) : (0,0),
                           (4, 0) : (1,1),
                           (4, 3) : (0,0),
                           ("Sinit", 0) : (1,1)}
        for (from_state, to_state, slabel) in mach.transitions(data=True):
            assert label_reference[(from_state, to_state)] == (slabel["x"],
                                                               slabel["y"])
Exemplo n.º 2
0
def hash_question_mark_test():
    specs = GRSpec(env_vars={'w': ['low', 'medium', 'high']},
                   sys_vars={'a': (0, 2)},
                   env_init=['w="low"'],
                   env_safety=['(a=1) -> ((w="low") || (w="medium"))'],
                   env_prog=['(w="high")'],
                   sys_init=['a=2'],
                   sys_safety=['a=2'],
                   sys_prog=['a=2'])
    with nt.assert_raises(ValueError):
        jtlv.synthesize(specs)
Exemplo n.º 3
0
def hash_question_mark_test():
    specs = GRSpec(env_vars={'w': ['low', 'medium', 'high']},
                   sys_vars={'a': (0, 2)},

                    env_init=['w="low"'],
                    env_safety=['(a=1) -> ((w="low") || (w="medium"))'],
                    env_prog=['(w="high")'],

                    sys_init=['a=2'],
                    sys_safety=['a=2'],
                    sys_prog=['a=2'])
    with nt.assert_raises(ValueError):
        jtlv.synthesize(specs)
Exemplo n.º 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
Exemplo n.º 5
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
Exemplo n.º 6
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