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 ) ) )")
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 ) ) )")
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')
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')
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