Beispiel #1
0
def isinit_test(self, no_str):
    self.str_to_int()
    init = {'env': self.env_init, 'sys': self.sys_init}
    pyinit = dict()
    for side, clauses in init.items():
        if no_str:
            clauses = [self._bool_int[x] for x in clauses]
        logger.info('clauses to compile: ' + str(clauses))
        c = [
            ts.translate_ast(self.ast(x), 'python').flatten() for x in clauses
        ]
        logger.info('after translation to python: ' + str(c))
        s = _conj(c, op='and')
        if not s:
            s = 'True'
        pyinit[side] = s
    # Do the conjunction of assumptions (env_init) and assertions (sys_init)
    s = '({assumption}) and ({assertion})'.format(assumption=pyinit['env'],
                                                  assertion=pyinit['sys'])
    # The original code looked like this. Every state was considered a valid
    # initial state if not (env_init) or (sys_init)
    #    s = 'not ({assumption}) or ({assertion})'.format(
    #        assumption=pyinit['env'],
    #        assertion=pyinit['sys'])
    logger.info(
        'should be valid in initial states: {formula}'.format(formula=s))
    return compile(s, '<string>', 'eval')
def test_translate_ast_to_gr1c():
    x = '(loc = "s2") -> X((((env_alice = "left") && (env_bob = "bright"))))'
    s = spec.GRSpec(sys_vars={'loc': ['s0', 's2'],
                              'env_alice': ['left', 'right'],
                              'env_bob': ['bleft', 'bright']},
                    sys_safety=[x])
    s.str_to_int()
    sint = s._bool_int[x]
    print(repr(sint))
    rint = s.ast(sint)
    print(repr(rint))
    r = ts.translate_ast(rint, 'gr1c')
    print(repr(r))
    print(r.flatten())
    assert r.flatten() == ("( ( loc = 1 ) -> "
                           "( ( env_alice' = 0 ) & ( env_bob' = 1 ) ) )")
Beispiel #3
0
def test_translate_ast_to_gr1c():
    x = '(loc = "s2") -> X((((env_alice = "left") && (env_bob = "bright"))))'
    s = spec.GRSpec(sys_vars={
        'loc': ['s0', 's2'],
        'env_alice': ['left', 'right'],
        'env_bob': ['bleft', 'bright']
    },
                    sys_safety=[x])
    s.str_to_int()
    sint = s._bool_int[x]
    print(repr(sint))
    rint = s.ast(sint)
    print(repr(rint))
    r = ts.translate_ast(rint, 'gr1c')
    print(repr(r))
    print(r.flatten())
    assert r.flatten() == ("( ( loc = 1 ) -> "
                           "( ( env_alice' = 0 ) & ( env_bob' = 1 ) ) )")
Beispiel #4
0
    def compile_init(self, no_str):
        """Compile python expression for initial conditions.

        The returned bytecode can be used with C{eval}
        and a C{dict} assigning values to variables.
        Its value is the implication

            C{env_init => sys_init}

        Use the corresponding python data types
        for the C{dict} values:

              - C{bool} for Boolean variables
              - C{int} for integers
              - C{str} for arbitrary finite types

        @param no_str: if True, then compile the formula
            where all string variables have been replaced by integers.
            Otherwise compile the original formula containing strings.

        @return: python expression compiled for C{eval}
        @rtype: C{code}
        """
        self.str_to_int()
        init = {'env': self.env_init, 'sys': self.sys_init}
        pyinit = dict()
        for side, clauses in init.items():
            if no_str:
                clauses = [self._bool_int[x] for x in clauses]
            logger.info('clauses to compile: ' + str(clauses))
            c = [
                ts.translate_ast(self.ast(x), 'python').flatten()
                for x in clauses
            ]
            logger.info('after translation to python: ' + str(c))
            s = _conj(c, op='and')
            if not s:
                s = 'True'
            pyinit[side] = s
        s = 'not ({assumption}) or ({assertion})'.format(
            assumption=pyinit['env'], assertion=pyinit['sys'])
        return compile(s, '<string>', 'eval')
Beispiel #5
0
    def compile_init(self, no_str):
        """Compile python expression for initial conditions.

        The returned bytecode can be used with C{eval}
        and a C{dict} assigning values to variables.
        Its value is the conjunction of C{env_init} and C{sys_init}.

        Use the corresponding python data types
        for the C{dict} values:

              - C{bool} for Boolean variables
              - C{int} for integers
              - C{str} for arbitrary finite types

        @param no_str: if True, then compile the formula
            where all string variables have been replaced by integers.
            Otherwise compile the original formula containing strings.

        @return: python expression compiled for C{eval}
        @rtype: C{code}
        """
        self.str_to_int()
        init = {'env': self.env_init, 'sys': self.sys_init}
        pyinit = dict()
        for side, clauses in init.iteritems():
            if no_str:
                clauses = [self._bool_int[x] for x in clauses]
            logger.info('clauses to compile: ' + str(clauses))
            c = [ts.translate_ast(self.ast(x), 'python').flatten()
                 for x in clauses]
            logger.info('after translation to python: ' + str(c))
            s = _conj(c, op='and')
            if not s:
                s = 'True'
            pyinit[side] = s
        s = 'not ({assumption}) or ({assertion})'.format(
            assumption=pyinit['env'],
            assertion=pyinit['sys'])
        return compile(s, '<string>', 'eval')
Beispiel #6
0
def synthesize(formula, env_vars=None, sys_vars=None):
    """Return Moore transducer if C{formula} is realizable.

    Variable C{dict}s have variable names as keys and their type as
    value. The types should be 'boolean'. These parameters are only
    used if formula is of type C{str}. Else, the variable dictionaries
    associated with the L{LTL} or L{GRSpec} object are used.

    @param formula: linear temporal logic formula
    @type formula: C{str}, L{LTL}, or L{GRSpec}

    @param env_vars: uncontrolled variables (inputs); used only if
        C{formula} is of type C{str}
    @type env_vars: C{dict} or None

    @param sys_vars: controlled variables (outputs); used only if
        C{formula} is of type C{str}
    @type sys_vars: C{dict} or None

    @return: symbolic Moore transducer
        (guards are conjunctions, not sets)
    @rtype: L{MooreMachine}
    """
    if isinstance(formula, GRSpec):
        env_vars = formula.env_vars
        sys_vars = formula.sys_vars
    elif isinstance(formula, LTL):
        env_vars = formula.input_variables
        sys_vars = formula.output_variables

    all_vars = dict(env_vars)
    all_vars.update(sys_vars)
    if not all(v == 'boolean' for v in all_vars.itervalues()):
        raise TypeError(
            'all variables should be Boolean:\n{v}'.format(v=all_vars))

    if isinstance(formula, GRSpec):
        f = translate(formula, 'wring')
    else:
        T = parse(str(formula))
        f = translate_ast(T, 'wring').flatten(env_vars=env_vars,
                                              sys_vars=sys_vars)

    # dump partition file
    s = '.inputs {inp}\n.outputs {out}'.format(
        inp=' '.join(env_vars),
        out=' '.join(sys_vars)
    )
    with open(IO_PARTITION_FILE, 'w') as fid:
        fid.write(s)

    # call lily
    try:
        p = subprocess.Popen([LILY, '-f', f, '-syn', IO_PARTITION_FILE],
                             stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        out = p.stdout.read()
    except OSError as e:
        if e.errno == os.errno.ENOENT:
            raise Exception(
                'lily.pl not found in path.\n'
                'See the Lily docs for setting PERL5LIB and PATH.')
        else:
            raise

    dotf = open(DOTFILE, 'r')
    fail_msg = 'Formula is not realizable'
    if dotf.read(len(fail_msg)) == fail_msg:
        return None
    dotf.seek(0)
    g = nx.read_dot(dotf)
    dotf.close()
    moore = lily_strategy2moore(g, env_vars, sys_vars)
    return moore