def _run(default_models, is_moore, anon_inputs, anon_outputs, sync_automaton: Automaton, global_automatae_pairs, bounds, solver_creater: Z3SolverFactory, logic, logger) -> Bool: _log_automatae(logger, global_automatae_pairs, sync_automaton) if default_models: logger.info('model is given: checking it..') underlying_solver = solver_creater.create('_check') model_checker = par_model_searcher.ParModelSearcher() models = model_checker.check( logic, is_moore, global_automatae_pairs, sync_automaton, anon_inputs, anon_outputs, underlying_solver, BaseNames(SCHED_ID_PREFIX, ACTIVE_NAME, SENDS_NAME, SENDS_PREV_NAME, HAS_TOK_NAME), default_models[0]) underlying_solver.die() if models: logger.info('the model passed checking!') return models logger.info( 'the model did not pass the check - searching another one..') underlying_solver = solver_creater.create() model_searcher = par_model_searcher.ParModelSearcher() models = model_searcher.search( logic, is_moore, global_automatae_pairs, sync_automaton, anon_inputs, anon_outputs, bounds, underlying_solver, BaseNames(SCHED_ID_PREFIX, ACTIVE_NAME, SENDS_NAME, SENDS_PREV_NAME, HAS_TOK_NAME)) underlying_solver.die() return models
def check_unreal( ltl_text, part_text, is_moore, ltl3ba: LTL3BA, solver_factory: Z3SolverFactory, min_size, max_size, ltl3ba_timeout_sec=None, opt_level=0, ) -> LTS: """ :raise: subprocess.TimeoutException :arg opt_level: Note that opt_level > 0 may introduce unsoundness (returns unrealizable while it is) """ timer = Timer() outputs, inputs, expr = parse_acacia_and_build_expr(ltl_text, part_text, ltl3ba, opt_level) timer.sec_restart() automaton = ltl3ba.convert(expr, timeout=ltl3ba_timeout_sec) # note no negation logging.info("(unreal) automaton size is: %i" % len(automaton.nodes)) logging.debug("(unreal) automaton (dot) is:\n" + automaton2dot.to_dot(automaton)) logging.debug("(unreal) automaton translation took (sec): %i" % timer.sec_restart()) encoder = create_encoder(inputs, outputs, not is_moore, automaton, solver_factory.create()) model = model_searcher.search(min_size, max_size, encoder) logging.debug("(unreal) model_searcher.search took (sec): %i" % timer.sec_restart()) return model
def _run(default_models, is_moore, anon_inputs, anon_outputs, sync_automaton:Automaton, global_automatae_pairs, bounds, solver_creater:Z3SolverFactory, logic, logger) -> Bool: _log_automatae(logger, global_automatae_pairs, sync_automaton) if default_models: logger.info('model is given: checking it..') underlying_solver = solver_creater.create('_check') model_checker = par_model_searcher.ParModelSearcher() models = model_checker.check(logic, is_moore, global_automatae_pairs, sync_automaton, anon_inputs, anon_outputs, underlying_solver, BaseNames(SCHED_ID_PREFIX, ACTIVE_NAME, SENDS_NAME, SENDS_PREV_NAME, HAS_TOK_NAME), default_models[0]) underlying_solver.die() if models: logger.info('the model passed checking!') return models logger.info('the model did not pass the check - searching another one..') underlying_solver = solver_creater.create() model_searcher = par_model_searcher.ParModelSearcher() models = model_searcher.search(logic, is_moore, global_automatae_pairs, sync_automaton, anon_inputs, anon_outputs, bounds, underlying_solver, BaseNames(SCHED_ID_PREFIX, ACTIVE_NAME, SENDS_NAME, SENDS_PREV_NAME, HAS_TOK_NAME)) underlying_solver.die() return models
def check_real(spec: Spec, min_size, max_size, ltl_to_atm: LTLToAutomaton, solver_factory: Z3SolverFactory, use_direct_encoding: bool) -> LTS or None: shared_aht, dstFormPropMgr = SharedAHT(), DstFormulaPropMgr() # normalize formula (negations appear only in front of basic propositions) spec.formula = NNFNormalizer().dispatch(spec.formula) logging.info("CTL* formula size: %i", expr_size(spec.formula)) if use_direct_encoding: top_formula, atm_by_p, UCWs = automize_ctl(spec.formula, ltl_to_atm) logging.info("Total number of states in sub-automata: %i", sum([len(a.nodes) for a in atm_by_p.values()])) for p, atm in atm_by_p.items(): logging.debug(str(p) + ', atm: \n' + automaton_to_dot.to_dot(atm)) encoder = CTLEncoderDirect( top_formula, atm_by_p, UCWs, build_tau_desc(spec.inputs), spec.inputs, dict((o, build_output_desc(o, True, spec.inputs)) for o in spec.outputs), range(max_size)) else: aht_automaton = ctl2aht.ctl2aht(spec, ltl_to_atm, shared_aht, dstFormPropMgr) aht_nodes, aht_transitions = get_reachable_from( aht_automaton.init_node, shared_aht.transitions, dstFormPropMgr) logging.info('The AHT automaton size (nodes/transitions) is: %i/%i' % (len(aht_nodes), len(aht_transitions))) if not aht_transitions: logging.info('AHT is empty => the spec is unrealizable!') return None if logging.getLogger().isEnabledFor( logging.DEBUG): # aht2dot takes long time logging.debug('AHT automaton (dot) is...\n') logging.debug( aht2dot.convert(aht_automaton, shared_aht, dstFormPropMgr)) encoder = CTLEncoderViaAHT( aht_automaton, aht_transitions, dstFormPropMgr, build_tau_desc(spec.inputs), spec.inputs, dict((o, build_output_desc(o, True, spec.inputs)) for o in spec.outputs), range(max_size)) model = model_searcher.search(min_size, max_size, encoder, solver_factory.create()) return model
def check_real( ltl_text, part_text, is_moore, ltl3ba, solver_factory: Z3SolverFactory, min_size, max_size, opt_level=2 ) -> LTS: """ :param opt_level: values > 0 introduce incompleteness (but it is sound: if returns REAL, then REAL) """ timer = Timer() inputs, outputs, expr = parse_acacia_and_build_expr(ltl_text, part_text, ltl3ba, opt_level) timer.sec_restart() automaton = ltl3ba.convert(~expr) logging.info("(real) automaton size is: %i" % len(automaton.nodes)) logging.debug("(real) automaton (dot) is:\n" + automaton2dot.to_dot(automaton)) logging.debug("(real) automaton translation took (sec): %i" % timer.sec_restart()) encoder = create_encoder(inputs, outputs, is_moore, automaton, solver_factory.create()) model = model_searcher.search(min_size, max_size, encoder) logging.debug("(real) model_searcher.search took (sec): %i" % timer.sec_restart()) return model
parser.add_argument('--maxsize', metavar='maxsize', type=int, default=4, required=False, help='stop at this size') parser.add_argument('-v', '--verbose', action='count', default=0) args = parser.parse_args() assert args.minsize <= args.maxsize logger = setup_logging(args.verbose) logger.info(args) with tempfile.NamedTemporaryFile(dir='./') as smt_file: smt_files_prefix = smt_file.name ltl_to_automaton = translator_via_spot.LTLToAtmViaSpot() solver_factory = Z3SolverFactory(smt_files_prefix, Z3_PATH, # we don't really need this False, True, True) elli.check_real(readfile(args.spec), readfile(args.spec.replace('.ltl', '.part')), args.moore, ltl_to_automaton, solver_factory.create(), 0, args.minsize, args.maxsize) solver_factory.down_solvers() exit(0)
def main(): parser = argparse.ArgumentParser( description='Bounded Synthesis Tool', formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument('spec', metavar='spec', type=str, help='the specification file (Acacia or TLSF format)') gr = parser.add_mutually_exclusive_group() gr.add_argument('--moore', action='store_true', default=True, dest='moore', help='system is Moore (ignored for TLSF)') gr.add_argument('--mealy', action='store_false', default=False, dest='moore', help='system is Mealy (ignored for TLSF)') gr = parser.add_mutually_exclusive_group() gr.add_argument('--spot', action='store_true', default=True, dest='spot', help='use SPOT for translating LTL->BA') gr.add_argument('--ltl3ba', action='store_false', default=False, dest='spot', help='use LTL3BA for translating LTL->BA') parser.add_argument( '--maxK', type=int, default=0, help="reduce liveness to co-reachability (safety)." "This sets the upper bound on the number of 'bad' visits." "We iterate over increasing k (exact value of k is set heuristically)." "(k=0 means no reduction)") gr = parser.add_mutually_exclusive_group() gr.add_argument( '--bound', metavar='bound', type=int, default=32, required=False, help= 'upper bound on the size of the model (for unreal this specifies size of env model)' ) gr.add_argument( '--size', metavar='size', type=int, default=0, required=False, help= 'search the model of this size (for unreal this specifies size of env model)' ) parser.add_argument('--incr', action='store_true', required=False, default=False, help='use incremental solving') parser.add_argument('--tmp', action='store_true', required=False, default=False, help='keep temporary smt2 files') parser.add_argument('--dot', metavar='dot', type=str, required=False, help='write the output into a dot graph file') parser.add_argument('--log', metavar='log', type=str, required=False, default=None, help='name of the log file') parser.add_argument( '--unreal', action='store_true', required=False, help='simple check of unrealizability: ' 'invert the spec, system type, (in/out)puts, ' 'and synthesize the model for env ' '(note that the inverted spec will NOT be strengthened)') parser.add_argument('-v', '--verbose', action='count', default=0) args = parser.parse_args() setup_logging(args.verbose, args.log) logging.info(args) if args.incr and args.tmp: logging.warning( "--tmp --incr: incremental queries do not produce smt2 files, " "so I won't save any temporal files.") with tempfile.NamedTemporaryFile(dir='./') as smt_file: smt_files_prefix = smt_file.name ltl_to_automaton = (translator_via_ltl3ba.LTLToAtmViaLTL3BA, translator_via_spot.LTLToAtmViaSpot)[args.spot]() solver_factory = Z3SolverFactory(smt_files_prefix, Z3_PATH, args.incr, False, not args.tmp) if args.size == 0: min_size, max_size = 1, args.bound else: min_size, max_size = args.size, args.size ltl_text, part_text, is_moore = convert_tlsf_or_acacia_to_acacia( args.spec, args.moore) if args.unreal: model = check_unreal(ltl_text, part_text, is_moore, ltl_to_automaton, solver_factory.create(), args.maxK, min_size, max_size) else: model = check_real(ltl_text, part_text, is_moore, ltl_to_automaton, solver_factory.create(), args.maxK, min_size, max_size) if not model: logging.info('model NOT FOUND') else: logging.info('FOUND model for {who} of size {size}'.format( who=('sys', 'env')[args.unreal], size=len(model.states))) if model: dot_model_str = lts_to_dot(model, ARG_MODEL_STATE, (not is_moore) ^ args.unreal) if args.dot: with open(args.dot, 'w') as out: out.write(dot_model_str) logging.info('{model_type} model is written to {file}'.format( model_type=['Mealy', 'Moore'][is_moore], file=out.name)) else: logging.info(dot_model_str) solver_factory.down_solvers() return UNKNOWN_RC if model is None else (REALIZABLE_RC, UNREALIZABLE_RC)[args.unreal]
def main(): """ :return: 1 if model is found, 0 otherwise """ parser = argparse.ArgumentParser( description='Bounded Synthesizer for CTL*', formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument('spec', metavar='spec', type=str, help='the specification file (in python format)') group = parser.add_mutually_exclusive_group() group.add_argument( '--bound', metavar='bound', type=int, default=128, required=False, help= 'upper bound on the size of the model (for unreal this specifies size of env model)' ) group.add_argument( '--size', metavar='size', type=int, default=0, required=False, help= 'search the model of this size (for unreal this specifies size of env model)' ) group = parser.add_mutually_exclusive_group() group.add_argument('--direct', action='store_true', default=True, dest='direct', help='use direct encoding') group.add_argument('--aht', action='store_false', default=False, dest='direct', help='encode via AHT') parser.add_argument('--incr', action='store_true', required=False, default=False, help='use incremental solving') parser.add_argument('--tmp', action='store_true', required=False, default=False, help='keep temporary smt2 files') parser.add_argument('--dot', metavar='dot', type=str, required=False, help='write the output into a dot graph file') parser.add_argument('--aiger', metavar='aiger', type=str, required=False, help='write the output into an AIGER format') parser.add_argument('--log', metavar='log', type=str, required=False, default=None, help='name of the log file') parser.add_argument('-v', '--verbose', action='count', default=0) args = parser.parse_args() setup_logging(args.verbose, args.log) logging.info(args) if args.incr and args.tmp: logging.warning( "--tmp --incr: incremental queries do not produce smt2 files, " "so I won't save any temporal files.") with tempfile.NamedTemporaryFile(dir='./') as smt_file: smt_files_prefix = smt_file.name ltl_to_atm = translator_via_spot.LTLToAtmViaSpot() solver_factory = Z3SolverFactory(smt_files_prefix, Z3_PATH, args.incr, False, not args.tmp) if args.size == 0: min_size, max_size = 1, args.bound else: min_size, max_size = args.size, args.size spec = parse_python_spec(args.spec) model = check_real(spec, min_size, max_size, ltl_to_atm, solver_factory, args.direct) logging.info('{status} model for {who}'.format( status=('FOUND', 'NOT FOUND')[model is None], who='sys')) if model: dot_model_str = lts_to_dot(model, ARG_MODEL_STATE, False) if args.dot: with open(args.dot, 'w') as out: out.write(dot_model_str) logging.info( 'Moore model is written to {file}'.format(file=out.name)) else: logging.info(dot_model_str) if args.aiger: with open(args.aiger, 'w') as aiger_out: aiger_out.write(lts_to_aiger(model)) solver_factory.down_solvers() return UNKNOWN if model is None else REALIZABLE