@@ -6212,6 +6212,42 @@ def model(self):
62126212 """
62136213 return ModelRef (self )
62146214
6215+ def proof (self ):
6216+ """Return a proof for the last `check()`.
6217+
6218+ This function raises an exception if
6219+ a proof is not available (e.g., last `check()` does not return unsat).
6220+
6221+ >>> s = Solver()
6222+ >>> s.set('produce-proofs','true')
6223+ >>> a = Int('a')
6224+ >>> s.add(a + 2 == 0)
6225+ >>> s.check()
6226+ sat
6227+ >>> try:
6228+ ... s.proof()
6229+ ... except RuntimeError:
6230+ ... print("failed to get proof (last `check()` must have returned unsat)")
6231+ failed to get proof (last `check()` must have returned unsat)
6232+ >>> s.add(a == 0)
6233+ >>> s.check()
6234+ unsat
6235+ >>> s.proof()
6236+ (SCOPE: Not(And(a + 2 == 0, a == 0)),
6237+ (SCOPE: Not(And(a + 2 == 0, a == 0)),
6238+ [a + 2 == 0, a == 0],
6239+ (EQ_RESOLVE: False,
6240+ (ASSUME: a == 0, [a == 0]),
6241+ (MACRO_SR_EQ_INTRO: (a == 0) == False,
6242+ [a == 0, 7, 12],
6243+ (EQ_RESOLVE: a == -2,
6244+ (ASSUME: a + 2 == 0, [a + 2 == 0]),
6245+ (MACRO_SR_EQ_INTRO: (a + 2 == 0) == (a == -2),
6246+ [a + 2 == 0, 7, 12]))))))
6247+ """
6248+ p = self .solver .getProof ()[0 ]
6249+ return ProofRef (self , p )
6250+
62156251 def assertions (self ):
62166252 """Return an AST vector containing all added constraints.
62176253
@@ -6760,6 +6796,98 @@ def evaluate(t):
67606796 return m [t ]
67616797
67626798
6799+ class ProofRef :
6800+ """A proof tree where every proof reference corresponds to the
6801+ root step of a proof. The branches of the root step are the
6802+ premises of the step."""
6803+
6804+ def __init__ (self , solver , proof ):
6805+ self .proof = proof
6806+ self .solver = solver
6807+
6808+ def __del__ (self ):
6809+ if self .solver is not None :
6810+ self .solver = None
6811+
6812+ def __repr__ (self ):
6813+ return obj_to_string (self )
6814+
6815+ def getRule (self ):
6816+ """Returns the proof rule used by the root step of the proof.
6817+
6818+ >>> s = Solver()
6819+ >>> s.set('produce-proofs','true')
6820+ >>> a = Int('a')
6821+ >>> s.add(a + 2 == 0, a == 0)
6822+ >>> s.check()
6823+ unsat
6824+ >>> p = s.proof()
6825+ >>> p.getRule()
6826+ <ProofRule.SCOPE: 1>
6827+ """
6828+ return self .proof .getRule ()
6829+
6830+ def getResult (self ):
6831+ """Returns the conclusion of the root step of the proof.
6832+
6833+ >>> s = Solver()
6834+ >>> s.set('produce-proofs','true')
6835+ >>> a = Int('a')
6836+ >>> s.add(a + 2 == 0, a == 0)
6837+ >>> s.check()
6838+ unsat
6839+ >>> p = s.proof()
6840+ >>> p.getResult()
6841+ Not(And(a + 2 == 0, a == 0))
6842+ """
6843+ return _to_expr_ref (self .proof .getResult (), Context (self .solver ))
6844+
6845+ def getChildren (self ):
6846+ """Returns the premises, i.e., proofs themselvels, of the root step of
6847+ the proof.
6848+
6849+ >>> s = Solver()
6850+ >>> s.set('produce-proofs','true')
6851+ >>> a = Int('a')
6852+ >>> s.add(a + 2 == 0, a == 0)
6853+ >>> s.check()
6854+ unsat
6855+ >>> p = s.proof()
6856+ >>> p = p.getChildren()[0].getChildren()[0]
6857+ >>> p
6858+ (EQ_RESOLVE: False,
6859+ (ASSUME: a == 0, [a == 0]),
6860+ (MACRO_SR_EQ_INTRO: (a == 0) == False,
6861+ [a == 0, 7, 12],
6862+ (EQ_RESOLVE: a == -2,
6863+ (ASSUME: a + 2 == 0, [a + 2 == 0]),
6864+ (MACRO_SR_EQ_INTRO: (a + 2 == 0) == (a == -2),
6865+ [a + 2 == 0, 7, 12]))))
6866+ """
6867+ children = self .proof .getChildren ()
6868+ return [ProofRef (self .solver , cp ) for cp in children ]
6869+
6870+ def getArguments (self ):
6871+ """Returns the arguments of the root step of the proof as a list of
6872+ expressions.
6873+
6874+ >>> s = Solver()
6875+ >>> s.set('produce-proofs','true')
6876+ >>> a = Int('a')
6877+ >>> s.add(a + 2 == 0, a == 0)
6878+ >>> s.check()
6879+ unsat
6880+ >>> p = s.proof()
6881+ >>> p.getArguments()
6882+ []
6883+ >>> p = p.getChildren()[0]
6884+ >>> p.getArguments()
6885+ [a + 2 == 0, a == 0]
6886+ """
6887+ args = self .proof .getArguments ()
6888+ return [_to_expr_ref (a , Context (self .solver )) for a in args ]
6889+
6890+
67636891def simplify (a ):
67646892 """Simplify the expression `a`.
67656893
0 commit comments