def test_bool_models(self): b1 = define_const('b1', bool_t) b2 = define_const('b2', bool_t) b3 = define_const('b3', bool_t) b_fml1 = Terms.parse_term('(or b1 b2 b3)') self.ctx.assert_formula(b_fml1) self.assertEqual(self.ctx.check_context(self.param), Status.SAT) b_mdl1 = Model.from_context(self.ctx, 1) self.assertNotEqual(b_mdl1, None) bval1 = b_mdl1.get_bool_value(b1) bval2 = b_mdl1.get_bool_value(b2) bval3 = b_mdl1.get_bool_value(b3) self.assertEqual(bval1, False) self.assertEqual(bval2, False) self.assertEqual(bval3, True) b_fmla2 = Terms.parse_term('(not b3)') self.ctx.assert_formula(b_fmla2) self.assertEqual(self.ctx.check_context(self.param), Status.SAT) b_mdl1 = Model.from_context(self.ctx, 1) self.assertNotEqual(b_mdl1, None) bval1 = b_mdl1.get_bool_value(b1) bval2 = b_mdl1.get_bool_value(b2) bval3 = b_mdl1.get_bool_value(b3) val1 = b_mdl1.get_value(b1) val2 = b_mdl1.get_value(b2) val3 = b_mdl1.get_value(b3) self.assertEqual(bval1, False) self.assertEqual(bval2, True) self.assertEqual(bval3, False) self.assertEqual(bval1, val1) self.assertEqual(bval2, val2) self.assertEqual(bval3, val3)
def missing(self): retcode = 2 if not self.addModel(): sys.stderr.write('addModel failed\n') return retcode self.protocol.constrainVariablesAPI(self.context) timelines = self.protocol.timelines tlen = len(timelines) interpretation = Configuration.timeline_interpretation tint_text = Configuration.INTERPRETATIONS[interpretation] print('There are {0} timelines ({1})\n'.format(tlen, tint_text)) if not timelines: return retcode for timeline in timelines: formula = timeline.toYicesTerm(interpretation) yassert_formula(self, formula) smt_stat = self.context.check_context() if smt_stat == Status.UNSAT: sys.stderr.write('The model is UNSAT: something is rotten in the State\n') retcode = 1 return retcode for timeline in timelines: satisfiable = True yevents = [ ] for eindex, timevar in enumerate(timeline.varlist): events = self.protocol.event_map[timevar] for e in events: yevents.append(e.yices_term) smt_stat = self.context.check_context_with_assumptions(None, yevents) if smt_stat == Status.UNSAT: satisfiable = False print('UNSAT at level {0}, i.e. timestamp {1}'.format(eindex, timevar)) unsat_core = self.context.get_unsat_core() print("\nUnsat core :\n") for term in unsat_core: Terms.print_to_fd(1, term, 80, 100, 0) print("\n") break elif self.verbose and smt_stat == Status.SAT: print('SAT at level {0}, i.e. timestamp {1}'.format(eindex, timevar)) model = Model.from_context(self.context, 1) self.print_solution(model, header=None, frees=timeline.fv) model.dispose() if satisfiable: print('Timeline of {0} OK ({1}):\n'.format(timeline.term, tint_text)) #print a model model = Model.from_context(self.context, 1) self.print_solution(model, header=None, frees=timeline.fv) model.dispose() retcode = 0 self._cleanUp() return retcode
def compute_reduced_core(self, i, j, val): """We compute the unsat core then remove any unnecessary terms.""" if not (0 <= i <= 8 and 0 <= j <= 8 and 1 <= val <= 9): raise Exception(f'Index error: {i} {j} {val}') context = Context() self.assert_puzzle(context) self.assert_not_value(context, i, j, val) self.assert_trivial_rules(context) smt_stat = context.check_context_with_assumptions( None, self.duplicate_rules) # a valid puzzle should have a unique solution, so this should not happen, if it does we bail if smt_stat != Status.UNSAT: print(f'Error: {i} {j} {val} - not UNSAT: {Status.name(smt_stat)}') model = Model.from_context(context, 1) answer = self.puzzle_from_model(model) print( 'Counter example (i.e. origonal puzzle does not have a unique solution):' ) answer.pprint() model.dispose() context.dispose() return None core = context.get_unsat_core() filtered = core.copy() for term in core: filtered.remove(term) smt_stat = context.check_context_with_assumptions(None, filtered) if smt_stat != Status.UNSAT: filtered.append(term) context.dispose() print( f'Core: {i} {j} {val} {len(filtered)} / {len(self.duplicate_rules)}' ) return (i, j, val, filtered)
def compute_core(self, i, j, val): """We compute the unsat core of the duplicate_rules when asserting self.var(i, j) != val w.r.t the puzzle (val is assumed to be the unique solution).""" if not (0 <= i <= 8 and 0 <= j <= 8 and 1 <= val <= 9): raise Exception(f'Index error: {i} {j} {val}') context = Context() self.assert_puzzle(context) self.assert_not_value(context, i, j, val) self.assert_trivial_rules(context) smt_stat = context.check_context_with_assumptions( None, self.duplicate_rules) # a valid puzzle should have a unique solution, so this should not happen, if it does we bail if smt_stat != Status.UNSAT: print(f'Error: {i} {j} {val} - not UNSAT: {Status.name(smt_stat)}') model = Model.from_context(context, 1) answer = self.puzzle_from_model(model) print( 'Counter example (i.e. origonal puzzle does not have a unique solution):' ) answer.pprint() model.dispose() context.dispose() return None core = context.get_unsat_core() context.dispose() print( f'Core: {i} {j} {val} {len(core)} / {len(self.duplicate_rules)}') return (i, j, val, core)
def entire(self): retcode = 2 if not self.addModel(): return retcode self.protocol.constrainVariablesAPI(self.context) searchSpace = Frontier(self.protocol) tower = list(searchSpace.tower()) tower.sort() for point in tower: print(point) assertions = self.protocol.toYicesTerms(point) alen = len(assertions) if alen: smt_stat = self.context.check_context_with_assumptions(None, assertions) if smt_stat == Status.SAT: print('SAT') #get the model model = Model.from_context(self.context, 1) self.print_solution(model, header=None, frees=self.protocol.FV(point)) model.dispose() elif smt_stat == Status.UNSAT: print('UNSAT') unsat_core = self.context.get_unsat_core() print("\nUnsat core:\n") for term in unsat_core: Terms.print_to_fd(1, term, 80, 100, 0) print("\n") else: sys.stderr.write('context.check_context_with_assumptions returned {0}\n', smt_stat) self._cleanUp() return retcode
def test_bv_models(self): bv_t = Types.bv_type(3) bv1 = define_const('bv1', bv_t) bv2 = define_const('bv2', bv_t) bv3 = define_const('bv3', bv_t) fmla1 = Terms.parse_term('(= bv1 (bv-add bv2 bv3))') fmla2 = Terms.parse_term('(bv-gt bv2 0b000)') fmla3 = Terms.parse_term('(bv-gt bv3 0b000)') self.ctx.assert_formula(fmla1) self.ctx.assert_formulas([fmla1, fmla2, fmla3]) self.assertEqual(self.ctx.check_context(self.param), Status.SAT) mdl1 = Model.from_context(self.ctx, 1) val1 = mdl1.get_value(bv1) self.assertEqual(val1[0], 0) self.assertEqual(val1[1], 0) self.assertEqual(val1[2], 0) val2 = mdl1.get_value(bv2) self.assertEqual(val2[0], 0) self.assertEqual(val2[1], 0) self.assertEqual(val2[2], 1) val3 = mdl1.get_value(bv3) self.assertEqual(val3[0], 0) self.assertEqual(val3[1], 0) self.assertEqual(val3[2], 1) mdl1.dispose()
def solve(self): context = Context() self.assert_rules(context) self.assert_puzzle(context) smt_stat = context.check_context(None) answer = None if smt_stat == Status.SAT: model = Model.from_context(context, 1) answer = self.puzzle_from_model(model) model.dispose() context.dispose() return answer
def test_tuple_models(self): tup_t = Types.new_tuple_type([bool_t, real_t, int_t]) t1 = define_const('t1', tup_t) assert_formula( '(ite (select t1 1) (< (select t1 2) (select t1 3)) (> (select t1 2) (select t1 3)))', self.ctx) self.assertEqual(self.ctx.check_context(self.param), Status.SAT) mdl = Model.from_context(self.ctx, 1) mdlstr = mdl.to_string(80, 100, 0) self.assertEqual(mdlstr, '(= t1 (mk-tuple false 1 0))') val = mdl.get_value(t1) self.assertEqual(val[0], False) self.assertEqual(val[1], 1) self.assertEqual(val[2], 0)
def test_int_models(self): ''' int32, int64 ''' i1 = define_const('i1', int_t) i2 = define_const('i2', int_t) assert_formula('(> i1 3)', self.ctx) assert_formula('(< i2 i1)', self.ctx) self.assertEqual(self.ctx.check_context(self.param), Status.SAT) mdl = Model.from_context(self.ctx, 1) i32v1 = mdl.get_integer_value(i1) i32v2 = mdl.get_integer_value(i2) self.assertEqual(i32v1, 4) self.assertEqual(i32v2, 3) mdl.print_to_fd(1) mdl.print_to_fd(1, 80, 100, 0) mdlstr = mdl.to_string(80, 100, 0) self.assertEqual(mdlstr, '(= i1 4)\n(= i2 3)')
def incrementally_solve(self): retcode = 2 if not self.addModel(): return retcode self.protocol.constrainVariablesAPI(self.context) if self.context.status() == Status.UNSAT: print('The model appears to be UNSAT: smt_stat = {}\n'.format(self.context.status())) print('For more information use the --consistency option.\n') return retcode # The meaning of the levels: # # 0. Just the events # 1. The events plus the distinctness of each timeline: distinct(varlist) for timeline(bot, varlist) in facts. # 2. The events plus the ascendingness of each timeline for level in range(0, 4): #print('context status: ', Status.name(self.context.status())) self.context.push() assertions = self.getProtocolIncrementally(level) alen = len(assertions) if alen: smt_stat = self.context.check_context_with_assumptions(None, assertions) sys.stderr.write('Level {0}: context.check_context_with_assumptions returned {1}\n'.format(level, Status.name(smt_stat))) if smt_stat == Status.SAT: #get the model model = Model.from_context(self.context, 1) print('Level {0} has a solution: smt_stat = {1}\n'.format(level, smt_stat)) self.print_solution(model) model.dispose() elif smt_stat == Status.UNSAT: unsat_core = self.context.get_unsat_core() if not unsat_core: sys.stderr.write('unsat_core is empty\n') else: print('Level {0} unsat core is:\n'.format(level)) for term in unsat_core: Terms.print_to_fd(1, term, 80, 100, 0) print('') return 0 else: sys.stderr.write('context.check_context_with_assumptions returned {0}\n'.format(Status.name(smt_stat))) self.context.pop() self._cleanUp() return 0
def solve(self, theory_file): retcode = 2 if not self.addFacts(): return retcode if theory_file is not None: self.writeTheory(theory_file) smt_stat = self.context.check_context() if smt_stat != Status.SAT: print('No solution: smt_stat = {0}\n'.format(smt_stat)) retcode = 1 else: print('\nSatisfiable.') #get the model model = Model.from_context(self.context, 1) self.print_solution(model) model.dispose() retcode = 0 self._cleanUp() return retcode
def test_scalar_models(self): scalar_t = Types.new_scalar_type(10) sc1 = define_const('sc1', scalar_t) sc2 = define_const('sc2', scalar_t) sc3 = define_const('sc3', scalar_t) assert_formula('(/= sc1 sc2)', self.ctx) assert_formula('(/= sc1 sc3)', self.ctx) self.assertEqual(self.ctx.check_context(self.param), Status.SAT) mdl = Model.from_context(self.ctx, 1) val1 = mdl.get_scalar_value(sc1) val2 = mdl.get_scalar_value(sc2) val3 = mdl.get_scalar_value(sc3) self.assertEqual(val1, 9) self.assertEqual(val2, 8) self.assertEqual(val3, 8) self.assertEqual(Terms.is_scalar(sc1), True) sc1val = mdl.get_value_as_term(sc1) self.assertEqual(Terms.is_scalar(sc1val), True) self.assertEqual(mdl.get_value(sc1), sc1val)
def test_model_support(self): x = define_const('x', real_t) y = define_const('y', real_t) z = define_const('z', real_t) formula = Terms.parse_term('(> x 0)') t0 = Terms.parse_term('(ite (> x 0) (+ x z) y)') t1 = Terms.parse_term('(+ (* x z) y)') self.ctx.assert_formula(formula) self.assertEqual(self.ctx.check_context(), Status.SAT) mdl = Model.from_context(self.ctx, 1) support = mdl.support_for_term(t0) self.assertEqual(len(support), 2) self.assertEqual(support[0], x) self.assertEqual(support[1], z) support = mdl.support_for_terms([t0, t1]) self.assertEqual(len(support), 3) self.assertEqual(support[0], x) self.assertEqual(support[1], y) self.assertEqual(support[2], z)
def test_implicant(self): i1 = define_const('i1', int_t) assert_formula('(and (> i1 2) (< i1 8) (/= i1 4))', self.ctx) self.assertEqual(self.ctx.check_context(self.param), Status.SAT) mdl = Model.from_context(self.ctx, 1) mdlstr = mdl.to_string(80, 100, 0) self.assertEqual(mdlstr, '(= i1 7)') fml = Terms.parse_term('(>= i1 3)') tarray = mdl.implicant_for_formula(fml) self.assertEqual(len(tarray), 1) implstr = Terms.to_string(tarray[0], 200, 10, 0) self.assertEqual(implstr, '(>= (+ -3 i1) 0)') fml2 = Terms.parse_term('(<= i1 9)') tarray2 = mdl.implicant_for_formulas([fml, fml2]) self.assertEqual(len(tarray2), 2) implstr2 = Terms.to_string(tarray2[0], 200, 10, 0) self.assertEqual(implstr2, '(>= (+ -3 i1) 0)') implstr3 = Terms.to_string(tarray2[1], 200, 10, 0) self.assertEqual(implstr3, '(>= (+ 9 (* -1 i1)) 0)')
def exhaust(self): result = 0 self.context.push() if not self.addFacts(): print('Bummer') return 2 # BD says: this is complete but crude # another way would be to use 'yices_assert_blocking_clause' while self.context.check_context() == Status.SAT: model = Model.from_context(self.context, 1) self.print_solution(model, 'Model #{0}:'.format(result)) diagram = YicesSignature.model2term(model) self.context.assert_formula(Terms.ynot(diagram)) model.dispose() result += 1 if result == Configuration.aleph_nought: break self.context.pop() print("I found {1} distinct model{2} (using an upper limit of {0})".format(Configuration.aleph_nought, result, "" if result == 1 else "s")) return result
def frontier(self): retcode = 2 if not self.addModel(): return retcode self.protocol.constrainVariablesAPI(self.context) searchSpace = Frontier(self.protocol) interpretation = Configuration.timeline_interpretation tint_text = Configuration.INTERPRETATIONS[interpretation] print('The timeline interpretation is: {0}\n'.format(tint_text)) while not searchSpace.finished(): point = searchSpace.nextElement() if point is None: break if self.verbose: print(point) assertions = self.protocol.toYicesTerms(point) alen = len(assertions) if alen: smt_stat = self.context.check_context_with_assumptions(None, assertions) if smt_stat == Status.SAT: if self.verbose: print('SAT') #get the model model = Model.from_context(self.context, 1) self.print_solution(model, header=None, frees=self.protocol.FV(point)) model.dispose() elif smt_stat == Status.UNSAT: searchSpace.addUnsat(point) if self.verbose: print('UNSAT') unsat_core = self.context.get_unsat_core() print("\nUnsat core:\n") for term in unsat_core: Terms.print_to_fd(1, term, 80, 100, 0) print("\n") else: sys.stderr.write('context.check_context_with_assumptions returned {0}\n', smt_stat) print('Frontier: {0}'.format(searchSpace.frontier)) self._cleanUp() return retcode
def test_function_models(self): funtype = Types.new_function_type([int_t, bool_t, real_t], real_t) ftystr = Types.to_string(funtype, 100, 80, 0) Types.print_to_fd(1, funtype, 100, 80, 0) self.assertEqual(ftystr, '(-> int bool real real)') fun1 = define_const('fun1', funtype) b1 = define_const('b1', bool_t) i1 = define_const('i1', int_t) r1 = define_const('r1', real_t) assert_formula( '(> (fun1 i1 b1 r1) (fun1 (+ i1 1) (not b1) (- r1 i1)))', self.ctx) self.assertEqual(self.ctx.check_context(self.param), Status.SAT) mdl = Model.from_context(self.ctx, 1) mdlstr = mdl.to_string(80, 100, 0) self.assertEqual( mdlstr, '(= b1 false)\n(= i1 1463)\n(= r1 -579)\n(function fun1\n (type (-> int bool real real))\n (= (fun1 1463 false -579) 1)\n (= (fun1 1464 true -2042) 0)\n (default 2))' ) fun1val = mdl.get_value(fun1) self.assertEqual(fun1val((1463, False, -579)), 1) self.assertEqual(fun1val((1464, True, -2042)), 0) self.assertEqual(fun1val((1462, True, -2041)), 2)
def test_rat_models(self): ''' rational32, rational64, double ''' r1 = define_const('r1', real_t) r2 = define_const('r2', real_t) assert_formula('(> r1 3)', self.ctx) assert_formula('(< r1 4)', self.ctx) assert_formula('(< (- r1 r2) 0)', self.ctx) self.assertEqual(self.ctx.check_context(self.param), Status.SAT) mdl = Model.from_context(self.ctx, 1) v1 = mdl.get_fraction_value(r1) v2 = mdl.get_fraction_value(r2) # r1 = 7/2, r2 = 4/1 self.assertEqual(v1.numerator, 7) self.assertEqual(v1.denominator, 2) self.assertEqual(v2.numerator, 4) self.assertEqual(v2.denominator, 1) rdoub1 = mdl.get_float_value(r1) rdoub2 = mdl.get_float_value(r2) self.assertEqual(rdoub1, 3.5) self.assertEqual(rdoub2, 4.0) val1 = mdl.get_value(r1) val2 = mdl.get_value(r2) self.assertEqual(val1, 3.5) self.assertEqual(val2, 4.0)
set_value(context, (8, 3), 9) set_value(context, (8, 7), 8) set_value(context, (8, 9), 5) set_value(context, (9, 1), 6) set_value(context, (9, 2), 7) set_value(context, (9, 3), 1) set_value(context, (9, 7), 2) #check sat smt_stat = context.check_context(None) if smt_stat != Status.SAT: print('No solution: smt_stat = {0}\n'.format(smt_stat)) else: #print model model = Model.from_context(context, 1) for i in range(9): for j in range(9): val = model.get_value(V(i, j)) print('V({0}, {1}) = {2}'.format(i, j, val)) model.dispose() print('Cleaning up\n') context.dispose() config.dispose() Yices.exit()