def theorem(s: Solver) -> None: utils.logger.always_print('checking theorems:') prog = syntax.the_program for th in prog.theorems(): if th.twostate: keys = [KEY_OLD, KEY_NEW] else: keys = [KEY_ONE] t = s.get_translator(*keys) if th.name is not None: msg = ' ' + th.name elif th.tok is not None: msg = ' on line %d' % th.tok.lineno else: msg = '' utils.logger.always_print(' theorem%s... ' % msg, end='') sys.stdout.flush() with s: s.add(z3.Not(t.translate_expr(th.expr))) logic.check_unsat([(th.tok, 'theorem%s may not hold' % msg)], s, keys)
def check_automaton_init(s: Solver, a: AutomatonDecl) -> None: utils.logger.always_print('checking automaton init:') prog = syntax.the_program t = s.get_translator(KEY_ONE) init_decl = a.the_init() assert init_decl is not None # checked by resolver init_phase = prog.scope.get_phase(init_decl.phase) assert init_phase is not None # checked by resolver with s: for init in prog.inits(): s.add(t.translate_expr(init.expr)) for inv in init_phase.invs(): with s: s.add(z3.Not(t.translate_expr(inv.expr))) if inv.tok is not None: msg = ' on line %d' % inv.tok.lineno else: msg = '' utils.logger.always_print(' implies phase invariant%s... ' % msg, end='') sys.stdout.flush() logic.check_unsat([ (inv.tok, 'phase invariant%s may not hold in initial state' % msg) ], s, [KEY_ONE])
def theorem(s: Solver) -> None: utils.logger.always_print('checking theorems:') prog = syntax.the_program for th in prog.theorems(): if th.num_states == 2: num_states = 2 elif th.num_states == 1: num_states = 1 else: num_states = 0 t = s.get_translator(num_states) if th.name is not None: msg = ' ' + th.name elif th.span is not None: msg = ' on line %d' % th.span[0].lineno else: msg = '' utils.logger.always_print(' theorem%s... ' % msg, end='') sys.stdout.flush() with s.new_frame(): s.add(t.translate_expr(Not(th.expr))) logic.check_unsat([(th.span, 'theorem%s does not hold' % msg)], s, num_states)
def always_assert_inductive_trace(self) -> None: for i, f in enumerate(self.fs[:-1]): for c in self.fs[i + 1].summary(): res = self.clause_implied_by_transitions_from_frame( f, c, Solver()) assert res is None, ("Non inductive trace:\n\t%s\n\t%s" % (c, f))
def check_automaton_edge_covering(s: Solver, a: AutomatonDecl) -> None: utils.logger.always_print('checking automaton edge covering:') prog = syntax.the_program t = s.get_translator(KEY_NEW, KEY_OLD) for phase in a.phases(): utils.logger.always_print(' checking phase %s:' % phase.name) with s: for inv in phase.invs(): s.add(t.translate_expr(inv.expr, old=True)) for trans in prog.transitions(): if any(delta.transition == trans.name and delta.precond is None for delta in phase.transitions()): utils.logger.always_print(' transition %s is covered trivially.' % trans.name) continue utils.logger.always_print(' checking transition %s is covered... ' % trans.name, end='') with s: s.add(t.translate_transition(trans)) s.add(z3.And(*(z3.Not(t.translate_precond_of_transition(delta.precond, trans)) for delta in phase.transitions() if trans.name == delta.transition))) logic.check_unsat([(phase.tok, 'transition %s is not covered by this phase' % (trans.name, )), (trans.tok, 'this transition misses transitions from phase %s' % (phase.name,))], s, [KEY_OLD, KEY_NEW])
def always_assert_inductive_trace(self) -> None: for i, f in enumerate(self.fs[:-1]): with utils.LogTag(utils.logger, 'inductive-trace-assert', lvl=logging.DEBUG, i=str(i)): for p in self.automaton.phases(): for c in self.fs[i + 1].summary_of(p): res = self.clause_implied_by_transitions_from_frame( f, p, c, Solver()) assert res is None, ( "Non inductive trace:\n\t%s\n\t%s\n\t%s" % (p.name(), c, f))
def check_automaton_inductiveness(s: Solver, a: AutomatonDecl) -> None: utils.logger.always_print('checking automaton inductiveness:') prog = syntax.the_program t = s.get_translator(KEY_NEW, KEY_OLD) for phase in a.phases(): utils.logger.always_print(' checking phase %s:' % phase.name) with s: for inv in phase.invs(): s.add(t.translate_expr(inv.expr, old=True)) for delta in phase.transitions(): trans = prog.scope.get_definition(delta.transition) assert trans is not None precond = delta.precond target = prog.scope.get_phase( delta.target) if delta.target is not None else phase assert target is not None trans_pretty = '(%s, %s)' % (trans.name, str(precond) if (precond is not None) else 'true') utils.logger.always_print(' checking transition: %s' % trans_pretty) with s: s.add(t.translate_transition(trans, precond=precond)) for inv in target.invs(): with s: s.add(z3.Not(t.translate_expr(inv.expr))) if inv.tok is not None: msg = ' on line %d' % inv.tok.lineno else: msg = '' utils.logger.always_print( ' preserves invariant%s... ' % msg, end='') sys.stdout.flush() logic.check_unsat([ (inv.tok, 'invariant%s may not be preserved by transition %s in phase %s' % (msg, trans_pretty, phase.name)), (delta.tok, 'this transition may not preserve invariant%s' % (msg, )) ], s, [KEY_OLD, KEY_NEW])
def diagram_trace_to_explicitly_relaxed_trace(trace: RelaxedTrace, safety: Sequence[syntax.InvariantDecl]) -> None: relaxed_prog = relaxed_program(syntax.the_program) with syntax.prog_context(relaxed_prog): s = Solver() end_expr = syntax.Not(syntax.And(*(invd.expr for invd in safety))) with syntax.the_program.scope.n_states(1): end_expr.resolve(syntax.the_program.scope, syntax.BoolSort) trace_decl = diagram_trace_to_explicitly_relaxed_trace_decl(trace, end_expr) with syntax.the_program.scope.n_states(1): trace_decl.resolve(syntax.the_program.scope) print(trace_decl) res = bmc_trace(relaxed_prog, trace_decl, s, lambda slvr, ks: logic.check_solver(slvr, ks, minimize=True)) print(res) assert False
def translate_transition_call(s: Solver, key: str, key_old: str, c: syntax.TransitionCall) -> z3.ExprRef: prog = syntax.the_program ition = prog.scope.get_definition(c.target) assert ition is not None lator = s.get_translator(key, key_old) bs = lator.bind(ition.binder) qs: List[Optional[z3.ExprRef]] = [b for b in bs] if c.args is not None: for j, a in enumerate(c.args): if isinstance(a, Expr): bs[j] = lator.translate_expr(a) qs[j] = None else: assert isinstance(a, syntax.Star) qs1 = [q for q in qs if q is not None] with lator.scope.in_scope(ition.binder, bs): body = lator.translate_transition_body(ition) if len(qs1) > 0: return z3.Exists(qs1, body) else: return body
def __init__(self, master, **kwargs): self.puzzleGrid = SDKGrid("") self.solver = Solver.Solver() self.master = master master.geometry('450x500+0+0') top_title_header = Frame(self.master, width=450, height=25) top_title_header.pack() top_frame = Frame(self.master, width=450, height=500) top_frame.pack() #create input (entry) widgets and assign to SDKgrid for x in range(9): for y in range(9): input = Entry(top_frame, width=2, font=("Courier", 24), justify="center") self.puzzleGrid.get_cell_at_coords(x, y).entryBox = input input.grid(row=x, column=y) grid_to_label_spacer = Frame(width=450, height=10) grid_to_label_spacer.pack() #label for messages self.message = StringVar() self.message.set("LOAD or manually input a puzzle!") self.label_for_messages = Label(self.master, textvariable=self.message) self.label_for_messages.pack() #separate grid and buttons label_to_button_spacer = Frame(width=600, height=10) label_to_button_spacer.pack() #container for buttons bottom_frame = Frame(width=600, height=50) bottom_frame.pack() """Button Widgets""" solve_button = Button(bottom_frame, text="SOLVE", fg="blue", command=lambda: self.solve_button()) solve_button.pack(side=LEFT) step_button = Button(bottom_frame, text="STEP", fg="black", command=lambda: self.step_button()) step_button.pack(side=LEFT) populate_button = Button(bottom_frame, text="LOAD", fg="black", command=lambda: self.load()) populate_button.pack(side=LEFT) save_button = Button(bottom_frame, text="SAVE", fg="black", command=lambda: self.save()) save_button.pack(side=LEFT) quit_button = Button(bottom_frame, text="QUIT", fg="red", command=bottom_frame.quit) quit_button.pack(side=LEFT)
def bmc_trace(prog: syntax.Program, trace: syntax.TraceDecl, s: Solver, sat_checker: Callable[[Solver, int], Optional[logic.Trace]], log: bool = False) -> Optional[logic.Trace]: n_states = len(list(trace.transitions())) + 1 if log: print('%s states' % (n_states, )) lator = s.get_translator(n_states) with s.new_frame(): if len(trace.components) > 0 and not isinstance( trace.components[0], syntax.AssertDecl): for init in prog.inits(): s.add(lator.translate_expr(init.expr)) i = 0 for c in trace.components: if isinstance(c, syntax.AssertDecl): if c.expr is None: if i != 0: utils.print_error_and_exit( c.span, 'assert init is only allowed in the first state') for init in prog.inits(): assert i == 0 s.add(lator.translate_expr(init.expr)) else: s.add(lator.translate_expr(New(c.expr, i))) else: te: syntax.TransitionExpr = c.transition if isinstance(te, syntax.AnyTransition): logic.assert_any_transition(s, lator, i, allow_stutter=True) else: l = [] for call in te.calls: tid = z3.Bool( logic.get_transition_indicator( str(i), call.target)) l.append(tid) s.add( z3.Implies( tid, translate_transition_call(s, lator, i, call))) s.add(z3.Or(*l)) i += 1 return sat_checker(s, n_states)
def bmc_trace(prog: syntax.Program, trace: syntax.TraceDecl, s: Solver, sat_checker: Callable[[Solver, List[str]], Optional[logic.Trace]], log: bool = False) -> Optional[logic.Trace]: n_states = len(list(trace.transitions())) + 1 if log: print('%s states' % (n_states, )) keys = ['state%2d' % i for i in range(n_states)] for k in keys: s.get_translator( k) # initialize all the keys before pushing a solver stack frame with s: lator = s.get_translator(keys[0]) if len(trace.components) > 0 and not isinstance( trace.components[0], syntax.AssertDecl): for init in prog.inits(): s.add(lator.translate_expr(init.expr)) i = 0 for c in trace.components: if isinstance(c, syntax.AssertDecl): if c.expr is None: if i != 0: utils.print_error_and_exit( c.tok, 'assert init is only allowed in the first state') for init in prog.inits(): s.add( s.get_translator(keys[i]).translate_expr( init.expr)) else: s.add(s.get_translator(keys[i]).translate_expr(c.expr)) else: te: syntax.TransitionExpr = c.transition if isinstance(te, syntax.AnyTransition): logic.assert_any_transition(s, str(i), keys[i + 1], keys[i], allow_stutter=True) else: l = [] for call in te.calls: tid = z3.Bool( logic.get_transition_indicator( str(i), call.target)) l.append(tid) s.add(tid == translate_transition_call( s, keys[i + 1], keys[i], call)) s.add(z3.Or(*l)) i += 1 return sat_checker(s, keys)
def main() -> None: resource.setrlimit( resource.RLIMIT_AS, (90 * 10**9, 90 * 10**9) ) # limit RAM usage to 45 GB # TODO: make this a command line argument # TODO: not sure if this is actually the right way to do this (also, what about child processes?) utils.args = parse_args(sys.argv[1:]) if utils.args.log_xml: fmt = '%(message)s' elif utils.args.log_time: fmt = '%(asctime)s %(filename)s:%(lineno)d: %(message)s' else: fmt = '%(filename)s:%(lineno)d: %(message)s' if 'json' in utils.args and utils.args.json: utils.args.log = 'critical' utils.logger.setLevel(getattr(logging, utils.args.log.upper(), None)) handler = logging.StreamHandler(stream=sys.stdout) handler.terminator = '' handler.setFormatter(MyFormatter(fmt)) logging.root.addHandler(handler) # utils.logger.addHandler(handler) with utils.LogTag(utils.logger, 'main', lvl=logging.INFO): if utils.args.print_cmdline: with utils.LogTag(utils.logger, 'options', lvl=logging.INFO): utils.logger.info(' '.join([sys.executable] + sys.argv)) utils.logger.info('Running mypyvy with the following options:') for k, v in sorted(vars(utils.args).items()): utils.logger.info(f' {k} = {v!r}') utils.logger.info('setting seed to %d' % utils.args.seed) z3.set_param('smt.random_seed', utils.args.seed) # utils.logger.info('enable z3 macro finder') # z3.set_param('smt.macro_finder', True) if utils.args.timeout is not None: utils.logger.info('setting z3 timeout to %s' % utils.args.timeout) z3.set_param('timeout', utils.args.timeout) pre_parse_error_count = utils.error_count with open(utils.args.filename) as f: prog = parse_program( f.read(), force_rebuild=utils.args.forbid_parser_rebuild, filename=utils.args.filename) if utils.error_count > pre_parse_error_count: utils.logger.always_print('program has syntax errors.') sys.exit(1) if utils.args.print_program_repr: utils.logger.always_print(repr(prog)) if utils.args.print_program: utils.logger.always_print(str(prog)) pre_resolve_error_count = utils.error_count prog.resolve() if utils.error_count > pre_resolve_error_count: utils.logger.always_print('program has resolution errors.') sys.exit(1) syntax.the_program = prog s = Solver() # initialize common keys s.get_translator(KEY_ONE) s.get_translator(KEY_NEW) s.get_translator(KEY_OLD) utils.args.main(s) utils.logger.info('total number of queries: %s' % s.nqueries) if utils.args.ipython: ipython(s) sys.exit(1 if utils.error_count > 0 else 0)
def main() -> None: # limit RAM usage to 45 GB # TODO: make this a command line argument # TODO: not sure if this is actually the right way to do this (also, what about child processes?) resource.setrlimit(resource.RLIMIT_AS, (90 * 10**9, 90 * 10**9)) utils.args = parse_args(sys.argv[1:]) if utils.args.log_xml: fmt = '%(message)s' elif utils.args.log_time: fmt = '%(asctime)s %(filename)s:%(lineno)d: %(message)s' else: fmt = '%(filename)s:%(lineno)d: %(message)s' if 'json' in utils.args and utils.args.json: utils.args.log = 'critical' utils.logger.setLevel(getattr(logging, utils.args.log.upper(), None)) handler = logging.StreamHandler(stream=sys.stdout) handler.terminator = '' handler.setFormatter(MyFormatter(fmt)) logging.root.addHandler(handler) if utils.args.print_cmdline: utils.logger.always_print(' '.join([sys.executable] + sys.argv)) utils.logger.info('Running mypyvy with the following options:') for k, v in sorted(vars(utils.args).items()): utils.logger.info(f' {k} = {v!r}') utils.logger.info('setting seed to %d' % utils.args.seed) z3.set_param('smt.random_seed', utils.args.seed) z3.set_param('sat.random_seed', utils.args.seed) # utils.logger.info('enable z3 macro finder') # z3.set_param('smt.macro_finder', True) if utils.args.timeout is not None: utils.logger.info('setting z3 timeout to %s' % utils.args.timeout) z3.set_param('timeout', utils.args.timeout) pre_parse_error_count = utils.error_count with open(utils.args.filename) as f: prog = parse_program(f.read(), forbid_rebuild=utils.args.forbid_parser_rebuild, filename=utils.args.filename) if utils.error_count > pre_parse_error_count: utils.logger.always_print('program has syntax errors.') utils.exit(1) if utils.args.print_program is not None: if utils.args.print_program == 'str': to_str: Callable[[Program], str] = str end = '\n' elif utils.args.print_program == 'repr': to_str = repr end = '\n' elif utils.args.print_program == 'faithful': to_str = syntax.faithful_print_prog end = '' elif utils.args.print_program == 'without-invariants': def p(prog: Program) -> str: return syntax.faithful_print_prog(prog, skip_invariants=True) to_str = p end = '' else: assert False utils.logger.always_print(to_str(prog), end=end) pre_typecheck_error_count = utils.error_count typechecker.typecheck_program(prog) if utils.error_count > pre_typecheck_error_count: utils.logger.always_print('program has resolution errors.') utils.exit(1) syntax.the_program = prog s = Solver(use_cvc4=utils.args.cvc4) utils.args.main(s) if utils.args.ipython: ipython(s) utils.exit(1 if utils.error_count > 0 else 0)
def trace(s: Solver) -> None: prog = syntax.the_program if len(list(prog.traces())) > 0: utils.logger.always_print('finding traces:') for trace in prog.traces(): n_states = len(list(trace.transitions())) + 1 print('%s states' % (n_states,)) keys = ['state%2d' % i for i in range(n_states)] for k in keys: s.get_translator(k) # initialize all the keys before pushing a solver stack frame with s: lator = s.get_translator(keys[0]) if len(trace.components) > 0 and not isinstance(trace.components[0], syntax.AssertDecl): for init in prog.inits(): s.add(lator.translate_expr(init.expr)) i = 0 for c in trace.components: if isinstance(c, syntax.AssertDecl): if c.expr is None: if i != 0: utils.print_error_and_exit(c.tok, 'assert init is only allowed in the first state') for init in prog.inits(): s.add(s.get_translator(keys[i]).translate_expr(init.expr)) else: s.add(s.get_translator(keys[i]).translate_expr(c.expr)) else: te: syntax.TransitionExpr = c.transition if isinstance(te, syntax.AnyTransition): logic.assert_any_transition(s, str(i), keys[i + 1], keys[i], allow_stutter=True) else: l = [] for call in te.calls: tid = z3.Bool(logic.get_transition_indicator(str(i), call.target)) l.append(tid) s.add(tid == translate_transition_call(s, keys[i + 1], keys[i], call)) s.add(z3.Or(*l)) i += 1 res = logic.check_unsat([], s, keys) if (res == z3.sat) != trace.sat: utils.print_error(trace.tok, 'trace declared %s but was %s!' % ('sat' if trace.sat else 'unsat', res))