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 check_real(ltl_text, part_text, is_moore, ltl_to_atm: LTLToAutomaton, solver: SolverInterface, max_k: int, min_size, max_size, opt_level=0) -> LTS: """ When opt_level>0, introduce incompleteness (but it is sound: if returns REAL, then REAL) When max_k>0, reduce UCW to k-UCW. """ timer = Timer() spec = parse_acacia_and_build_expr(ltl_text, part_text, ltl_to_atm, opt_level) logging.info("LTL formula size: %i", expr_size(spec.formula)) timer.sec_restart() automaton = ltl_to_atm.convert(~spec.formula) logging.info('automaton size is: %i' % len(automaton.nodes)) logging.debug('automaton (dot) is:\n' + automaton_to_dot.to_dot(automaton)) logging.debug('automaton translation took (sec): %i' % timer.sec_restart()) tau_desc = build_tau_desc(spec.inputs) desc_by_output = dict( (o, build_output_desc(o, is_moore, spec.inputs)) for o in spec.outputs) if max_k == 0: logging.info("using CoBuchiEncoder") encoder = CoBuchiEncoder(automaton, tau_desc, spec.inputs, desc_by_output, range(max_size)) model = model_searcher.search(min_size, max_size, encoder, solver) else: coreach_automaton = k_reduce(automaton, max_k) # with open('/tmp/orig.dot', 'w') as f: # f.write(automaton_to_dot.to_dot(automaton)) # with open('/tmp/red.dot', 'w') as f: # f.write(automaton_to_dot.to_dot(coreach_automaton)) # exit() logging.info("using CoReachEncoder") logging.info('co-reachability automaton size is: %i' % len(coreach_automaton.nodes)) logging.debug('co-reachability automaton (dot) is:\n' + automaton_to_dot.to_dot(coreach_automaton)) encoder = CoreachEncoder(coreach_automaton, tau_desc, spec.inputs, desc_by_output, range(max_size), max_k) model = model_k_searcher.search(min_size, max_size, max_k, encoder, solver) logging.info('searching a model took (sec): %i' % timer.sec_restart()) return model
def check_unreal(ltl_text, part_text, is_moore, ltl_to_atm: LTLToAutomaton, solver: SolverInterface, max_k: int, min_size, max_size, opt_level=0) -> LTS: """ Note that opt_level > 0 may introduce unsoundness (returns unrealizable while it is). """ timer = Timer() spec = parse_acacia_and_build_expr(ltl_text, part_text, ltl_to_atm, opt_level) logging.info("LTL formula size: %i", expr_size(spec.formula)) timer.sec_restart() automaton = ltl_to_atm.convert(spec.formula) logging.info('(unreal) automaton size is: %i' % len(automaton.nodes)) logging.debug('(unreal) automaton (dot) is:\n' + automaton_to_dot.to_dot(automaton)) logging.debug('(unreal) automaton translation took (sec): %i' % timer.sec_restart()) # note: inputs/outputs and machine type are reversed tau_desc = build_tau_desc(spec.outputs) desc_by_output = dict((i, build_output_desc(i, not is_moore, spec.outputs)) for i in spec.inputs) if max_k == 0: encoder = CoBuchiEncoder(automaton, tau_desc, spec.outputs, desc_by_output, range(max_size)) model = model_searcher.search(min_size, max_size, encoder, solver) else: coreach_automaton = k_reduce(automaton, max_k) logging.info("(unreal) using CoReachEncoder") logging.info('(unreal) co-reachability automaton size is: %i' % len(coreach_automaton.nodes)) logging.debug('(unreal) co-reachability automaton (dot) is:\n' + automaton_to_dot.to_dot(coreach_automaton)) encoder = CoreachEncoder(coreach_automaton, tau_desc, spec.outputs, desc_by_output, range(max_size), max_k) model = model_k_searcher.search(min_size, max_size, max_k, encoder, solver) logging.debug('(unreal) model_searcher.search took (sec): %i' % timer.sec_restart()) return model
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