From 9f449e726e41255a9083a0b196d9c6592312f48d Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 3 Feb 2025 19:26:13 +0100 Subject: [PATCH 001/132] Added multiple classes for supporting proof generation. Added method getProof() in BasicProverEnvironment.java --- .../sosy_lab/java_smt/ResolutionProofDAG.java | 32 ++++ .../java_smt/ResolutionProofNode.java | 41 +++++ .../sosy_lab/java_smt/SourceProofNode.java | 30 ++++ .../java_smt/api/BasicProverEnvironment.java | 20 ++- .../java_smt/api/proofs/ProofDAG.java | 22 +++ .../java_smt/api/proofs/ProofFactory.java | 26 ++++ .../java_smt/api/proofs/ProofNode.java | 30 ++++ .../visitors/ProofTraversalVisitor.java | 38 +++++ .../api/proofs/visitors/ProofVisitor.java | 19 +++ .../java_smt/basicimpl/AbstractProofDAG.java | 57 +++++++ .../java_smt/basicimpl/AbstractProofNode.java | 68 ++++++++ src/org/sosy_lab/java_smt/resProofRule.java | 145 ++++++++++++++++++ 12 files changed, 522 insertions(+), 6 deletions(-) create mode 100644 src/org/sosy_lab/java_smt/ResolutionProofDAG.java create mode 100644 src/org/sosy_lab/java_smt/ResolutionProofNode.java create mode 100644 src/org/sosy_lab/java_smt/SourceProofNode.java create mode 100644 src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java create mode 100644 src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java create mode 100644 src/org/sosy_lab/java_smt/api/proofs/ProofNode.java create mode 100644 src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java create mode 100644 src/org/sosy_lab/java_smt/api/proofs/visitors/ProofVisitor.java create mode 100644 src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java create mode 100644 src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java create mode 100644 src/org/sosy_lab/java_smt/resProofRule.java diff --git a/src/org/sosy_lab/java_smt/ResolutionProofDAG.java b/src/org/sosy_lab/java_smt/ResolutionProofDAG.java new file mode 100644 index 0000000000..6853c30ab5 --- /dev/null +++ b/src/org/sosy_lab/java_smt/ResolutionProofDAG.java @@ -0,0 +1,32 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt; + +import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.basicimpl.AbstractProofDAG; + +public class ResolutionProofDAG extends AbstractProofDAG { + + @Override + public void addNode(ProofNode node) { + super.addNode(node); + } + + @Override + public ProofNode getNode(int nodeId) { + return super.getNode(nodeId); + } + + @Override + public void addEdge(int parentNodeId, int childNodeId) { + super.addEdge(parentNodeId, childNodeId); + } +} diff --git a/src/org/sosy_lab/java_smt/ResolutionProofNode.java b/src/org/sosy_lab/java_smt/ResolutionProofNode.java new file mode 100644 index 0000000000..be782d9001 --- /dev/null +++ b/src/org/sosy_lab/java_smt/ResolutionProofNode.java @@ -0,0 +1,41 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt; + +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; +import org.sosy_lab.java_smt.resProofRule.Rule; + +public class ResolutionProofNode extends AbstractProofNode + implements ProofNode { + + private final Formula pivot; + + public ResolutionProofNode(Formula formula, Formula pivot) { + super(Rule.RESOLUTION, formula); + this.pivot = pivot; + } + + + @Override + public boolean isSource() { + return false; + } + + public Formula getPivot() { + return pivot; + } + + public Rule getRule() { + return super.getRule(); + } +} diff --git a/src/org/sosy_lab/java_smt/SourceProofNode.java b/src/org/sosy_lab/java_smt/SourceProofNode.java new file mode 100644 index 0000000000..22bc300584 --- /dev/null +++ b/src/org/sosy_lab/java_smt/SourceProofNode.java @@ -0,0 +1,30 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt; + +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; + +public class SourceProofNode extends AbstractProofNode + implements ProofNode { + + + public SourceProofNode(resProofRule.Rule rule, Formula formula) { + super(rule, formula); + } + + + @Override + public boolean isSource() { + return true; + } +} diff --git a/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java b/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java index b5ac3b1455..652b10b801 100644 --- a/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java @@ -16,6 +16,7 @@ import java.util.Optional; import org.checkerframework.checker.nullness.qual.Nullable; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; +import org.sosy_lab.java_smt.api.proofs.ProofDAG; /** * Super interface for {@link ProverEnvironment} and {@link InterpolatingProverEnvironment} that @@ -32,7 +33,7 @@ public interface BasicProverEnvironment extends AutoCloseable { */ @Nullable @CanIgnoreReturnValue - default T push(BooleanFormula f) throws InterruptedException { + default T push(BooleanFormula f) throws InterruptedException, SolverException { push(); return addConstraint(f); } @@ -46,7 +47,7 @@ default T push(BooleanFormula f) throws InterruptedException { /** Add a constraint to the latest backtracking point. */ @Nullable @CanIgnoreReturnValue - T addConstraint(BooleanFormula constraint) throws InterruptedException; + T addConstraint(BooleanFormula constraint) throws InterruptedException, SolverException; /** * Create a new backtracking point, i.e., a new level on the assertion stack. Each level can hold @@ -55,7 +56,7 @@ default T push(BooleanFormula f) throws InterruptedException { *

If formulas are added before creating the first backtracking point, they can not be removed * via a POP-operation. */ - void push() throws InterruptedException; + void push() throws InterruptedException, SolverException; /** * Get the number of backtracking points/levels on the current stack. @@ -87,7 +88,7 @@ boolean isUnsatWithAssumptions(Collection assumptions) *

A model might contain additional symbols with their evaluation, if a solver uses its own * temporary symbols. There should be at least a value-assignment for each free symbol. */ - Model getModel() throws SolverException; + Model getModel() throws SolverException, InterruptedException; /** * Get a temporary view on the current satisfying assignment. This should be called only @@ -95,7 +96,7 @@ boolean isUnsatWithAssumptions(Collection assumptions) * should no longer be used as soon as any constraints are added to, pushed, or popped from the * prover stack. */ - default Evaluator getEvaluator() throws SolverException { + default Evaluator getEvaluator() throws InterruptedException, SolverException { return getModel(); } @@ -107,7 +108,8 @@ default Evaluator getEvaluator() throws SolverException { *

Note that if you need to iterate multiple times over the model it may be more efficient to * use this method instead of {@link #getModel()} (depending on the solver). */ - default ImmutableList getModelAssignments() throws SolverException { + default ImmutableList getModelAssignments() + throws SolverException, InterruptedException { try (Model model = getModel()) { return model.asList(); } @@ -149,6 +151,12 @@ default ImmutableMap getStatistics() { return ImmutableMap.of(); } + /** + * Get proof of unsatisfiability of the conjuction of the current satck of all formulas. Should + * only be called after {@link #isUnsat()} returned true. + */ + ProofDAG getProof() throws SolverException, InterruptedException; + /** * Closes the prover environment. The object should be discarded, and should not be used after * closing. The first call of this method will close the prover instance, further calls are diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java b/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java new file mode 100644 index 0000000000..ca7265879a --- /dev/null +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java @@ -0,0 +1,22 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.api.proofs; + +import java.util.Collection; +import org.sosy_lab.java_smt.api.proofs.visitors.ProofVisitor; + +public interface ProofDAG { + void addNode(ProofNode node); + ProofNode getNode(int nodeId); + void addEdge(int parentNodeId, int childNodeId); + Collection> getNodes(); + void accept(ProofVisitor visitor); // To allow traversal of the entire DAG +} diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java new file mode 100644 index 0000000000..0060e051cf --- /dev/null +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java @@ -0,0 +1,26 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.api.proofs; + +import org.sosy_lab.java_smt.ResolutionProofNode; +import org.sosy_lab.java_smt.SourceProofNode; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.resProofRule.Rule; + +public class ProofFactory { + public static ProofNode createSourceNode(Rule rule, Formula formula) { + return new SourceProofNode(rule, formula); + } + + public static ProofNode createResolutionNode(Formula formula, Formula pivot) { + return new ResolutionProofNode(formula, pivot); + } +} diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java b/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java new file mode 100644 index 0000000000..7d36f4b8db --- /dev/null +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java @@ -0,0 +1,30 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.api.proofs; + + +import java.util.List; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.proofs.visitors.ProofVisitor; + +/** + * A proof node in the proof DAG of a proof. + * + * @author Gabriel Carpio + */ +public interface ProofNode { + List> getChildren(); + void addChild(ProofNode child); + boolean isSource(); + boolean isSink(); + void accept(ProofVisitor visitor); + Formula getFormula(); +} diff --git a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java new file mode 100644 index 0000000000..35e65fc3fc --- /dev/null +++ b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java @@ -0,0 +1,38 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.api.proofs.visitors; + +import java.util.HashSet; +import java.util.Set; +import org.sosy_lab.java_smt.api.proofs.ProofDAG; +import org.sosy_lab.java_smt.api.proofs.ProofNode; + +public class ProofTraversalVisitor implements ProofVisitor { + private final Set> visited = new HashSet<>(); + + @Override + public void visitNode(ProofNode node) { + if (visited.add(node)) { + for (ProofNode child : node.getChildren()) { + visitNode(child); + } + } + } + + @Override + public void visitDAG(ProofDAG dag) { + for (ProofNode node : dag.getNodes()) { + if (!visited.contains(node)) { + visitNode(node); + } + } + } +} \ No newline at end of file diff --git a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofVisitor.java b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofVisitor.java new file mode 100644 index 0000000000..469c797ac7 --- /dev/null +++ b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofVisitor.java @@ -0,0 +1,19 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.api.proofs.visitors; + +import org.sosy_lab.java_smt.api.proofs.ProofDAG; +import org.sosy_lab.java_smt.api.proofs.ProofNode; + +public interface ProofVisitor { + void visitNode(ProofNode node); + void visitDAG(ProofDAG dag); +} diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java new file mode 100644 index 0000000000..acd13a0b6e --- /dev/null +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java @@ -0,0 +1,57 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.basicimpl; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import org.sosy_lab.java_smt.api.proofs.ProofDAG; +import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.visitors.ProofVisitor; + +/** + * A proof DAG in the proof DAG of a proof. + * + * @author Gabriel Carpio + */ +public abstract class AbstractProofDAG implements ProofDAG { + private final Map> nodes = new HashMap<>(); + private int nodeIdCounter = 0; + + @Override + public void addNode(ProofNode node) { + nodes.put(nodeIdCounter++, node); + } + + @Override + public ProofNode getNode(int nodeId) { + return nodes.get(nodeId); + } + + @Override + public void addEdge(int parentNodeId, int childNodeId) { + ProofNode parent = nodes.get(parentNodeId); + ProofNode child = nodes.get(childNodeId); + if (parent != null && child != null) { + parent.addChild(child); + } + } + + @Override + public Collection> getNodes() { + return nodes.values(); + } + + @Override + public void accept(ProofVisitor visitor) { + visitor.visitDAG(this); + } +} \ No newline at end of file diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java new file mode 100644 index 0000000000..662023defd --- /dev/null +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java @@ -0,0 +1,68 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.sosy_lab.java_smt.basicimpl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.visitors.ProofVisitor; + +/** + * A proof node in the proof DAG of a proof. + * + * @author Gabriel Carpio + */ +public abstract class AbstractProofNode implements ProofNode { + private final List> children; + private final R rule; + private final Formula formula; + + protected AbstractProofNode(R rule, Formula formula) { + this.rule = rule; + this.formula = formula; + children = new ArrayList<>(); + } + + @Override + public Formula getFormula() { + return formula; + } + + @Override + public List> getChildren() { + return Collections.unmodifiableList(children); + } + + @Override + public void addChild(ProofNode child) { + children.add(child); + } + + public R getRule() { + return rule; + } + + @Override + public boolean isSource() { + return false; + } + + @Override + public boolean isSink() { + return children.isEmpty(); + } + + @Override + public void accept(ProofVisitor visitor) { + visitor.visitNode(this); + } +} \ No newline at end of file diff --git a/src/org/sosy_lab/java_smt/resProofRule.java b/src/org/sosy_lab/java_smt/resProofRule.java new file mode 100644 index 0000000000..cb111a1011 --- /dev/null +++ b/src/org/sosy_lab/java_smt/resProofRule.java @@ -0,0 +1,145 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt; + +/** + * A proof rule in the proof DAG of the internal proof format of JavaSMT. + * + * @author Gabriel Carpio + */ +public class resProofRule { + + /** + * Any operation that proves a term. + */ + public enum Rule{ + //Resolution Rule + RESOLUTION("res", "(res t proof1 proof2)"), + // Logical operators + TRUE_POSITIVE("true+", "(+ true)"), + FALSE_NEGATIVE("false-", "(- false)"), + NOT_POSITIVE("not+", "(+ (not p0) + p0)"), + NOT_NEGATIVE("not-", "(- (not p0) - p0)"), + AND_POSITIVE("and+", "(+ (and p0 … pn) - p0 … - pn)"), + AND_NEGATIVE("and-", "(- (and p0 … pn) + pi)"), + OR_POSITIVE("or+", "(+ (or p0 … pn) - pi)"), + OR_NEGATIVE("or-", "(- (or p0 … pn) + p0 … + pn)"), + IMPLIES_POSITIVE("=>+", "(+ (=> p0 … pn) +/- pi)"), + IMPLIES_NEGATIVE("=>-", "(- (=> p0 … pn) - p0 … + pn)"), + EQUAL_POSITIVE1("=+1", "(+ (= p0 p1) + p0 + p1)"), + EQUAL_NEGATIVE1("=-1", "(- (= p0 p1) + p0 - p1)"), + EQUAL_POSITIVE2("=+2", "(+ (= p0 p1) - p0 - p1)"), + EQUAL_NEGATIVE2("=-2", "(- (= p0 p1) - p0 + p1)"), + XOR_POSITIVE("xor+", "(+(xor l1) +(xor l2) -(xor l3))"), + XOR_NEGATIVE("xor-", "(-(xor l1) -(xor l2) -(xor l3))"), + + // Quantifiers + FORALL_POSITIVE("forall+", "(+ (forall x (F x)) - (F (choose x (F x))))"), + FORALL_NEGATIVE("forall-", "(- (forall x (F x)) + (F t))"), + EXISTS_POSITIVE("exists+", "(+ (exists x (F x)) - (F t))"), + EXISTS_NEGATIVE("exists-", "(- (exists x (F x)) + (F (choose x (F x))))"), + + // Equality axioms + REFLEXIVITY("refl", "(+ (= t t))"), + SYMMETRY("symm", "(+(= t0 t1) -(= t1 t0))"), + TRANSITIVITY("trans", "(+(= t0 tn) -(= t0 t1) … -(= tn-1 tn))"), + CONGRUENCE("cong", "(+(= (f t0 … tn) (f t0' … tn')) -(= t0 t0') … -(= tn tn'))"), + EQUALITY_POSITIVE("=+", "(+ (= t0 … tn) -(= t0 t1) … -(= tn-1 tn))"), + EQUALITY_NEGATIVE("=-", "(- (= t0 … tn) +(= ti tj))"), + DISTINCT_POSITIVE("distinct+", "(+ (distinct t0 … tn) +(= t0 t1) … +(= t0 tn) … +(= tn-1 tn))"), + DISTINCT_NEGATIVE("distinct-", "(- (distinct t0 … tn) -(= ti tj))"), + + // ITE, define-fun, annotations + ITE1("ite1", "(+(= (ite t0 t1 t2) t1) - t0)"), + ITE2("ite2", "(+(= (ite t0 t1 t2) t2) + t0)"), + DEL("del!", "(+(= (! t :annotation…) t))"), + EXPAND("expand", "(+(= (f t0 … tn) (let ((x0 t0)…(xn tn)) d)))"), + + // Array Theory + SELECTSTORE1("selectstore1", "(+ (= (select (store a i v) i) v))"), + SELECTSTORE2("selectstore2", "(+ (= (select (store a i v) j) (select a j)) (= i j))"), + EXTDIFF("extdiff", "(+ (= a b) (- (= (select a (@diff a b)) (select b (@diff a b)))))"), + CONST("const", "(+ (= (select (@const v) i) v))"), + + // Linear Arithmetic + POLY_ADD("poly+", "(+ (= (+ a1 ... an) a))"), + POLY_MUL("poly*", "(+ (= (* a1 ... an) a))"), + TO_REAL("to_real", "(+ (= (to_real a) a'))"), + FARKAS("farkas", "(- (<=? a1 b1) ... - (<=? an bn))"), + TRICHOTOMY("trichotomy", "(+ (< a b) (= a b) (< b a))"), + TOTAL("total", "(+ (<= a b) (< b a))"), + GT_DEF("gt_def", "(+ (= (> a b) (< b a)))"), + GE_DEF("ge_def", "(+ (= (>= a b) (<= b a)))"), + DIV_DEF("div_def", "(+ (= a (* b1 ... bn (/ a b1 ... bn))) (= b1 0) ... (= bn 0))"), + NEG_DEF("neg_def", "(+ (= (- a) (* (- 1) a)))"), + NEG_DEF2("neg_def2", "(+ (= (- a b1 ... bn) (+ a (* (- 1) b1)) ... (* (- 1) bn)))"), + ABS_DEF("abs_def", "(+ (= (abs x) (ite (< x 0) (- x) x)))"), + TOTAL_INT("total_int", "(+ (<= a c) (<= (c+1) a))"), + TO_INT_LOW("to_int_low", "(+ (<= (to_real (to_int x)) x))"), + TO_INT_HIGH("to_int_high", "(+ (< x (+ (to_real (to_int x)) 1.0)))"), + DIV_LOW("div_low", "(+ (<= (* d (div x d)) x) (= d 0))"), + DIV_HIGH("div_high", "(+ (< x (+ (* d (div x d)) (abs d))) (= d 0))"), + MOD_DEF("mod_def", "(+ (= (mod x d) (- x (* d (div x d)))) (= d 0))"), + DIVISIBLE_DEF("divisible_def", "(+ (= ((_ divisible c) x) (= x (* c (div x c)))))"), + EXPAND_IS_INT("expand_is_int", "(+ (= (is_int x) (= x (to_real (to_int x)))))"), + + // Data Types + DT_PROJECT("dt_project", "(= (seli (cons a1 ... an)) ai)"), + DT_CONS("dt_cons", "(~ ((_ is cons) x), (= (cons (sel1 x) ... (seln x)) x))"), + DT_TEST_CONS("dt_test_cons", "((_ is cons) (cons a1 ... an))"), + DT_TEST_CONS_PRIME("dt_test_cons_prime", "(~ ((_ is cons') (cons a1 ... an)))"), + DT_EXHAUST("dt_exhaust", "((_ is cons1) x), ..., ((_ is consn) x)"), + DT_ACYCLIC("dt_acyclic", "(~ (= (cons ... x ...) x))"), + DT_MATCH("dt_match", + "(= (match t ((p1 x1) c1) ...) (ite ((_ is p1) t) (let (x1 (sel1 t)) c1) ...))"); + + private final String name; + private final String clause; + + Rule(String name, String clause) { + this.name = name; + this.clause = clause; + } + + public String getName() { + return name; + } + + public String getClause() { + return clause; + } + } + + /** + * Retrieves a ProofRule by its name. + * + * @param name The name of the proof rule. + * @return The matching ProofRule, or null if not found. + */ + public static Rule getRuleByName(String name) { + for (Rule rule : Rule.values()) { + if (rule.getName().equalsIgnoreCase(name)) { + return rule; + } + } + throw new IllegalArgumentException("Rule not found or not specified: " + name); + } + + /** + * Prints all proof rules for debugging or inspection. + */ + public static void printAllRules() { + System.out.println("Available Proof Rules:"); + for (Rule rule : Rule.values()) { + System.out.println(rule.getName() + ": " + rule.getClause()); + } + } +} From b2bc9ebede550c19d3f7f837ef6d613a71f5003b Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 17 Feb 2025 19:43:40 +0100 Subject: [PATCH 002/132] Added GENERATE_PROOFS to ProverOptions --- src/org/sosy_lab/java_smt/api/SolverContext.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/org/sosy_lab/java_smt/api/SolverContext.java b/src/org/sosy_lab/java_smt/api/SolverContext.java index 3fbd476c77..a963269fc0 100644 --- a/src/org/sosy_lab/java_smt/api/SolverContext.java +++ b/src/org/sosy_lab/java_smt/api/SolverContext.java @@ -52,6 +52,11 @@ enum ProverOptions { */ GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS, + /** + * Whether the solver should generate proofs for unsatisfiable formulas. + */ + GENERATE_PROOFS, + /** Whether the solver should enable support for formulae build in SL theory. */ ENABLE_SEPARATION_LOGIC } From 766e66588f8230510b660b20aff6716cc2f0cca0 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 17 Feb 2025 22:16:10 +0100 Subject: [PATCH 003/132] Added implementation of getProof for SMTInterpol. Changed default behaviour of getProof to return unsupported operation. --- .../java_smt/api/BasicProverEnvironment.java | 9 +++++++- .../java_smt/basicimpl/AbstractProver.java | 6 +++++ .../SmtInterpolAbstractProver.java | 22 +++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java b/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java index 652b10b801..6bd3814923 100644 --- a/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java @@ -155,7 +155,14 @@ default ImmutableMap getStatistics() { * Get proof of unsatisfiability of the conjuction of the current satck of all formulas. Should * only be called after {@link #isUnsat()} returned true. */ - ProofDAG getProof() throws SolverException, InterruptedException; + default ProofDAG getProof() throws SolverException, InterruptedException { + try { + throw new UnsupportedOperationException("Proof generation isn't enabled."); + } catch (UnsupportedOperationException e) { + System.out.println(e.getMessage()); + throw e; + } + } /** * Closes the prover environment. The object should be discarded, and should not be used after diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java index 07dbbbb5d6..baa7dc07d1 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java @@ -33,6 +33,7 @@ public abstract class AbstractProver implements BasicProverEnvironment { private final boolean generateAllSat; protected final boolean generateUnsatCores; private final boolean generateUnsatCoresOverAssumptions; + private final boolean generateProofs; protected final boolean enableSL; protected boolean closed = false; @@ -53,6 +54,7 @@ protected AbstractProver(Set pOptions) { generateUnsatCores = pOptions.contains(ProverOptions.GENERATE_UNSAT_CORE); generateUnsatCoresOverAssumptions = pOptions.contains(ProverOptions.GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS); + generateProofs = pOptions.contains(ProverOptions.GENERATE_PROOFS); enableSL = pOptions.contains(ProverOptions.ENABLE_SEPARATION_LOGIC); assertedFormulas.add(LinkedHashMultimap.create()); @@ -77,6 +79,10 @@ protected final void checkGenerateUnsatCoresOverAssumptions() { ProverOptions.GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS); } + protected final void checkGenerateProofs() { + Preconditions.checkState(generateProofs, TEMPLATE, ProverOptions.GENERATE_PROOFS); + } + protected final void checkEnableSeparationLogic() { Preconditions.checkState(enableSL, TEMPLATE, ProverOptions.ENABLE_SEPARATION_LOGIC); } diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java index 97c185ba00..9666c7e391 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java @@ -37,10 +37,12 @@ import org.sosy_lab.common.collect.Collections3; import org.sosy_lab.common.collect.PathCopyingPersistentTreeMap; import org.sosy_lab.common.collect.PersistentMap; +import org.sosy_lab.java_smt.ResolutionProofDAG; import org.sosy_lab.java_smt.api.BasicProverEnvironment; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; +import org.sosy_lab.java_smt.api.proofs.ProofDAG; import org.sosy_lab.java_smt.basicimpl.AbstractProver; import org.sosy_lab.java_smt.basicimpl.CachingModel; import org.sosy_lab.java_smt.basicimpl.FormulaCreator; @@ -213,6 +215,26 @@ public ImmutableMap getStatistics() { return builder.buildOrThrow(); } + @Override + public ProofDAG getProof() { + checkState(!closed); + checkGenerateProofs(); + final Term proof; + try { + proof = env.getProof(); + } catch (SMTLIBException e) { + if (e.getMessage().contains("Context is inconsistent")) { + throw new IllegalStateException("Cannot get proof from satisfiable environment", e); + } else { + throw e; + } + } + + ResolutionProofDAG proofDag = new ResolutionProofDAG<>(); + //convertToResolutionProof(proof, proofDag, creator); + return proofDag; + } + @Override public void close() { if (!closed) { From ca725ba439a8433c158ab3f480414f51cb37b67b Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 3 Mar 2025 17:33:42 +0100 Subject: [PATCH 004/132] Added ProofTermParser to transform a proof DAG made out of Term objects from SMTInterpol to a ResolutionProofDAG. Not working. Class SmtInterpolProofNode should help transform from the internal SMTInterpol proof representation to ResolutionProofDAG. Not working. Added some tests to evaluate proofs given back by SMTInterpol and the ResolutionProofDAG objects that should be returned. --- .../{resProofRule.java => ResProofRule.java} | 14 +- .../sosy_lab/java_smt/ResolutionProofDAG.java | 74 ++++- .../java_smt/ResolutionProofNode.java | 10 +- .../sosy_lab/java_smt/SourceProofNode.java | 7 +- .../java_smt/api/BasicProverEnvironment.java | 15 +- .../java_smt/api/proofs/ProofDAG.java | 3 +- .../java_smt/api/proofs/ProofFactory.java | 6 +- .../java_smt/basicimpl/AbstractProofDAG.java | 3 +- .../solvers/smtinterpol/ProofTermParser.java | 198 +++++++++++++ .../SmtInterpolAbstractProver.java | 15 +- .../smtinterpol/SmtInterpolProofNode.java | 271 ++++++++++++++++++ .../smtinterpol/SmtInterpolProofsTest.java | 205 +++++++++++++ .../smtinterpol/SmtInterpolSolverContext.java | 3 + 13 files changed, 789 insertions(+), 35 deletions(-) rename src/org/sosy_lab/java_smt/{resProofRule.java => ResProofRule.java} (95%) create mode 100644 src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java create mode 100644 src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNode.java create mode 100644 src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java diff --git a/src/org/sosy_lab/java_smt/resProofRule.java b/src/org/sosy_lab/java_smt/ResProofRule.java similarity index 95% rename from src/org/sosy_lab/java_smt/resProofRule.java rename to src/org/sosy_lab/java_smt/ResProofRule.java index cb111a1011..3bcd9da866 100644 --- a/src/org/sosy_lab/java_smt/resProofRule.java +++ b/src/org/sosy_lab/java_smt/ResProofRule.java @@ -15,14 +15,16 @@ * * @author Gabriel Carpio */ -public class resProofRule { +public class ResProofRule { /** * Any operation that proves a term. */ - public enum Rule{ + public enum ResAxiom { //Resolution Rule RESOLUTION("res", "(res t proof1 proof2)"), + + ASSUME("assume", "(assume t)"), // Logical operators TRUE_POSITIVE("true+", "(+ true)"), FALSE_NEGATIVE("false-", "(- false)"), @@ -104,7 +106,7 @@ public enum Rule{ private final String name; private final String clause; - Rule(String name, String clause) { + ResAxiom(String name, String clause) { this.name = name; this.clause = clause; } @@ -124,8 +126,8 @@ public String getClause() { * @param name The name of the proof rule. * @return The matching ProofRule, or null if not found. */ - public static Rule getRuleByName(String name) { - for (Rule rule : Rule.values()) { + public static ResAxiom getRuleByName(String name) { + for (ResAxiom rule : ResAxiom.values()) { if (rule.getName().equalsIgnoreCase(name)) { return rule; } @@ -138,7 +140,7 @@ public static Rule getRuleByName(String name) { */ public static void printAllRules() { System.out.println("Available Proof Rules:"); - for (Rule rule : Rule.values()) { + for (ResAxiom rule : ResAxiom.values()) { System.out.println(rule.getName() + ": " + rule.getClause()); } } diff --git a/src/org/sosy_lab/java_smt/ResolutionProofDAG.java b/src/org/sosy_lab/java_smt/ResolutionProofDAG.java index 6853c30ab5..b613379c9a 100644 --- a/src/org/sosy_lab/java_smt/ResolutionProofDAG.java +++ b/src/org/sosy_lab/java_smt/ResolutionProofDAG.java @@ -10,23 +10,89 @@ package org.sosy_lab.java_smt; +import com.google.common.collect.ImmutableSet; +import de.uni_freiburg.informatik.ultimate.logic.AnnotatedTerm; +import de.uni_freiburg.informatik.ultimate.logic.Annotation; +import de.uni_freiburg.informatik.ultimate.logic.FunctionSymbol; +import de.uni_freiburg.informatik.ultimate.logic.Script; +import de.uni_freiburg.informatik.ultimate.logic.Sort; +import de.uni_freiburg.informatik.ultimate.logic.Term; +import de.uni_freiburg.informatik.ultimate.smtinterpol.dpll.Clause; +import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.ResolutionNode; +import java.util.Map; +import org.sosy_lab.java_smt.ResProofRule.ResAxiom; +import org.sosy_lab.java_smt.api.BooleanFormula; +import org.sosy_lab.java_smt.api.FormulaManager; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.AbstractProofDAG; +import org.sosy_lab.java_smt.basicimpl.FormulaCreator; +import org.sosy_lab.java_smt.solvers.smtinterpol.ProofTermParser; + +public class ResolutionProofDAG extends AbstractProofDAG { + + public ResolutionProofDAG() { + super(); + } + + /** + * Converts the proof Term returned from SMTInterpol into a ResolutionProofDAG. + * This version traverses AnnotatedTerm instances looking for annotations with key + * ProofConstants.ANNOTKEY_PROVES and uses the associated clause string. + * + * @param proof the proof term + * @return a ResolutionProofDAG representing the proof + */ + public static ResolutionProofDAG fromTerm( + Term proof, FormulaManager pManager, + Map pAnnotatedTerms) { + + // Use our new ProofTermParser to convert the proof term to a ResolutionProofDAG + return ProofTermParser.convert(proof, pManager, pAnnotatedTerms); + } + + /** + * Recursively traverses the annotated proof term. + * + * @param term the current term + * @param dag the proof DAG being constructed + * @param parentClause the clause from the parent annotation (if available) + */ + private static void traverseTerm(Term term, ResolutionProofDAG dag, ProofNode parentClause) { + if (term instanceof AnnotatedTerm) { + AnnotatedTerm annotatedTerm = (AnnotatedTerm) term; + for (Annotation annotation : annotatedTerm.getAnnotations()) { + /* + if (annotation.getKey().equals(ProofConstants.ANNOTKEY_PROVES)) { + //ProofNode clause = annotation.getValue().toString(); + if (parentClause != null) { + dag.addEdge(parentClause, clause); + } else { + dag.addNode(clause); + } + for (Term subTerm : annotatedTerm.getSubterms()) { + traverseTerm(subTerm, dag, clause); + } + } + + */ + } + } + } + -public class ResolutionProofDAG extends AbstractProofDAG { @Override - public void addNode(ProofNode node) { + public void addNode(ProofNode node) { super.addNode(node); } @Override - public ProofNode getNode(int nodeId) { + public ProofNode getNode(int nodeId) { return super.getNode(nodeId); } @Override - public void addEdge(int parentNodeId, int childNodeId) { + public void addEdge(ProofNode parentNodeId, ProofNode childNodeId) { super.addEdge(parentNodeId, childNodeId); } } diff --git a/src/org/sosy_lab/java_smt/ResolutionProofNode.java b/src/org/sosy_lab/java_smt/ResolutionProofNode.java index be782d9001..da6b3da361 100644 --- a/src/org/sosy_lab/java_smt/ResolutionProofNode.java +++ b/src/org/sosy_lab/java_smt/ResolutionProofNode.java @@ -13,15 +13,15 @@ import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; -import org.sosy_lab.java_smt.resProofRule.Rule; +import org.sosy_lab.java_smt.ResProofRule.ResAxiom; -public class ResolutionProofNode extends AbstractProofNode - implements ProofNode { +public class ResolutionProofNode extends AbstractProofNode + implements ProofNode { private final Formula pivot; public ResolutionProofNode(Formula formula, Formula pivot) { - super(Rule.RESOLUTION, formula); + super(ResAxiom.RESOLUTION, formula); this.pivot = pivot; } @@ -35,7 +35,7 @@ public Formula getPivot() { return pivot; } - public Rule getRule() { + public ResAxiom getRule() { return super.getRule(); } } diff --git a/src/org/sosy_lab/java_smt/SourceProofNode.java b/src/org/sosy_lab/java_smt/SourceProofNode.java index 22bc300584..658867db8b 100644 --- a/src/org/sosy_lab/java_smt/SourceProofNode.java +++ b/src/org/sosy_lab/java_smt/SourceProofNode.java @@ -13,12 +13,13 @@ import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; +import org.sosy_lab.java_smt.ResProofRule.ResAxiom; -public class SourceProofNode extends AbstractProofNode - implements ProofNode { +public class SourceProofNode extends AbstractProofNode + implements ProofNode { - public SourceProofNode(resProofRule.Rule rule, Formula formula) { + public SourceProofNode(ResAxiom rule, Formula formula) { super(rule, formula); } diff --git a/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java b/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java index 6bd3814923..03efd7a1eb 100644 --- a/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java @@ -33,7 +33,7 @@ public interface BasicProverEnvironment extends AutoCloseable { */ @Nullable @CanIgnoreReturnValue - default T push(BooleanFormula f) throws InterruptedException, SolverException { + default T push(BooleanFormula f) throws InterruptedException { push(); return addConstraint(f); } @@ -47,7 +47,7 @@ default T push(BooleanFormula f) throws InterruptedException, SolverException { /** Add a constraint to the latest backtracking point. */ @Nullable @CanIgnoreReturnValue - T addConstraint(BooleanFormula constraint) throws InterruptedException, SolverException; + T addConstraint(BooleanFormula constraint) throws InterruptedException; /** * Create a new backtracking point, i.e., a new level on the assertion stack. Each level can hold @@ -56,7 +56,7 @@ default T push(BooleanFormula f) throws InterruptedException, SolverException { *

If formulas are added before creating the first backtracking point, they can not be removed * via a POP-operation. */ - void push() throws InterruptedException, SolverException; + void push() throws InterruptedException; /** * Get the number of backtracking points/levels on the current stack. @@ -88,7 +88,7 @@ boolean isUnsatWithAssumptions(Collection assumptions) *

A model might contain additional symbols with their evaluation, if a solver uses its own * temporary symbols. There should be at least a value-assignment for each free symbol. */ - Model getModel() throws SolverException, InterruptedException; + Model getModel() throws SolverException; /** * Get a temporary view on the current satisfying assignment. This should be called only @@ -96,7 +96,7 @@ boolean isUnsatWithAssumptions(Collection assumptions) * should no longer be used as soon as any constraints are added to, pushed, or popped from the * prover stack. */ - default Evaluator getEvaluator() throws InterruptedException, SolverException { + default Evaluator getEvaluator() throws SolverException { return getModel(); } @@ -108,8 +108,7 @@ default Evaluator getEvaluator() throws InterruptedException, SolverException { *

Note that if you need to iterate multiple times over the model it may be more efficient to * use this method instead of {@link #getModel()} (depending on the solver). */ - default ImmutableList getModelAssignments() - throws SolverException, InterruptedException { + default ImmutableList getModelAssignments() throws SolverException { try (Model model = getModel()) { return model.asList(); } @@ -155,7 +154,7 @@ default ImmutableMap getStatistics() { * Get proof of unsatisfiability of the conjuction of the current satck of all formulas. Should * only be called after {@link #isUnsat()} returned true. */ - default ProofDAG getProof() throws SolverException, InterruptedException { + default ProofDAG getProof() { try { throw new UnsupportedOperationException("Proof generation isn't enabled."); } catch (UnsupportedOperationException e) { diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java b/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java index ca7265879a..49cdf137f6 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java @@ -11,12 +11,13 @@ package org.sosy_lab.java_smt.api.proofs; import java.util.Collection; +import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.api.proofs.visitors.ProofVisitor; public interface ProofDAG { void addNode(ProofNode node); ProofNode getNode(int nodeId); - void addEdge(int parentNodeId, int childNodeId); + void addEdge(ProofNode parentNodeId, ProofNode childNodeId); Collection> getNodes(); void accept(ProofVisitor visitor); // To allow traversal of the entire DAG } diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java index 0060e051cf..7b4679875d 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java @@ -13,14 +13,14 @@ import org.sosy_lab.java_smt.ResolutionProofNode; import org.sosy_lab.java_smt.SourceProofNode; import org.sosy_lab.java_smt.api.Formula; -import org.sosy_lab.java_smt.resProofRule.Rule; +import org.sosy_lab.java_smt.ResProofRule.ResAxiom; public class ProofFactory { - public static ProofNode createSourceNode(Rule rule, Formula formula) { + public static ProofNode createSourceNode(ResAxiom rule, Formula formula) { return new SourceProofNode(rule, formula); } - public static ProofNode createResolutionNode(Formula formula, Formula pivot) { + public static ProofNode createResolutionNode(Formula formula, Formula pivot) { return new ResolutionProofNode(formula, pivot); } } diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java index acd13a0b6e..56783f38c5 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java @@ -13,6 +13,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; +import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.api.proofs.ProofDAG; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.api.proofs.visitors.ProofVisitor; @@ -37,7 +38,7 @@ public ProofNode getNode(int nodeId) { } @Override - public void addEdge(int parentNodeId, int childNodeId) { + public void addEdge(ProofNode parentNodeId, ProofNode childNodeId) { ProofNode parent = nodes.get(parentNodeId); ProofNode child = nodes.get(childNodeId); if (parent != null && child != null) { diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java new file mode 100644 index 0000000000..e4d7e9363a --- /dev/null +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java @@ -0,0 +1,198 @@ +package org.sosy_lab.java_smt.solvers.smtinterpol; + +import de.uni_freiburg.informatik.ultimate.logic.AnnotatedTerm; +import de.uni_freiburg.informatik.ultimate.logic.Annotation; +import de.uni_freiburg.informatik.ultimate.logic.ApplicationTerm; +import de.uni_freiburg.informatik.ultimate.logic.LetTerm; +import de.uni_freiburg.informatik.ultimate.logic.Term; +import de.uni_freiburg.informatik.ultimate.logic.TermVariable; +import java.util.HashMap; +import java.util.Map; +import org.sosy_lab.java_smt.ResProofRule; +import org.sosy_lab.java_smt.ResProofRule.ResAxiom; +import org.sosy_lab.java_smt.ResolutionProofDAG; +import org.sosy_lab.java_smt.api.BooleanFormula; +import org.sosy_lab.java_smt.api.FormulaManager; +import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.basicimpl.AbstractProofDAG; +import org.sosy_lab.java_smt.basicimpl.FormulaCreator; + +public class ProofTermParser { + + private final ResolutionProofDAG proofDag; + private final Map annotatedTerms; + private final Map letBindings = new HashMap<>(); + private final Map> termToNode = new HashMap<>(); + private final FormulaManager mgr; + + public ProofTermParser(Map pAnnotatedTerms, FormulaManager pMgr) { + annotatedTerms = pAnnotatedTerms; + mgr = pMgr; + proofDag = new ResolutionProofDAG(); + } + + + public static ResolutionProofDAG convert( + Term proof, + FormulaManager pManager, + Map pAnnotatedTerms) { + ProofTermParser parser = new ProofTermParser(pAnnotatedTerms, pManager); + ProofNode rootNode = parser.parseProofTerm(proof); + if (rootNode != null) { + parser.proofDag.addNode(rootNode); + } + return parser.proofDag; + } + + + public ProofNode parseProofTerm(Term term) { + if (termToNode.containsKey(term)) { + return termToNode.get(term); + } + + ProofNode node = null; + + if (term instanceof AnnotatedTerm) { + node = parseAnnotatedTerm((AnnotatedTerm) term); + } else if (term instanceof ApplicationTerm) { + node = parseApplicationTerm((ApplicationTerm) term); + } else if (term instanceof LetTerm) { + node = parseLetTerm((LetTerm) term); + } + + if (node != null) { + termToNode.put(term, node); + } + + return node; + } + + private ProofNode parseAnnotatedTerm(AnnotatedTerm term) { + for (Annotation annotation : term.getAnnotations()) { + if (annotation.getKey().equals(":proves") || annotation.getKey().equals(":rup") + || annotation.getKey().equals(":input")) { + Term formulaTerm = extractFormulaFromAnnotation(annotation); + BooleanFormula formula = getBooleanFormulaFromTerm(formulaTerm); + ProofNode node = createSourceNode(ResAxiom.RESOLUTION, formula); + return node; + } + } + return parseProofTerm(term.getSubterm()); + } + + private ProofNode parseApplicationTerm(ApplicationTerm term) { + String funcName = term.getFunction().getName(); + Term[] params = term.getParameters(); + + if (funcName.equals("..res") && params.length >= 3) { + Term clauseTerm = params[0]; + BooleanFormula formula = getBooleanFormulaFromTerm(clauseTerm); + ProofNode resNode = createSourceNode(ResAxiom.RESOLUTION, formula); + + for (int i = 1; i < params.length; i++) { + ProofNode childNode = parseProofTerm(params[i]); + if (childNode != null) { + proofDag.addEdge(resNode, childNode); + } + } + return resNode; + } else if (funcName.equals("..assume") && params.length > 0) { + Term assumedFormula = params[0]; + BooleanFormula formula = getBooleanFormulaFromTerm(assumedFormula); + return createSourceNode(ResAxiom.ASSUME, formula); + } else if (funcName.equals("..axiom") && params.length > 0) { + Term axiomFormula = params[0]; + BooleanFormula formula = getBooleanFormulaFromTerm(axiomFormula); + ResAxiom axiomType = inferAxiomType(funcName, params); + return createSourceNode(axiomType, formula); + } else if (funcName.startsWith("@")) { + String lemmaType = funcName.substring(1); + ResAxiom axiomType = mapTheoryLemmaToAxiom(lemmaType); + + if (params.length > 0) { + Term lemmaFormula = params[0]; + BooleanFormula formula = getBooleanFormulaFromTerm(lemmaFormula); + return createSourceNode(axiomType, formula); + } + } + + ProofNode lastNode = null; + for (Term param : params) { + lastNode = parseProofTerm(param); + } + + return lastNode; + } + + private ProofNode parseLetTerm(LetTerm term) { + Map oldBindings = new HashMap<>(letBindings); + TermVariable[] vars = term.getVariables(); + Term[] values = term.getValues(); + + for (int i = 0; i < vars.length; i++) { + letBindings.put(vars[i].getName(), values[i]); + } + + ProofNode result = parseProofTerm(term.getSubTerm()); + letBindings.clear(); + letBindings.putAll(oldBindings); + + return result; + } + + private Term extractFormulaFromAnnotation(Annotation annotation) { + Object value = annotation.getValue(); + if (value instanceof Term) { + return (Term) value; + } + return null; + } + + private String extractName(Term term) { + if (term instanceof AnnotatedTerm) { + for (Annotation annot : ((AnnotatedTerm) term).getAnnotations()) { + if (":named".equals(annot.getKey())) { + return annot.getValue().toString(); + } + } + } + return null; + } + + private BooleanFormula getBooleanFormulaFromTerm(Term term) { + String name = extractName(term); + if (name != null && annotatedTerms.containsKey(name)) { + return annotatedTerms.get(name); + } + return ((SmtInterpolFormulaManager) mgr).encapsulateBooleanFormula(term); + } + + private ProofNode createSourceNode(ResAxiom rule, BooleanFormula formula) { + ProofNode node = new org.sosy_lab.java_smt.SourceProofNode(rule, formula); + proofDag.addNode(node); + return node; + } + + private ResAxiom inferAxiomType(String funcName, Term[] params) { + return ResAxiom.RESOLUTION; + } + + private ResAxiom mapTheoryLemmaToAxiom(String lemmaType) { + switch (lemmaType) { + case "equalsTransitive": + return ResAxiom.TRANSITIVITY; + case "equalsSymmetric": + return ResAxiom.SYMMETRY; + case "equalsReflexive": + return ResAxiom.REFLEXIVITY; + case "distinctNegation": + return ResAxiom.DISTINCT_NEGATIVE; + case "store": + return ResAxiom.SELECTSTORE1; + case "select": + return ResAxiom.SELECTSTORE2; + default: + return ResAxiom.RESOLUTION; + } + } +} \ No newline at end of file diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java index 9666c7e391..f1ba6c4a93 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java @@ -37,6 +37,7 @@ import org.sosy_lab.common.collect.Collections3; import org.sosy_lab.common.collect.PathCopyingPersistentTreeMap; import org.sosy_lab.common.collect.PersistentMap; +import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.ResolutionProofDAG; import org.sosy_lab.java_smt.api.BasicProverEnvironment; import org.sosy_lab.java_smt.api.BooleanFormula; @@ -216,12 +217,15 @@ public ImmutableMap getStatistics() { } @Override - public ProofDAG getProof() { + public ProofDAG getProof() { checkState(!closed); checkGenerateProofs(); + final Term proof; + final ProofDAG proofDAG; try { proof = env.getProof(); + proofDAG = ResolutionProofDAG.fromTerm(proof, mgr, annotatedTerms.peek()); } catch (SMTLIBException e) { if (e.getMessage().contains("Context is inconsistent")) { throw new IllegalStateException("Cannot get proof from satisfiable environment", e); @@ -230,9 +234,12 @@ public ProofDAG getProof() { } } - ResolutionProofDAG proofDag = new ResolutionProofDAG<>(); - //convertToResolutionProof(proof, proofDag, creator); - return proofDag; + //ResolutionProofDAG proofDag = fromSmtInterpol(proof, creator, getAssertedFormulas()); + return proofDAG; + } + + protected Term smtInterpolGetProof() { + return env.getProof(); } @Override diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNode.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNode.java new file mode 100644 index 0000000000..541ee2a3c2 --- /dev/null +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNode.java @@ -0,0 +1,271 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.solvers.smtinterpol; + +import de.uni_freiburg.informatik.ultimate.logic.AnnotatedTerm; +import de.uni_freiburg.informatik.ultimate.logic.Annotation; +import de.uni_freiburg.informatik.ultimate.logic.Term; +import de.uni_freiburg.informatik.ultimate.logic.Theory; +import de.uni_freiburg.informatik.ultimate.smtinterpol.dpll.Clause; +import de.uni_freiburg.informatik.ultimate.smtinterpol.dpll.IAnnotation; +import de.uni_freiburg.informatik.ultimate.smtinterpol.dpll.Literal; +import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.LeafNode; +import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.ProofNode; +import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.ProofRules; + +import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.ResolutionNode; +import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.ResolutionNode.Antecedent; +import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.SourceAnnotation; +import de.uni_freiburg.informatik.ultimate.smtinterpol.theory.cclosure.CCAnnotation; +import de.uni_freiburg.informatik.ultimate.smtinterpol.theory.linar.EQAnnotation; +import de.uni_freiburg.informatik.ultimate.smtinterpol.theory.linar.LAAnnotation; +import de.uni_freiburg.informatik.ultimate.smtinterpol.theory.quant.QuantAnnotation; +import java.util.Map; +import org.sosy_lab.java_smt.ResProofRule; +import org.sosy_lab.java_smt.ResProofRule.ResAxiom; +import org.sosy_lab.java_smt.ResolutionProofDAG; +import org.sosy_lab.java_smt.ResolutionProofNode; +import org.sosy_lab.java_smt.SourceProofNode; +import org.sosy_lab.java_smt.api.BooleanFormula; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; + + +class SmtInterpolProofNode extends AbstractProofNode { + static class ResolutionProofDAGBuilder { + private final SmtInterpolFormulaCreator creator; + private Theory theory; + + public ResolutionProofDAGBuilder(SmtInterpolFormulaCreator creator) { + this.creator = creator; + } + + /* + // Morris traversal that processes every node and returns the created ResolutionProofDAG. + public static ResolutionProofDAG buildDag(SmtInterpolProofNode root) { + SmtInterpolProofNode current = root; + // Morris Traversal: process each node in inorder without extra stack. + while (current != null) { + if (current.getLeft() == null) { + current.processNode(); + current = current.getRight(); + } else { + SmtInterpolProofNode predecessor = current.getLeft(); + while (predecessor.getRight() != null && predecessor.getRight() != current) { + predecessor = predecessor.getRight(); + } + if (predecessor.getRight() == null) { + predecessor.setRight(current); // create temporary thread + current = current.getLeft(); + } else { + predecessor.setRight(null); // remove the thread + current = current.getRight(); + } + } + } + // Create DAG from the processed tree. + ResolutionProofDAG dag = new ResolutionProofDAG(); + addDagEdges(root, dag); + return dag; + } + */ + + // Recursively adds nodes and edges from the tree to the dag. + private static void addDagEdges(SmtInterpolProofNode node, ResolutionProofDAG dag) { + if (node == null) { + return; + } + dag.addNode(node.getTransformed()); + if (node.getLeft() != null) { + dag.addEdge(node.getTransformed(), node.getLeft().getTransformed()); + addDagEdges(node.getLeft(), dag); + } + if (node.getRight() != null) { + dag.addEdge(node.getTransformed(), node.getRight().getTransformed()); + addDagEdges(node.getRight(), dag); + } + } + + public void processResNode(SmtInterpolProofNode node) { + if (node.getLeft() == null && node.getRight() == null) { + throw new UnsupportedOperationException("Cannot process leaf node"); + } else { + ResolutionNode rn = (ResolutionNode) node.node; + Antecedent[] antecedents = rn.getAntecedents(); + Literal pivot = antecedents[0].mPivot; + node.transformed = new ResolutionProofNode(node.getFormula(), + creator.encapsulateBoolean(pivot.getSMTFormula(theory))); + } + } + + /* + public void processSourceNode(SmtInterpolProofNode node) { + if (node.getLeft() == null && node.getRight() == null) { + node.transformed = new SourceProofNode(node.getFormula()); + } else { + throw new UnsupportedOperationException("Cannot process resolution node"); + } + } + */ + } + + private static ProofNode node; + private SmtInterpolProofNode left; + private SmtInterpolProofNode right; + private org.sosy_lab.java_smt.api.proofs.ProofNode transformed; + + + protected SmtInterpolProofNode(String rule, Formula formula) { + super(rule, formula); + } + + /* + public static SmtInterpolProofNode create( + Clause pClause, Theory pTheory, + Map pAnnotatedTerms, SmtInterpolFormulaCreator pCreator) { + Term clsAsTerm = pClause.toTerm(pTheory); + boolean createFormula = true; + String termName = null; + ProofNode pn = pClause.getProof(); + SmtInterpolProofNode newNode; + String rule; + if (clsAsTerm instanceof AnnotatedTerm) { + termName = getTermName((AnnotatedTerm) clsAsTerm); + if (termName != null) { + createFormula = false; + } + } + + if (!pn.isLeaf()) { + rule = ProofRules.RES; + newNode = new SmtInterpolProofNode(rule, + createFormula ? pCreator.encapsulateBoolean(clsAsTerm) : pAnnotatedTerms.get(termName)); + newNode.setProofNode(pn); + ResolutionNode rn = (ResolutionNode) pn; + newNode.left = create(rn.getPrimary(), pTheory, pAnnotatedTerms, pCreator); + Antecedent[] antecedents = rn.getAntecedents(); + if (antecedents.length > 0) { + newNode.right = create(antecedents[0].mAntecedent, pTheory, pAnnotatedTerms, pCreator); + } + } else { + LeafNode ln = (LeafNode) pn; + Term res; + final IAnnotation annot = ln.getTheoryAnnotation(); + if (ln.getLeafKind() == -1) { + rule = "INPUT"; + } else if (ln.getLeafKind() >= 0) { + rule = "TAUTOLOGY"; + } + if (annot == null) { + assert ln.getLeafKind() == LeafNode.ASSUMPTION; + rule = ProofRules.ASSUME; + + } else if (annot instanceof EQAnnotation) { + rule = ProofRules.ORACLE; + + } else if (annot instanceof LAAnnotation) { + rule = + } else if (annot instanceof CCAnnotation) { + rule = + } else if (annot instanceof QuantAnnotation) { + rule = + } else if (annot instanceof SourceAnnotation) { + rule = + } + newNode = new SmtInterpolProofNode(rule, + createFormula ? pCreator.encapsulateBoolean(clsAsTerm) : pAnnotatedTerms.get(termName)); + newNode.setProofNode(pn); + } + + + return newNode; + } + */ + public org.sosy_lab.java_smt.api.proofs.ProofNode getTransformed() { + return transformed; + } + + public SmtInterpolProofNode getLeft() { + return left; + } + + public SmtInterpolProofNode getRight() { + return right; + } + + // Helper for assigning temporary thread pointers + public void setRight(SmtInterpolProofNode node) { + this.right = node; + } + + private void setProofNode(ProofNode pNode) { + this.node = pNode; + } + + private static String getTermName(AnnotatedTerm pTerm) { + for (Annotation annotation : pTerm.getAnnotations()) { + if (annotation.getKey().equals(":named")) { + return annotation.getValue().toString(); + } + } + return null; + } + + private static ProofNode getNode() { + return node; + } + + public static Term annotationMethod(Clause cls, ProofRules rule) { + ProofNode pn = cls.getProof(); + Term res = null; + final IAnnotation annot = ((LeafNode) pn).getTheoryAnnotation(); + if (annot != null) { + res = annot.toTerm(cls, rule); + } + return res; + } + + /* + + + + public static ResolutionProofDAG generateProofDAG(ProofNode node) { + ResolutionProofDAG dag = new ResolutionProofDAG(); + if (node == null) { + return dag; + } + if (node.isLeaf()) { + + } else { + ResolutionNode resNode = (ResolutionNode) node; + ResolutionNode.Antecedent[] antecedents = resNode.getAntecedents(); + if (antecedents != null) { + for (ResolutionNode.Antecedent antecedent : antecedents) { + traverse(antecedent.mAntecedent.getProof()); + } + } + } + } + + + private void predecessorSetRight(SmtInterpolProofNode predecessor, SmtInterpolProofNode thread) { + try { + Field rightField = BinaryProofNode.class.getDeclaredField("right"); + rightField.setAccessible(true); + rightField.set(predecessor, thread); + } catch (Exception e) { + throw new RuntimeException("Unable to set right field via reflection", e); + } + } + + */ + +} diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java new file mode 100644 index 0000000000..e3ee3d0f51 --- /dev/null +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java @@ -0,0 +1,205 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.solvers.smtinterpol; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import com.google.common.collect.ImmutableSet; +import de.uni_freiburg.informatik.ultimate.logic.Term; +import de.uni_freiburg.informatik.ultimate.smtinterpol.dpll.Clause; +import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.ProofNode; +import de.uni_freiburg.informatik.ultimate.smtinterpol.smtlib2.SMTInterpol; +import java.io.StringReader; +import java.lang.reflect.Method; +import java.util.Set; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.sosy_lab.common.ShutdownManager; +import org.sosy_lab.common.configuration.Configuration; +import org.sosy_lab.common.configuration.InvalidConfigurationException; +import org.sosy_lab.common.log.BasicLogManager; +import org.sosy_lab.common.log.LogManager; +import org.sosy_lab.java_smt.ResolutionProofDAG; +import org.sosy_lab.java_smt.api.BooleanFormula; +import org.sosy_lab.java_smt.api.FormulaManager; +import org.sosy_lab.java_smt.api.NumeralFormula.IntegerFormula; +import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; +import org.sosy_lab.java_smt.api.SolverException; +import org.sosy_lab.java_smt.basicimpl.AbstractFormulaManager; +import org.sosy_lab.java_smt.basicimpl.AbstractNumeralFormulaManager.NonLinearArithmetic; + +public class SmtInterpolProofsTest { + + private SmtInterpolSolverContext context; + private SmtInterpolFormulaManager mgr; + private SmtInterpolBooleanFormulaManager bmgr; + private SmtInterpolIntegerFormulaManager imgr; + + @Before + public void setupSolver() throws InvalidConfigurationException { + Configuration config = Configuration.defaultConfiguration(); + LogManager logger = BasicLogManager.create(config); + ShutdownManager shutdown = ShutdownManager.create(); + + // Create new context with SMTInterpol + context = SmtInterpolSolverContext.create( + config, + logger, + shutdown.getNotifier(), + null, // no logfile + 42, // randomSeed + NonLinearArithmetic.USE); + + // Get managers for creating formulas + mgr = (SmtInterpolFormulaManager) context.getFormulaManager(); + bmgr = (SmtInterpolBooleanFormulaManager) mgr.getBooleanFormulaManager(); + imgr = (SmtInterpolIntegerFormulaManager) mgr.getIntegerFormulaManager(); + } + + @After + public void closeSolver() { + if (context != null) { + context.close(); + } + } + + @Test + public void testGetProofTerm() throws SolverException, InterruptedException { + //example from the 2022 paper + BooleanFormula q1 = bmgr.makeVariable("q1"); + BooleanFormula q2 = bmgr.makeVariable("q2"); + BooleanFormula notQ1OrQ2 = bmgr.or(bmgr.not(q1), q2); + BooleanFormula q1True = bmgr.equivalence(q1, bmgr.makeTrue()); + BooleanFormula q2False = bmgr.equivalence(q2, bmgr.makeFalse()); + + SmtInterpolTheoremProver prover = (SmtInterpolTheoremProver) context.newProverEnvironment0( + Set.of(ProverOptions.GENERATE_PROOFS)); + try { + prover.addConstraint(notQ1OrQ2); + prover.addConstraint(q1True); + prover.addConstraint(q2False); + assertThat(prover.isUnsat()).isTrue(); + + + Term proof = prover.smtInterpolGetProof(); + assertThat(proof).isNotNull(); + + + //String proofStr = proof.toString(); + //System.out.println(proofStr); + System.out.println(proof); + } finally { + prover.close(); + } + } + + @Test + public void testGetProofClause() throws Exception { + //example from the 2022 paper + String constraint1 = "(set-logic QF_UF)\n" + + "(declare-fun q1 () Bool)\n" + + "(declare-fun q2 () Bool)\n" + + "(assert (or (not q1) q2))"; + String constraint2 = "(assert q1)"; + String constraint3 = "(assert (not q2))"; + + + BooleanFormula formula1 = + context.getFormulaManager().parse(constraint1); + + BooleanFormula formula2 = + context.getFormulaManager().parse(constraint2); + + BooleanFormula formula3 = + context.getFormulaManager().parse(constraint3); + + SmtInterpolTheoremProver prover = (SmtInterpolTheoremProver) context.newProverEnvironment0( + Set.of(ProverOptions.GENERATE_PROOFS, ProverOptions.GENERATE_MODELS)); + + SMTInterpol smtinterpol = (SMTInterpol) prover.env; + try { + prover.addConstraint(formula1); + prover.addConstraint(formula2); + prover.addConstraint(formula3); + assertThat(prover.isUnsat()).isTrue(); + + Clause proof = smtinterpol.retrieveProof(); + ProofNode proofNode = proof.getProof(); + Term term = smtinterpol.getProof(); + + assertThat(proof).isNotNull(); + + + //String proofStr = proof.toString(); + System.out.println(invokeGetProofMode(smtinterpol).toString()); + System.out.println(proof.toTerm(smtinterpol.getTheory())); + System.out.println(proof); + System.out.println(proofNode); + System.out.println(term); + } finally { + prover.close(); + } + } + + @Test + public void testProofTermParserIntegration() throws Exception { + // Arrange: parse constraints as in the SmtInterpolProofsTest. + String constraint1 = "(set-logic QF_UF)\n" + + "(declare-fun q1 () Bool)\n" + + "(declare-fun q2 () Bool)\n" + + "(assert (or (not q1) q2))"; + String constraint2 = "(assert q1)"; + String constraint3 = "(assert (not q2))"; + + BooleanFormula formula1 = context.getFormulaManager().parse(constraint1); + BooleanFormula formula2 = context.getFormulaManager().parse(constraint2); + BooleanFormula formula3 = context.getFormulaManager().parse(constraint3); + + // Create a prover with proof and model generation enabled. + SmtInterpolTheoremProver prover = + (SmtInterpolTheoremProver) context.newProverEnvironment0( + ImmutableSet.of(ProverOptions.GENERATE_PROOFS, ProverOptions.GENERATE_MODELS)); + SMTInterpol smtInterpol = (SMTInterpol) prover.env; + try { + // Act: add constraints and check unsat. + prover.addConstraint(formula1); + prover.addConstraint(formula2); + prover.addConstraint(formula3); + assertTrue(prover.isUnsat()); + + // Retrieve the proof term from SMTInterpol. + Term proofTerm = smtInterpol.getProof(); + assertNotNull(proofTerm); + + // Convert the retrieved proof term to a ResolutionProofDAG using the context's formula creator + // and the asserted formulas. + ResolutionProofDAG dag = + (ResolutionProofDAG) prover.getProof(); + assertNotNull(dag); + + // Optionally, additional assertions on the dag structure can be added here. + } finally { + prover.close(); + } + } + + public static Object invokeGetProofMode(SMTInterpol instance) throws Exception { + Method getProofModeMethod = SMTInterpol.class.getDeclaredMethod("getProofMode"); + getProofModeMethod.setAccessible(true); + return getProofModeMethod.invoke(instance); + } + + + +} \ No newline at end of file diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolSolverContext.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolSolverContext.java index 80f6a0e9c6..5432a2d5af 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolSolverContext.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolSolverContext.java @@ -10,7 +10,9 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import static de.uni_freiburg.informatik.ultimate.smtinterpol.smtlib2.SMTInterpol.ProofMode; +import ap.Prover; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import de.uni_freiburg.informatik.ultimate.logic.LoggingScript; @@ -202,6 +204,7 @@ private Script createNewScript(Set pOptions) { pOptions.contains(ProverOptions.GENERATE_UNSAT_CORE) || pOptions.contains(ProverOptions.GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)); newOptions.put(":produce-models", pOptions.contains(ProverOptions.GENERATE_MODELS)); + newOptions.put(":produce-proofs", pOptions.contains(ProverOptions.GENERATE_PROOFS)); SMTInterpol smtInterpol = new SMTInterpol(getSmtInterpol(), newOptions, CopyMode.RESET_TO_DEFAULT); From 955c1affb8fd8e181b0565ad17540beaccaf8d75 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Wed, 5 Mar 2025 09:39:45 +0100 Subject: [PATCH 005/132] Z3: context now able to be created with proof generation. Option requireProofs must be set to true through Configuration. Added a class for testing the proof generation of Z3. SMTInterpol: some documentation. --- .../solvers/smtinterpol/ProofTermParser.java | 2 + .../SmtInterpolAbstractProver.java | 1 + .../smtinterpol/SmtInterpolProofsTest.java | 43 ++++++ .../java_smt/solvers/z3/Z3ProofsTest.java | 141 ++++++++++++++++++ .../java_smt/solvers/z3/Z3SolverContext.java | 9 +- 5 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java index e4d7e9363a..4a717ccb55 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java @@ -17,6 +17,8 @@ import org.sosy_lab.java_smt.basicimpl.AbstractProofDAG; import org.sosy_lab.java_smt.basicimpl.FormulaCreator; +//TODO: Correct parsing of the proof terms is missing, i.e. creation of nodes in the DAG and +// parsing annotations. Add relevant javadocs public class ProofTermParser { private final ResolutionProofDAG proofDag; diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java index f1ba6c4a93..5a0d6ed034 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java @@ -238,6 +238,7 @@ public ProofDAG getProof() { return proofDAG; } + //TODO: Delete this method protected Term smtInterpolGetProof() { return env.getProof(); } diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java index e3ee3d0f51..d1fc18c9ff 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java @@ -194,6 +194,49 @@ public void testProofTermParserIntegration() throws Exception { } } + @Test + public void testSmtInterpolProof() throws Exception { + // Arrange: parse constraints as in the SmtInterpolProofsTest. + String constraint1 = "(set-logic QF_UF)\n" + + "(declare-fun q1 () Bool)\n" + + "(declare-fun q2 () Bool)\n" + + "(assert (or (not q1) q2))"; + String constraint2 = "(assert q1)"; + String constraint3 = "(assert (not q2))"; + + BooleanFormula q1 = bmgr.makeVariable("q1"); + BooleanFormula q2 = bmgr.makeVariable("q2"); + + // Create a prover with proof and model generation enabled. + SmtInterpolTheoremProver prover = + (SmtInterpolTheoremProver) context.newProverEnvironment0( + ImmutableSet.of(ProverOptions.GENERATE_PROOFS, ProverOptions.GENERATE_MODELS)); + SMTInterpol smtInterpol = (SMTInterpol) prover.env; + try { + // Act: add constraints and check unsat. + prover.addConstraint(bmgr.or(bmgr.not(q1), q2)); + prover.addConstraint(q1); + prover.addConstraint(bmgr.not(q2)); + assertTrue(prover.isUnsat()); + + // Retrieve the proof term from SMTInterpol. + Term proofTerm = smtInterpol.getProof(); + assertNotNull(proofTerm); + + Term proof = prover.smtInterpolGetProof(); + assertThat(proof).isNotNull(); + + + //String proofStr = proof.toString(); + //System.out.println(proofStr); + System.out.println(proof); + + // Optionally, additional assertions on the dag structure can be added here. + } finally { + prover.close(); + } + } + public static Object invokeGetProofMode(SMTInterpol instance) throws Exception { Method getProofModeMethod = SMTInterpol.class.getDeclaredMethod("getProofMode"); getProofModeMethod.setAccessible(true); diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java new file mode 100644 index 0000000000..c4bf47b812 --- /dev/null +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java @@ -0,0 +1,141 @@ + +package org.sosy_lab.java_smt.solvers.z3; + +import com.microsoft.z3.*; + +import static com.google.common.truth.Truth.assertThat; + +import com.microsoft.z3.Context; +import com.microsoft.z3.Solver; +import java.lang.reflect.Constructor; +import java.util.HashMap; +import java.util.Set; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.sosy_lab.common.NativeLibraries; +import org.sosy_lab.common.ShutdownManager; +import org.sosy_lab.common.configuration.Configuration; +import org.sosy_lab.common.log.BasicLogManager; +import org.sosy_lab.common.log.LogManager; +import org.sosy_lab.java_smt.SolverContextFactory; +import org.sosy_lab.java_smt.api.BooleanFormula; +import org.sosy_lab.java_smt.api.FloatingPointRoundingMode; +import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; +import org.sosy_lab.java_smt.api.SolverException; +import org.sosy_lab.java_smt.basicimpl.AbstractNumeralFormulaManager.NonLinearArithmetic; +import org.sosy_lab.java_smt.solvers.smtinterpol.SmtInterpolSolverContext; + +public class Z3ProofsTest { + + private Z3SolverContext context; + private Z3FormulaManager mgr; + private Z3BooleanFormulaManager bmgr; + + @Before + public void setUpSolver() throws Exception { + Configuration config = + Configuration.builder().setOption("solver.z3.requireProofs", "true").build(); + LogManager logger = BasicLogManager.create(config); + ShutdownManager shutdown = ShutdownManager.create(); + + // Create new context with SMTInterpol + context = Z3SolverContext.create( + logger, + config, + shutdown.getNotifier(), + null, // no logfile + 42, // random seed value + FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN, + NonLinearArithmetic.USE, + NativeLibraries::loadLibrary + ); + mgr = (Z3FormulaManager) context.getFormulaManager(); + bmgr = (Z3BooleanFormulaManager) mgr.getBooleanFormulaManager(); + } + + @After + public void closeSolver() { + if (context != null) { + context.close(); + } + } + + @Test + public void testGetProofExpr() throws SolverException, InterruptedException { + //example from the 2022 paper + BooleanFormula q1 = bmgr.makeVariable("q1"); + BooleanFormula q2 = bmgr.makeVariable("q2"); + BooleanFormula notQ1OrQ2 = bmgr.or(bmgr.not(q1), q2); + BooleanFormula q1True = bmgr.equivalence(q1, bmgr.makeTrue()); + BooleanFormula q2False = bmgr.equivalence(q2, bmgr.makeFalse()); + + Z3TheoremProver prover = (Z3TheoremProver) context.newProverEnvironment0(Set.of()); + try { + System.out.println("proofs enabled: " + context.getGenerateProofs()); + prover.addConstraint(notQ1OrQ2); + prover.addConstraint(q1True); + prover.addConstraint(q2False); + assertThat(prover.isUnsat()).isTrue(); + + Context z3Context = createContextWithRawPointer(mgr.getFormulaCreator().getEnv()); + Solver solver = z3Context.mkSolver(); + //solver. + + //Expr proof = solver.getProof(); + //assertThat(proof).isNotNull(); + + + //String proofStr = proof.toString(); + //System.out.println(proofStr); + //System.out.println(proof); + } finally { + prover.close(); + } + } + + public static Context createContextWithRawPointer(long m_ctx) { + try { + Constructor constructor = Context.class.getDeclaredConstructor(long.class); + constructor.setAccessible(true); // allow access even if non‑public + return constructor.newInstance(m_ctx); + } catch (Exception e) { + throw new RuntimeException("Failed to create Context instance", e); + } + } + + @Test + public void Z3ProofTest() { + HashMap cfg = new HashMap<>(); + cfg.put("proof", "true"); + Context ctx = new Context(cfg); + try { + // Create boolean variables + BoolExpr q1 = ctx.mkBoolConst("q1"); + BoolExpr q2 = ctx.mkBoolConst("q2"); + + // Create solver + Solver solver = ctx.mkSolver(); + + // Assert (or (not q1) q2) + solver.add(ctx.mkOr(ctx.mkNot(q1), q2)); + + // Assert q1 + solver.add(q1); + + // Assert (not q2) + solver.add(ctx.mkNot(q2)); + + Status status = solver.check(); + + System.out.println("Unsat: " + (status == Status.UNSATISFIABLE)); + + Expr proof = solver.getProof(); + System.out.println("proof: " + proof); + System.out.println(Version.getFullVersion()); + } finally { + ctx.close(); + } + } +} + diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java index 7d408faf11..746e9b08fa 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java @@ -50,11 +50,13 @@ public final class Z3SolverContext extends AbstractSolverContext { private static final String OPT_ENGINE_CONFIG_KEY = "optsmt_engine"; private static final String OPT_PRIORITY_CONFIG_KEY = "priority"; + private static boolean GENERATE_PROOFS = false; @Options(prefix = "solver.z3") private static class ExtraOptions { - @Option(secure = true, description = "Require proofs from SMT solver") + @Option(secure = true, description = "Require proofs from SMT solver", + values = {"true", "false"}) boolean requireProofs = false; @Option( @@ -143,6 +145,7 @@ public static synchronized Z3SolverContext create( long cfg = Native.mkConfig(); if (extraOptions.requireProofs) { Native.setParamValue(cfg, "PROOF", "true"); + GENERATE_PROOFS = true; } Native.globalParamSet("smt.random_seed", String.valueOf(randomSeed)); Native.globalParamSet("model.compact", "false"); @@ -279,6 +282,10 @@ public void close() { } } + public boolean getGenerateProofs() { + return GENERATE_PROOFS; + } + @Override protected boolean supportsAssumptionSolving() { return true; From af4f67047ff91ce9210b7a4f2bd6258e1468345c Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Tue, 11 Mar 2025 17:54:07 +0100 Subject: [PATCH 006/132] Z3: Proof ast given by Z3 is now parsed to DAG made out of Z3ProofNode. Various changes to the ProofDAG interface and all classes inheriting it. --- src/org/sosy_lab/java_smt/ResProofRule.java | 27 +-- .../sosy_lab/java_smt/ResolutionProofDAG.java | 18 +- .../java_smt/ResolutionProofNode.java | 7 +- .../sosy_lab/java_smt/SourceProofNode.java | 4 +- .../java_smt/api/BasicProverEnvironment.java | 2 +- .../java_smt/api/proofs/ProofDAG.java | 13 +- .../java_smt/api/proofs/ProofFactory.java | 4 +- .../java_smt/api/proofs/ProofNode.java | 9 +- .../java_smt/api/proofs/ProofRule.java | 18 ++ .../visitors/ProofTraversalVisitor.java | 12 +- .../api/proofs/visitors/ProofVisitor.java | 6 +- .../java_smt/basicimpl/AbstractProofDAG.java | 19 +- .../java_smt/basicimpl/AbstractProofNode.java | 36 +++- .../solvers/smtinterpol/ProofTermParser.java | 33 ++- .../SmtInterpolAbstractProver.java | 4 +- .../smtinterpol/SmtInterpolProofNode.java | 19 +- .../java_smt/solvers/z3/Z3AbstractProver.java | 5 + .../java_smt/solvers/z3/Z3ProofDAG.java | 19 ++ .../java_smt/solvers/z3/Z3ProofNode.java | 12 ++ .../java_smt/solvers/z3/Z3ProofParser.java | 191 ++++++++++++++++++ .../java_smt/solvers/z3/Z3ProofRule.java | 105 ++++++++++ .../java_smt/solvers/z3/Z3ProofsTest.java | 66 ++++-- .../java_smt/solvers/z3/Z3TheoremProver.java | 20 ++ 23 files changed, 517 insertions(+), 132 deletions(-) create mode 100644 src/org/sosy_lab/java_smt/api/proofs/ProofRule.java create mode 100644 src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDAG.java create mode 100644 src/org/sosy_lab/java_smt/solvers/z3/Z3ProofNode.java create mode 100644 src/org/sosy_lab/java_smt/solvers/z3/Z3ProofParser.java create mode 100644 src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java diff --git a/src/org/sosy_lab/java_smt/ResProofRule.java b/src/org/sosy_lab/java_smt/ResProofRule.java index 3bcd9da866..8c81c29f03 100644 --- a/src/org/sosy_lab/java_smt/ResProofRule.java +++ b/src/org/sosy_lab/java_smt/ResProofRule.java @@ -10,6 +10,8 @@ package org.sosy_lab.java_smt; +import org.sosy_lab.java_smt.api.proofs.ProofRule; + /** * A proof rule in the proof DAG of the internal proof format of JavaSMT. * @@ -20,7 +22,7 @@ public class ResProofRule { /** * Any operation that proves a term. */ - public enum ResAxiom { + public enum ResAxiom implements ProofRule { //Resolution Rule RESOLUTION("res", "(res t proof1 proof2)"), @@ -104,19 +106,19 @@ public enum ResAxiom { "(= (match t ((p1 x1) c1) ...) (ite ((_ is p1) t) (let (x1 (sel1 t)) c1) ...))"); private final String name; - private final String clause; + private final String formula; - ResAxiom(String name, String clause) { - this.name = name; - this.clause = clause; + ResAxiom(String pName, String pFormula) { + name = pName; + formula = pFormula; } public String getName() { return name; } - public String getClause() { - return clause; + public String getFormula() { + return formula; } } @@ -126,7 +128,7 @@ public String getClause() { * @param name The name of the proof rule. * @return The matching ProofRule, or null if not found. */ - public static ResAxiom getRuleByName(String name) { + public static ResAxiom getResAxiomRuleByName(String name) { for (ResAxiom rule : ResAxiom.values()) { if (rule.getName().equalsIgnoreCase(name)) { return rule; @@ -135,13 +137,4 @@ public static ResAxiom getRuleByName(String name) { throw new IllegalArgumentException("Rule not found or not specified: " + name); } - /** - * Prints all proof rules for debugging or inspection. - */ - public static void printAllRules() { - System.out.println("Available Proof Rules:"); - for (ResAxiom rule : ResAxiom.values()) { - System.out.println(rule.getName() + ": " + rule.getClause()); - } - } } diff --git a/src/org/sosy_lab/java_smt/ResolutionProofDAG.java b/src/org/sosy_lab/java_smt/ResolutionProofDAG.java index b613379c9a..534ee99e3b 100644 --- a/src/org/sosy_lab/java_smt/ResolutionProofDAG.java +++ b/src/org/sosy_lab/java_smt/ResolutionProofDAG.java @@ -10,25 +10,17 @@ package org.sosy_lab.java_smt; -import com.google.common.collect.ImmutableSet; import de.uni_freiburg.informatik.ultimate.logic.AnnotatedTerm; import de.uni_freiburg.informatik.ultimate.logic.Annotation; -import de.uni_freiburg.informatik.ultimate.logic.FunctionSymbol; -import de.uni_freiburg.informatik.ultimate.logic.Script; -import de.uni_freiburg.informatik.ultimate.logic.Sort; import de.uni_freiburg.informatik.ultimate.logic.Term; -import de.uni_freiburg.informatik.ultimate.smtinterpol.dpll.Clause; -import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.ResolutionNode; import java.util.Map; -import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.FormulaManager; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.AbstractProofDAG; -import org.sosy_lab.java_smt.basicimpl.FormulaCreator; import org.sosy_lab.java_smt.solvers.smtinterpol.ProofTermParser; -public class ResolutionProofDAG extends AbstractProofDAG { +public class ResolutionProofDAG extends AbstractProofDAG { public ResolutionProofDAG() { super(); @@ -57,7 +49,7 @@ public static ResolutionProofDAG fromTerm( * @param dag the proof DAG being constructed * @param parentClause the clause from the parent annotation (if available) */ - private static void traverseTerm(Term term, ResolutionProofDAG dag, ProofNode parentClause) { + private static void traverseTerm(Term term, ResolutionProofDAG dag, ProofNode parentClause) { if (term instanceof AnnotatedTerm) { AnnotatedTerm annotatedTerm = (AnnotatedTerm) term; for (Annotation annotation : annotatedTerm.getAnnotations()) { @@ -82,17 +74,17 @@ private static void traverseTerm(Term term, ResolutionProofDAG dag, ProofNode node) { + public void addNode(ProofNode node) { super.addNode(node); } @Override - public ProofNode getNode(int nodeId) { + public ProofNode getNode(int nodeId) { return super.getNode(nodeId); } @Override - public void addEdge(ProofNode parentNodeId, ProofNode childNodeId) { + public void addEdge(int parentNodeId, int childNodeId) { super.addEdge(parentNodeId, childNodeId); } } diff --git a/src/org/sosy_lab/java_smt/ResolutionProofNode.java b/src/org/sosy_lab/java_smt/ResolutionProofNode.java index da6b3da361..6f823aa9b9 100644 --- a/src/org/sosy_lab/java_smt/ResolutionProofNode.java +++ b/src/org/sosy_lab/java_smt/ResolutionProofNode.java @@ -12,11 +12,12 @@ import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; import org.sosy_lab.java_smt.ResProofRule.ResAxiom; -public class ResolutionProofNode extends AbstractProofNode - implements ProofNode { +public class ResolutionProofNode extends AbstractProofNode + implements ProofNode { private final Formula pivot; @@ -35,7 +36,7 @@ public Formula getPivot() { return pivot; } - public ResAxiom getRule() { + public ProofRule getRule() { return super.getRule(); } } diff --git a/src/org/sosy_lab/java_smt/SourceProofNode.java b/src/org/sosy_lab/java_smt/SourceProofNode.java index 658867db8b..58714114a4 100644 --- a/src/org/sosy_lab/java_smt/SourceProofNode.java +++ b/src/org/sosy_lab/java_smt/SourceProofNode.java @@ -15,8 +15,8 @@ import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; import org.sosy_lab.java_smt.ResProofRule.ResAxiom; -public class SourceProofNode extends AbstractProofNode - implements ProofNode { +public class SourceProofNode extends AbstractProofNode + implements ProofNode { public SourceProofNode(ResAxiom rule, Formula formula) { diff --git a/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java b/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java index 03efd7a1eb..9e99e84d1b 100644 --- a/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java @@ -154,7 +154,7 @@ default ImmutableMap getStatistics() { * Get proof of unsatisfiability of the conjuction of the current satck of all formulas. Should * only be called after {@link #isUnsat()} returned true. */ - default ProofDAG getProof() { + default ProofDAG getProof() { try { throw new UnsupportedOperationException("Proof generation isn't enabled."); } catch (UnsupportedOperationException e) { diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java b/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java index 49cdf137f6..7ffe6015bc 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java @@ -11,13 +11,12 @@ package org.sosy_lab.java_smt.api.proofs; import java.util.Collection; -import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.api.proofs.visitors.ProofVisitor; -public interface ProofDAG { - void addNode(ProofNode node); - ProofNode getNode(int nodeId); - void addEdge(ProofNode parentNodeId, ProofNode childNodeId); - Collection> getNodes(); - void accept(ProofVisitor visitor); // To allow traversal of the entire DAG +public interface ProofDAG { + void addNode(ProofNode node); + ProofNode getNode(int nodeId); + void addEdge(int parentNodeId, int childNodeId); + Collection getNodes(); + void accept(ProofVisitor visitor); // To allow traversal of the entire DAG } diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java index 7b4679875d..659960da3d 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java @@ -16,11 +16,11 @@ import org.sosy_lab.java_smt.ResProofRule.ResAxiom; public class ProofFactory { - public static ProofNode createSourceNode(ResAxiom rule, Formula formula) { + public static ProofNode createSourceNode(ResAxiom rule, Formula formula) { return new SourceProofNode(rule, formula); } - public static ProofNode createResolutionNode(Formula formula, Formula pivot) { + public static ProofNode createResolutionNode(Formula formula, Formula pivot) { return new ResolutionProofNode(formula, pivot); } } diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java b/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java index 7d36f4b8db..e36aa6ebbf 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java @@ -20,11 +20,12 @@ * * @author Gabriel Carpio */ -public interface ProofNode { - List> getChildren(); - void addChild(ProofNode child); +public interface ProofNode { + List getChildren(); + void addChild(ProofNode child); boolean isSource(); boolean isSink(); - void accept(ProofVisitor visitor); + void accept(ProofVisitor visitor); Formula getFormula(); + int getId(); } diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofRule.java b/src/org/sosy_lab/java_smt/api/proofs/ProofRule.java new file mode 100644 index 0000000000..1aa6227662 --- /dev/null +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofRule.java @@ -0,0 +1,18 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.api.proofs; + +public interface ProofRule { + + String getName(); + + String getFormula(); +} diff --git a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java index 35e65fc3fc..114b69659b 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java +++ b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java @@ -15,21 +15,21 @@ import org.sosy_lab.java_smt.api.proofs.ProofDAG; import org.sosy_lab.java_smt.api.proofs.ProofNode; -public class ProofTraversalVisitor implements ProofVisitor { - private final Set> visited = new HashSet<>(); +public class ProofTraversalVisitor implements ProofVisitor { + private final Set visited = new HashSet<>(); @Override - public void visitNode(ProofNode node) { + public void visitNode(ProofNode node) { if (visited.add(node)) { - for (ProofNode child : node.getChildren()) { + for (ProofNode child : node.getChildren()) { visitNode(child); } } } @Override - public void visitDAG(ProofDAG dag) { - for (ProofNode node : dag.getNodes()) { + public void visitDAG(ProofDAG dag) { + for (ProofNode node : dag.getNodes()) { if (!visited.contains(node)) { visitNode(node); } diff --git a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofVisitor.java b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofVisitor.java index 469c797ac7..5067b89e47 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofVisitor.java +++ b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofVisitor.java @@ -13,7 +13,7 @@ import org.sosy_lab.java_smt.api.proofs.ProofDAG; import org.sosy_lab.java_smt.api.proofs.ProofNode; -public interface ProofVisitor { - void visitNode(ProofNode node); - void visitDAG(ProofDAG dag); +public interface ProofVisitor { + void visitNode(ProofNode node); + void visitDAG(ProofDAG dag); } diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java index 56783f38c5..7454d1cc75 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java @@ -13,7 +13,6 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; -import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.api.proofs.ProofDAG; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.api.proofs.visitors.ProofVisitor; @@ -23,36 +22,36 @@ * * @author Gabriel Carpio */ -public abstract class AbstractProofDAG implements ProofDAG { - private final Map> nodes = new HashMap<>(); +public abstract class AbstractProofDAG implements ProofDAG { + private final Map nodes = new HashMap<>(); private int nodeIdCounter = 0; @Override - public void addNode(ProofNode node) { + public void addNode(ProofNode node) { nodes.put(nodeIdCounter++, node); } @Override - public ProofNode getNode(int nodeId) { + public ProofNode getNode(int nodeId) { return nodes.get(nodeId); } @Override - public void addEdge(ProofNode parentNodeId, ProofNode childNodeId) { - ProofNode parent = nodes.get(parentNodeId); - ProofNode child = nodes.get(childNodeId); + public void addEdge(int parentNodeId, int childNodeId) { + ProofNode parent = nodes.get(parentNodeId); + ProofNode child = nodes.get(childNodeId); if (parent != null && child != null) { parent.addChild(child); } } @Override - public Collection> getNodes() { + public Collection getNodes() { return nodes.values(); } @Override - public void accept(ProofVisitor visitor) { + public void accept(ProofVisitor visitor) { visitor.visitDAG(this); } } \ No newline at end of file diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java index 662023defd..f50dc4be45 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java @@ -12,8 +12,10 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import org.sosy_lab.common.UniqueIdGenerator; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.api.proofs.visitors.ProofVisitor; /** @@ -21,15 +23,18 @@ * * @author Gabriel Carpio */ -public abstract class AbstractProofNode implements ProofNode { - private final List> children; - private final R rule; - private final Formula formula; +public abstract class AbstractProofNode implements ProofNode { + private final List children; + private ProofRule rule; + private Formula formula; + private final UniqueIdGenerator idGenerator = new UniqueIdGenerator(); + private final int id; - protected AbstractProofNode(R rule, Formula formula) { + protected AbstractProofNode(ProofRule rule, Formula formula) { this.rule = rule; this.formula = formula; children = new ArrayList<>(); + id = idGenerator.getFreshId(); } @Override @@ -38,16 +43,16 @@ public Formula getFormula() { } @Override - public List> getChildren() { + public List getChildren() { return Collections.unmodifiableList(children); } @Override - public void addChild(ProofNode child) { + public void addChild(ProofNode child) { children.add(child); } - public R getRule() { + public ProofRule getRule() { return rule; } @@ -62,7 +67,20 @@ public boolean isSink() { } @Override - public void accept(ProofVisitor visitor) { + public void accept(ProofVisitor visitor) { visitor.visitNode(this); } + + @Override + public int getId() { + return id; + } + + public void setRule(ProofRule rule) { + this.rule = rule; + } + + public void setFormula(Formula pFormula) { + formula = pFormula; + } } \ No newline at end of file diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java index 4a717ccb55..917652ca81 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java @@ -8,14 +8,11 @@ import de.uni_freiburg.informatik.ultimate.logic.TermVariable; import java.util.HashMap; import java.util.Map; -import org.sosy_lab.java_smt.ResProofRule; import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.ResolutionProofDAG; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.FormulaManager; import org.sosy_lab.java_smt.api.proofs.ProofNode; -import org.sosy_lab.java_smt.basicimpl.AbstractProofDAG; -import org.sosy_lab.java_smt.basicimpl.FormulaCreator; //TODO: Correct parsing of the proof terms is missing, i.e. creation of nodes in the DAG and // parsing annotations. Add relevant javadocs @@ -24,7 +21,7 @@ public class ProofTermParser { private final ResolutionProofDAG proofDag; private final Map annotatedTerms; private final Map letBindings = new HashMap<>(); - private final Map> termToNode = new HashMap<>(); + private final Map termToNode = new HashMap<>(); private final FormulaManager mgr; public ProofTermParser(Map pAnnotatedTerms, FormulaManager pMgr) { @@ -39,7 +36,7 @@ public static ResolutionProofDAG convert( FormulaManager pManager, Map pAnnotatedTerms) { ProofTermParser parser = new ProofTermParser(pAnnotatedTerms, pManager); - ProofNode rootNode = parser.parseProofTerm(proof); + ProofNode rootNode = parser.parseProofTerm(proof); if (rootNode != null) { parser.proofDag.addNode(rootNode); } @@ -47,12 +44,12 @@ public static ResolutionProofDAG convert( } - public ProofNode parseProofTerm(Term term) { + public ProofNode parseProofTerm(Term term) { if (termToNode.containsKey(term)) { return termToNode.get(term); } - ProofNode node = null; + ProofNode node = null; if (term instanceof AnnotatedTerm) { node = parseAnnotatedTerm((AnnotatedTerm) term); @@ -69,32 +66,32 @@ public ProofNode parseProofTerm(Term term) { return node; } - private ProofNode parseAnnotatedTerm(AnnotatedTerm term) { + private ProofNode parseAnnotatedTerm(AnnotatedTerm term) { for (Annotation annotation : term.getAnnotations()) { if (annotation.getKey().equals(":proves") || annotation.getKey().equals(":rup") || annotation.getKey().equals(":input")) { Term formulaTerm = extractFormulaFromAnnotation(annotation); BooleanFormula formula = getBooleanFormulaFromTerm(formulaTerm); - ProofNode node = createSourceNode(ResAxiom.RESOLUTION, formula); + ProofNode node = createSourceNode(ResAxiom.RESOLUTION, formula); return node; } } return parseProofTerm(term.getSubterm()); } - private ProofNode parseApplicationTerm(ApplicationTerm term) { + private ProofNode parseApplicationTerm(ApplicationTerm term) { String funcName = term.getFunction().getName(); Term[] params = term.getParameters(); if (funcName.equals("..res") && params.length >= 3) { Term clauseTerm = params[0]; BooleanFormula formula = getBooleanFormulaFromTerm(clauseTerm); - ProofNode resNode = createSourceNode(ResAxiom.RESOLUTION, formula); + ProofNode resNode = createSourceNode(ResAxiom.RESOLUTION, formula); for (int i = 1; i < params.length; i++) { - ProofNode childNode = parseProofTerm(params[i]); + ProofNode childNode = parseProofTerm(params[i]); if (childNode != null) { - proofDag.addEdge(resNode, childNode); + proofDag.addEdge(resNode.getId(), childNode.getId()); } } return resNode; @@ -118,7 +115,7 @@ private ProofNode parseApplicationTerm(ApplicationTerm term) { } } - ProofNode lastNode = null; + ProofNode lastNode = null; for (Term param : params) { lastNode = parseProofTerm(param); } @@ -126,7 +123,7 @@ private ProofNode parseApplicationTerm(ApplicationTerm term) { return lastNode; } - private ProofNode parseLetTerm(LetTerm term) { + private ProofNode parseLetTerm(LetTerm term) { Map oldBindings = new HashMap<>(letBindings); TermVariable[] vars = term.getVariables(); Term[] values = term.getValues(); @@ -135,7 +132,7 @@ private ProofNode parseLetTerm(LetTerm term) { letBindings.put(vars[i].getName(), values[i]); } - ProofNode result = parseProofTerm(term.getSubTerm()); + ProofNode result = parseProofTerm(term.getSubTerm()); letBindings.clear(); letBindings.putAll(oldBindings); @@ -169,8 +166,8 @@ private BooleanFormula getBooleanFormulaFromTerm(Term term) { return ((SmtInterpolFormulaManager) mgr).encapsulateBooleanFormula(term); } - private ProofNode createSourceNode(ResAxiom rule, BooleanFormula formula) { - ProofNode node = new org.sosy_lab.java_smt.SourceProofNode(rule, formula); + private ProofNode createSourceNode(ResAxiom rule, BooleanFormula formula) { + ProofNode node = new org.sosy_lab.java_smt.SourceProofNode(rule, formula); proofDag.addNode(node); return node; } diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java index 5a0d6ed034..da36a53ae9 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java @@ -217,12 +217,12 @@ public ImmutableMap getStatistics() { } @Override - public ProofDAG getProof() { + public ProofDAG getProof() { checkState(!closed); checkGenerateProofs(); final Term proof; - final ProofDAG proofDAG; + final ProofDAG proofDAG; try { proof = env.getProof(); proofDAG = ResolutionProofDAG.fromTerm(proof, mgr, annotatedTerms.peek()); diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNode.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNode.java index 541ee2a3c2..274abc4a22 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNode.java @@ -23,23 +23,14 @@ import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.ResolutionNode; import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.ResolutionNode.Antecedent; -import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.SourceAnnotation; -import de.uni_freiburg.informatik.ultimate.smtinterpol.theory.cclosure.CCAnnotation; -import de.uni_freiburg.informatik.ultimate.smtinterpol.theory.linar.EQAnnotation; -import de.uni_freiburg.informatik.ultimate.smtinterpol.theory.linar.LAAnnotation; -import de.uni_freiburg.informatik.ultimate.smtinterpol.theory.quant.QuantAnnotation; -import java.util.Map; -import org.sosy_lab.java_smt.ResProofRule; -import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.ResolutionProofDAG; import org.sosy_lab.java_smt.ResolutionProofNode; -import org.sosy_lab.java_smt.SourceProofNode; -import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; -class SmtInterpolProofNode extends AbstractProofNode { +class SmtInterpolProofNode extends AbstractProofNode { static class ResolutionProofDAGBuilder { private final SmtInterpolFormulaCreator creator; private Theory theory; @@ -85,11 +76,11 @@ private static void addDagEdges(SmtInterpolProofNode node, ResolutionProofDAG da } dag.addNode(node.getTransformed()); if (node.getLeft() != null) { - dag.addEdge(node.getTransformed(), node.getLeft().getTransformed()); + dag.addEdge(node.getTransformed().getId(), node.getLeft().getTransformed().getId()); addDagEdges(node.getLeft(), dag); } if (node.getRight() != null) { - dag.addEdge(node.getTransformed(), node.getRight().getTransformed()); + dag.addEdge(node.getTransformed().getId(), node.getRight().getTransformed().getId()); addDagEdges(node.getRight(), dag); } } @@ -123,7 +114,7 @@ public void processSourceNode(SmtInterpolProofNode node) { private org.sosy_lab.java_smt.api.proofs.ProofNode transformed; - protected SmtInterpolProofNode(String rule, Formula formula) { + protected SmtInterpolProofNode(ProofRule rule, Formula formula) { super(rule, formula); } diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3AbstractProver.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3AbstractProver.java index 7da2fbdbf5..237f3a2bda 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3AbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3AbstractProver.java @@ -242,6 +242,11 @@ private String getUnusedKey(Set seenKeys, final String originalKey) { return key; } + @Nullable + protected Deque> getStoredConstraints() { + return storedConstraints; + } + @Override public void close() { if (!closed) { diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDAG.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDAG.java new file mode 100644 index 0000000000..52e5c44725 --- /dev/null +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDAG.java @@ -0,0 +1,19 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.solvers.z3; + + +import org.sosy_lab.java_smt.basicimpl.AbstractProofDAG; + + +public class Z3ProofDAG extends AbstractProofDAG { + +} diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofNode.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofNode.java new file mode 100644 index 0000000000..08850d7fd1 --- /dev/null +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofNode.java @@ -0,0 +1,12 @@ +package org.sosy_lab.java_smt.solvers.z3; + +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.proofs.ProofRule; +import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; + +public class Z3ProofNode extends AbstractProofNode { + + public Z3ProofNode(Formula pFormula, ProofRule pProofRule) { + super(pProofRule, pFormula); + } +} \ No newline at end of file diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofParser.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofParser.java new file mode 100644 index 0000000000..9817e29466 --- /dev/null +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofParser.java @@ -0,0 +1,191 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.solvers.z3; + + +import com.microsoft.z3.Native; +import com.microsoft.z3.enumerations.Z3_decl_kind; +import com.microsoft.z3.enumerations.Z3_sort_kind; +import java.util.HashMap; +import java.util.Map; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.sosy_lab.java_smt.api.Formula; + +public class Z3ProofParser { + private final long z3context; + private final long z3solver; + private final Z3FormulaCreator formulaCreator; + private final Z3AbstractProver prover; + private final Map parsed = new HashMap<>(); + + + Z3ProofParser( + long ctx, long solver, Z3FormulaCreator creator, + Z3AbstractProver pProver) { + z3context = ctx; + z3solver = solver; + formulaCreator = creator; + prover = pProver; + } + + Z3ProofNode fromAST(long proof) { + if (parsed.containsKey(proof)) { + return parsed.get(proof); + } + + Native.incRef(z3context, proof); + long sort = Native.getSort(z3context, proof); + int declKind = Native.getDeclKind(z3context, + Native.getAppDecl(z3context, proof)); + int numArgs = Native.getAppNumArgs(z3context, proof); + Z3_sort_kind sort_kind = Z3_sort_kind.fromInt((int) sort); + Formula formula; + Z3ProofRule proofRule; + + if (sort_kind != Z3_sort_kind.Z3_UNKNOWN_SORT) { + formula = generateFormula(proof); + } else { + + long z3expr = Native.getAppArg(z3context, proof, numArgs - 1); + formula = generateFormula(z3expr); + } + proofRule = getPRfromDK(declKind); + Z3ProofNode proofNode = new Z3ProofNode(formula, proofRule); + parsed.put(proof, proofNode); + + for (int i = 0; i < numArgs - 1; i++) { + long arg = Native.getAppArg(z3context, proof, i); + proofNode.addChild(fromAST(arg)); + } + Native.decRef(z3context, proof); + return proofNode; + } + + private Z3ProofRule getPRfromDK(int declKind) { + Z3_decl_kind dk = Z3_decl_kind.fromInt(declKind); + switch (dk) { + case Z3_OP_PR_UNDEF: + return Z3ProofRule.UNDEF; + + case Z3_OP_PR_TRUE: + return Z3ProofRule.TRUE; + + case Z3_OP_PR_ASSERTED: + return Z3ProofRule.ASSERTED; + + case Z3_OP_PR_GOAL: + return Z3ProofRule.GOAL; + + case Z3_OP_PR_MODUS_PONENS: + return Z3ProofRule.MODUS_PONENS; + + case Z3_OP_PR_REFLEXIVITY: + return Z3ProofRule.REFLEXIVITY; + + case Z3_OP_PR_SYMMETRY: + return Z3ProofRule.SYMMETRY; + + case Z3_OP_PR_TRANSITIVITY: + return Z3ProofRule.TRANSITIVITY; + + case Z3_OP_PR_TRANSITIVITY_STAR: + return Z3ProofRule.TRANSITIVITY_STAR; + case Z3_OP_PR_MONOTONICITY: + return Z3ProofRule.MONOTONICITY; + case Z3_OP_PR_QUANT_INTRO: + return Z3ProofRule.QUANT_INTRO; + case Z3_OP_PR_BIND: + return Z3ProofRule.BIND; + case Z3_OP_PR_DISTRIBUTIVITY: + return Z3ProofRule.DISTRIBUTIVITY; + case Z3_OP_PR_AND_ELIM: + return Z3ProofRule.AND_ELIM; + case Z3_OP_PR_NOT_OR_ELIM: + return Z3ProofRule.NOT_OR_ELIM; + case Z3_OP_PR_REWRITE: + return Z3ProofRule.REWRITE; + case Z3_OP_PR_REWRITE_STAR: + return Z3ProofRule.REWRITE_STAR; + case Z3_OP_PR_PULL_QUANT: + return Z3ProofRule.PULL_QUANT; + case Z3_OP_PR_PUSH_QUANT: + return Z3ProofRule.PUSH_QUANT; + case Z3_OP_PR_ELIM_UNUSED_VARS: + return Z3ProofRule.ELIM_UNUSED_VARS; + case Z3_OP_PR_DER: + return Z3ProofRule.DER; + case Z3_OP_PR_QUANT_INST: + return Z3ProofRule.QUANT_INST; + case Z3_OP_PR_HYPOTHESIS: + return Z3ProofRule.HYPOTHESIS; + case Z3_OP_PR_LEMMA: + return Z3ProofRule.LEMMA; + case Z3_OP_PR_UNIT_RESOLUTION: + return Z3ProofRule.UNIT_RESOLUTION; + case Z3_OP_PR_IFF_TRUE: + return Z3ProofRule.IFF_TRUE; + case Z3_OP_PR_IFF_FALSE: + return Z3ProofRule.IFF_FALSE; + case Z3_OP_PR_COMMUTATIVITY: + return Z3ProofRule.COMMUTATIVITY; + case Z3_OP_PR_DEF_AXIOM: + return Z3ProofRule.DEF_AXIOM; + case Z3_OP_PR_ASSUMPTION_ADD: + return Z3ProofRule.ASSUMPTION_ADD; + case Z3_OP_PR_LEMMA_ADD: + return Z3ProofRule.LEMMA_ADD; + case Z3_OP_PR_REDUNDANT_DEL: + return Z3ProofRule.REDUNDANT_DEL; + case Z3_OP_PR_CLAUSE_TRAIL: + return Z3ProofRule.CLAUSE_TRAIL; + case Z3_OP_PR_DEF_INTRO: + return Z3ProofRule.DEF_INTRO; + case Z3_OP_PR_APPLY_DEF: + return Z3ProofRule.APPLY_DEF; + case Z3_OP_PR_IFF_OEQ: + return Z3ProofRule.IFF_OEQ; + case Z3_OP_PR_NNF_POS: + return Z3ProofRule.NNF_POS; + case Z3_OP_PR_NNF_NEG: + return Z3ProofRule.NNF_NEG; + case Z3_OP_PR_SKOLEMIZE: + return Z3ProofRule.SKOLEMIZE; + case Z3_OP_PR_MODUS_PONENS_OEQ: + return Z3ProofRule.MODUS_PONENS_OEQ; + case Z3_OP_PR_TH_LEMMA: + return Z3ProofRule.TH_LEMMA; + case Z3_OP_PR_HYPER_RESOLVE: + return Z3ProofRule.HYPER_RESOLVE; + default: + return Z3ProofRule.OPERATION; + } + } + + @Nullable + private Formula getFromStoredConstraints(long proof) { + String varName = Native.astToString(z3context, proof); + if (prover.getStoredConstraints().peek().containsKey(varName)) { + return prover.getStoredConstraints().peek().get(varName); + } else { + return null; + } + } + + private Formula generateFormula(long proof) { + Formula formula = getFromStoredConstraints(proof); + if (formula == null) { + formula = formulaCreator.encapsulate(formulaCreator.getFormulaType(proof), proof); + } + return formula; + } +} + + diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java new file mode 100644 index 0000000000..acf56a181d --- /dev/null +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java @@ -0,0 +1,105 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.solvers.z3; + +import javax.annotation.Nullable; +import org.sosy_lab.java_smt.api.proofs.ProofRule; + +//TODO correctly document the formula strings +public enum Z3ProofRule implements ProofRule { + + // Undefined proof object + UNDEF("undef", "undefined proof object"), + + // Basic assertions + TRUE("true", "proof for the expression 'true'"), + ASSERTED("asserted", "(asserted p)"), + GOAL("goal", "(goal p)"), + + // Logical inference rules + MODUS_PONENS("modus_ponens", "(mp p (implies p q) q)"), + REFLEXIVITY("reflexivity", "reflexivity (R t t), R is element of {=, ~, iff}"), //no antecendts + SYMMETRY("symmetry", "symmetry (R t1 t2) (R t2 t1)"), + TRANSITIVITY("transitivity", "trans (R t1 t2) (R t2 t3) (R t1 t3)"), + TRANSITIVITY_STAR("transitivity*", "trans *(R t1 t2) ... (R t3 t4) (R t1 t4)"), + MONOTONICITY("monotonicity", "monotonicity (R t1 s1) ... (R tn sn) (R (f t1 ... tn) (f s1 ... " + + "sn))"), + QUANT_INTRO("quant-intro", "quant-intro (~ p q) (~ (forall (x) p) (forall (x) q))"), + BIND("bind", "(proof-bind f (forall (x) f))"), + + // Boolean and CNF transformations + DISTRIBUTIVITY("distributivity", "(f g (= (f a (g b c)) (g (f a b) (f a c)))"), // + // no antecedents + AND_ELIM("and-elim", "and-elim (and p1 ... pn) pi"), + NOT_OR_ELIM("not-or-elim", "not-or-elim (not (or p1 ... pn)) (not pi)"), + + // Rewriting and simplifications + REWRITE("rewrite", "rewrite (R t s), R is element of {=, iff}"), //no antededents + REWRITE_STAR("rewrite*", "rewrite* (= t1 t2) ... (= tn-1 tn) (= t1 tn)"), + PULL_QUANT("pull_quant", "(= (f (forall x P(x)) R) (forall x (f P(x) R)))"), + PUSH_QUANT("push_quant", "(forall x (and P1(x) ... Pn(x))) (and (forall x P1(x)) ... (forall x Pn(x)))"), + ELIM_UNUSED_VARS("elim_unused_vars", "(forall x y P(x)) (forall x P(x))"), + DER("der", "(iff (forall x (or (not (= x t)) P(x))) P(t))"), + QUANT_INST("quant_inst", "(or (not (forall x P(x))) P(a))"), + + // Natural deduction style + HYPOTHESIS("hypothesis", "(hypothesis p)"), + LEMMA("lemma", "(or (not p1) ... (not pn))"), + UNIT_RESOLUTION("unit_resolution", "(or p1 ... pn q1 ... qm) (not p1) ... (not pn) (or q1 ... qm)"), + IFF_TRUE("iff_true", "(iff p true)"), + IFF_FALSE("iff_false", "(iff p false)"), + COMMUTATIVITY("commutativity", "(= (f a b) (f b a))"), + + // Tseitin-like axioms + DEF_AXIOM("def_axiom", "Propositional tautologies (CNF conversion)"), + + // Clause manipulation rules + ASSUMPTION_ADD("assumption_add", "(add_clause p)"), + LEMMA_ADD("lemma_add", "(add_lemma p)"), + REDUNDANT_DEL("redundant_del", "(delete_clause p)"), + CLAUSE_TRAIL("clause_trail", "(clause_trail p)"), + + // Definitions and introduction rules + DEF_INTRO("def_intro", "(= n e)"), + APPLY_DEF("apply_def", "(~ p q)"), + IFF_OEQ("iff_oeq", "(iff p q) (~ p q)"), + + // Negation Normal Form (NNF) transformations + NNF_POS("nnf_pos", "(~ (iff p q) (and (or p (not q)) (or (not p) q)))"), + NNF_NEG("nnf_neg", "(not (and p1 ... pn)) (or (not p1) ... (not pn))"), + + // Skolemization + SKOLEMIZE("skolemize", "(~ (exists x P(x)) P(sk))"), + + // Theory reasoning + MODUS_PONENS_OEQ("modus_ponens_oeq", "(mp~ p (~ p q) q)"), + TH_LEMMA("th_lemma", "Theory-specific lemma"), + HYPER_RESOLVE("hyper_resolve", "Hyper-resolution with multiple premises"), + + OPERATION("operation", null); + + private final String name; + private final String formula; + + Z3ProofRule(String name, String formula) { + this.name = name; + this.formula = formula; + } + + public String getName() { + return name; + } + + public String getFormula() { + return formula; + } +} + diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java index c4bf47b812..2aa0a0855a 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java @@ -3,10 +3,12 @@ import com.microsoft.z3.*; -import static com.google.common.truth.Truth.assertThat; + +import static org.junit.Assert.assertTrue; import com.microsoft.z3.Context; import com.microsoft.z3.Solver; + import java.lang.reflect.Constructor; import java.util.HashMap; import java.util.Set; @@ -18,13 +20,13 @@ import org.sosy_lab.common.configuration.Configuration; import org.sosy_lab.common.log.BasicLogManager; import org.sosy_lab.common.log.LogManager; -import org.sosy_lab.java_smt.SolverContextFactory; + import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.FloatingPointRoundingMode; -import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; + import org.sosy_lab.java_smt.api.SolverException; import org.sosy_lab.java_smt.basicimpl.AbstractNumeralFormulaManager.NonLinearArithmetic; -import org.sosy_lab.java_smt.solvers.smtinterpol.SmtInterpolSolverContext; + public class Z3ProofsTest { @@ -62,33 +64,22 @@ public void closeSolver() { } @Test - public void testGetProofExpr() throws SolverException, InterruptedException { + public void testTraverseProof() throws SolverException, InterruptedException { //example from the 2022 paper BooleanFormula q1 = bmgr.makeVariable("q1"); BooleanFormula q2 = bmgr.makeVariable("q2"); - BooleanFormula notQ1OrQ2 = bmgr.or(bmgr.not(q1), q2); - BooleanFormula q1True = bmgr.equivalence(q1, bmgr.makeTrue()); - BooleanFormula q2False = bmgr.equivalence(q2, bmgr.makeFalse()); Z3TheoremProver prover = (Z3TheoremProver) context.newProverEnvironment0(Set.of()); try { System.out.println("proofs enabled: " + context.getGenerateProofs()); - prover.addConstraint(notQ1OrQ2); - prover.addConstraint(q1True); - prover.addConstraint(q2False); - assertThat(prover.isUnsat()).isTrue(); + prover.addConstraint(bmgr.or(bmgr.not(q1), q2)); + prover.addConstraint(q1); + prover.addConstraint(bmgr.not(q2)); + assertTrue(prover.isUnsat()); - Context z3Context = createContextWithRawPointer(mgr.getFormulaCreator().getEnv()); - Solver solver = z3Context.mkSolver(); - //solver. + long proof = prover.getZ3Proof(); - //Expr proof = solver.getProof(); - //assertThat(proof).isNotNull(); - - //String proofStr = proof.toString(); - //System.out.println(proofStr); - //System.out.println(proof); } finally { prover.close(); } @@ -137,5 +128,38 @@ public void Z3ProofTest() { ctx.close(); } } + + public void encapsulateTest() { + HashMap cfg = new HashMap<>(); + cfg.put("proof", "true"); + Context ctx = new Context(cfg); + try { + // Create boolean variables + BoolExpr q1 = ctx.mkBoolConst("q1"); + BoolExpr q2 = ctx.mkBoolConst("q2"); + + // Create solver + Solver solver = ctx.mkSolver(); + + // Assert (or (not q1) q2) + solver.add(ctx.mkOr(ctx.mkNot(q1), q2)); + + // Assert q1 + solver.add(q1); + + // Assert (not q2) + solver.add(ctx.mkNot(q2)); + + Status status = solver.check(); + + System.out.println("Unsat: " + (status == Status.UNSATISFIABLE)); + + //Formula proof = Native.solverGetProof(ctx.nCtx(), ); + // System.out.println("proof: " + proof); + System.out.println(Version.getFullVersion()); + } finally { + ctx.close(); + } + } } diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java index 5ec0eae466..4e350821f5 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java @@ -21,10 +21,12 @@ import org.sosy_lab.common.ShutdownNotifier.ShutdownRequestListener; import org.sosy_lab.common.io.PathCounterTemplate; import org.sosy_lab.java_smt.api.BooleanFormula; +import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; import org.sosy_lab.java_smt.api.UserPropagator; +import org.sosy_lab.java_smt.api.proofs.ProofDAG; class Z3TheoremProver extends Z3AbstractProver implements ProverEnvironment { @@ -146,6 +148,24 @@ protected long getZ3Model() { } } + @Override + public ProofDAG getProof() { + return null; + } + + Formula getZ3ProofAsFormula(){ + long proof = Native.solverGetProof(z3context, z3solver); + return creator.encapsulate(creator.getFormulaType(proof), proof); + } + + long getZ3Proof(){ + return Native.solverGetProof(z3context, z3solver); + } + + long getZ3solver(){ + return z3solver; + } + @Override public int size() { Preconditions.checkState(!closed); From c2139ad5e528d6eb6cdb53c25eff48b1131b1e82 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Wed, 12 Mar 2025 10:28:26 +0100 Subject: [PATCH 007/132] Z3: Corrections to the parsing of the proof ast. Various changes to the ProofDAG interface and all classes inheriting it. --- .../java_smt/solvers/z3/Z3ProofNode.java | 31 +++++++++++-- .../java_smt/solvers/z3/Z3ProofParser.java | 24 +++++----- .../java_smt/solvers/z3/Z3ProofsTest.java | 46 +++++-------------- 3 files changed, 52 insertions(+), 49 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofNode.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofNode.java index 08850d7fd1..f34d762ec7 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofNode.java @@ -1,12 +1,35 @@ package org.sosy_lab.java_smt.solvers.z3; import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; -public class Z3ProofNode extends AbstractProofNode { +class Z3ProofNode extends AbstractProofNode { + + Z3ProofNode(Formula pFormula, ProofRule pProofRule) { + super(pProofRule, pFormula); + } + + String Z3ProofAsString() { + return Z3ProofAsString(0); + } + + private String Z3ProofAsString(int indentLevel) { + StringBuilder proof = new StringBuilder(); + String indent = " ".repeat(indentLevel); + + proof.append(indent).append("Formula: ").append(getFormula().toString()).append("\n"); + proof.append(indent).append("Rule: ").append(getRule().getName()).append("\n"); + proof.append(indent).append("No. Children: ").append(getChildren().size()).append("\n"); + + int i = 0; + for (ProofNode child : getChildren()) { + proof.append(indent).append("Child ").append(++i).append(":\n"); + proof.append(((Z3ProofNode) child).Z3ProofAsString(indentLevel + 1)); + } + + return proof.toString(); + } - public Z3ProofNode(Formula pFormula, ProofRule pProofRule) { - super(pProofRule, pFormula); - } } \ No newline at end of file diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofParser.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofParser.java index 9817e29466..a752e16c36 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofParser.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofParser.java @@ -43,10 +43,11 @@ Z3ProofNode fromAST(long proof) { Native.incRef(z3context, proof); long sort = Native.getSort(z3context, proof); + long sortKind = Native.getSortKind(z3context, sort); int declKind = Native.getDeclKind(z3context, Native.getAppDecl(z3context, proof)); int numArgs = Native.getAppNumArgs(z3context, proof); - Z3_sort_kind sort_kind = Z3_sort_kind.fromInt((int) sort); + Z3_sort_kind sort_kind = Z3_sort_kind.fromInt((int) sortKind); Formula formula; Z3ProofRule proofRule; @@ -169,18 +170,19 @@ private Z3ProofRule getPRfromDK(int declKind) { } } - @Nullable - private Formula getFromStoredConstraints(long proof) { - String varName = Native.astToString(z3context, proof); - if (prover.getStoredConstraints().peek().containsKey(varName)) { - return prover.getStoredConstraints().peek().get(varName); - } else { - return null; - } - } + //@Nullable + //private Formula getFromStoredConstraints(long proof) { + // String varName = Native.astToString(z3context, proof); + // if (prover.getStoredConstraints().peek().containsKey(varName)) { + // return prover.getStoredConstraints().peek().get(varName); + // } else { + // return null; + // } + // } private Formula generateFormula(long proof) { - Formula formula = getFromStoredConstraints(proof); + Formula formula = null; + //Formula formula = getFromStoredConstraints(proof); if (formula == null) { formula = formulaCreator.encapsulate(formulaCreator.getFormulaType(proof), proof); } diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java index 2aa0a0855a..b983f0d1fe 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java @@ -24,7 +24,9 @@ import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.FloatingPointRoundingMode; +import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; +import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.AbstractNumeralFormulaManager.NonLinearArithmetic; @@ -64,12 +66,15 @@ public void closeSolver() { } @Test - public void testTraverseProof() throws SolverException, InterruptedException { + public void printParsedProofTest() throws SolverException, InterruptedException { //example from the 2022 paper BooleanFormula q1 = bmgr.makeVariable("q1"); BooleanFormula q2 = bmgr.makeVariable("q2"); Z3TheoremProver prover = (Z3TheoremProver) context.newProverEnvironment0(Set.of()); + //Z3TheoremProver prover = + // (Z3TheoremProver) context.newProverEnvironment0(Set.of(ProverOptions + // .GENERATE_UNSAT_CORE)); try { System.out.println("proofs enabled: " + context.getGenerateProofs()); prover.addConstraint(bmgr.or(bmgr.not(q1), q2)); @@ -78,6 +83,11 @@ public void testTraverseProof() throws SolverException, InterruptedException { assertTrue(prover.isUnsat()); long proof = prover.getZ3Proof(); + Z3ProofParser parser = new Z3ProofParser(mgr.getEnvironment(), prover.getZ3solver(), + (Z3FormulaCreator) mgr.getFormulaCreator(), prover ); + Z3ProofNode root = parser.fromAST(proof); + + System.out.println(root.Z3ProofAsString()); } finally { @@ -96,7 +106,7 @@ public static Context createContextWithRawPointer(long m_ctx) { } @Test - public void Z3ProofTest() { + public void printZ3ProofAstTest() { HashMap cfg = new HashMap<>(); cfg.put("proof", "true"); Context ctx = new Context(cfg); @@ -129,37 +139,5 @@ public void Z3ProofTest() { } } - public void encapsulateTest() { - HashMap cfg = new HashMap<>(); - cfg.put("proof", "true"); - Context ctx = new Context(cfg); - try { - // Create boolean variables - BoolExpr q1 = ctx.mkBoolConst("q1"); - BoolExpr q2 = ctx.mkBoolConst("q2"); - - // Create solver - Solver solver = ctx.mkSolver(); - - // Assert (or (not q1) q2) - solver.add(ctx.mkOr(ctx.mkNot(q1), q2)); - - // Assert q1 - solver.add(q1); - - // Assert (not q2) - solver.add(ctx.mkNot(q2)); - - Status status = solver.check(); - - System.out.println("Unsat: " + (status == Status.UNSATISFIABLE)); - - //Formula proof = Native.solverGetProof(ctx.nCtx(), ); - // System.out.println("proof: " + proof); - System.out.println(Version.getFullVersion()); - } finally { - ctx.close(); - } - } } From e05451c275ebd754eb2e730d140c8f93cad0b62c Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 14 Mar 2025 19:12:11 +0100 Subject: [PATCH 008/132] Mathsat5: The Native API now includes the methods for proof processing --- .../source/libmathsat5j/includes/defines.h | 10 +++ ..._1smt_solvers_mathsat5_Mathsat5NativeApi.c | 73 +++++++++++++++++++ .../solvers/mathsat5/Mathsat5NativeApi.java | 18 +++++ .../mathsat5/Mathsat5NativeApiTest.java | 31 ++++++++ .../smtinterpol/SmtInterpolProofsTest.java | 2 + .../java_smt/solvers/z3/Z3ProofsTest.java | 3 +- 6 files changed, 136 insertions(+), 1 deletion(-) diff --git a/lib/native/source/libmathsat5j/includes/defines.h b/lib/native/source/libmathsat5j/includes/defines.h index 2b707fe9c1..7e4010f43e 100644 --- a/lib/native/source/libmathsat5j/includes/defines.h +++ b/lib/native/source/libmathsat5j/includes/defines.h @@ -372,6 +372,16 @@ typedef jvoid jjfailureCode; typedef jobject jjnamedtermswrapper; +typedef jlong jjproofManager; +#define MANAGER_ARG(num) STRUCT_ARG(msat_proof_manager, num) +#define MANAGER_ARG_VOID(num) STRUCT_ARG_VOID(msat_proof_manager, num) +#define MANAGER_RETURN STRUCT_RETURN + +typedef jlong jjproof; +#define PROOF_ARG(num) STRUCT_ARG(msat_proof, num) +#define PROOF_ARG_VOID(num) STRUCT_ARG_VOID(msat_proof, num) +#define PROOF_RETURN STRUCT_RETURN + // Abbreviations for common combinations of return and argument types // // Parameter explanation: diff --git a/lib/native/source/libmathsat5j/org_sosy_1lab_java_1smt_solvers_mathsat5_Mathsat5NativeApi.c b/lib/native/source/libmathsat5j/org_sosy_1lab_java_1smt_solvers_mathsat5_Mathsat5NativeApi.c index 30831f2a1b..26b376c53a 100644 --- a/lib/native/source/libmathsat5j/org_sosy_1lab_java_1smt_solvers_mathsat5_Mathsat5NativeApi.c +++ b/lib/native/source/libmathsat5j/org_sosy_1lab_java_1smt_solvers_mathsat5_Mathsat5NativeApi.c @@ -1206,6 +1206,79 @@ TERM_ARRAY_OUTPUT_ARG(2) CALL2(msat_term*, get_unsat_core) RETURN_TERM_ARRAY(2) +//Proof functions +/* + * msat_proof_manager msat_get_proof_manager(msat_env e) + */ +DEFINE_FUNC(jproofManager, 1get_1proof_1manager) WITH_ONE_ARG(jenv) +ENV_ARG(1) +CALL1(msat_proof_manager, get_proof_manager) +STRUCT_RETURN_WITH_ENV + +/* + * void msat_destroy_proof_manager(msat_proof_manager m) + */ +DEFINE_FUNC(void, 1destroy_1proof_1manager) WITH_ONE_ARG(jproofManager) +MANAGER_ARG_VOID(1) +VOID_CALL1(destroy_proof_manager) + +/* + * msat_proof msat_get_proof(msat_proof_manager m) + */ +DEFINE_FUNC(jproof, 1get_1proof) WITH_ONE_ARG(jproofManager) +MANAGER_ARG(1) +CALL1(msat_proof, get_proof) +PROOF_RETURN + +/* + * size_t msat_proof_id(msat_proof p) + */ +DEFINE_FUNC(int, 1proof_1id) WITH_ONE_ARG(jproof) +PROOF_ARG(1) +CALL1(int, proof_id) +INT_RETURN + +/* + * int msat_proof_is_term(msat_proof p) + */ +DEFINE_FUNC(int, 1proof_1is_1term) WITH_ONE_ARG(jproof) +PROOF_ARG(1) +CALL1(int, proof_is_term) +BOOLEAN_RETURN + +/* + * msat_term msat_proof_get_term(msat_proof p) + */ +DEFINE_FUNC(jterm, 1proof_1get_1term) WITH_ONE_ARG(jproof) +PROOF_ARG(1) +CALL1(msat_term, proof_get_term) +STRUCT_RETURN + +/* + * const char* msat_proof_get_name(msat_proof p) + */ +DEFINE_FUNC(string, 1proof_1get_1name) WITH_ONE_ARG(jproof) +PROOF_ARG(1) +CALL1(const char*, proof_get_name) +PLAIN_CONST_STRING_RETURN + +/* + * size_t msat_proof_get_arity(msat_proof p) + */ +DEFINE_FUNC(int, 1proof_1get_1arity) WITH_ONE_ARG(jproof) +PROOF_ARG(1) +CALL1(size_t, proof_get_arity) +INT_RETURN + +/* + * msat_proof msat_proof_get_child(msat_proof p, size_t i) + */ +DEFINE_FUNC(jproof, 1proof_1get_1child) WITH_TWO_ARGS(jproof, int) +PROOF_ARG(1) +SIMPLE_ARG(size_t, 2) +CALL2(msat_proof, proof_get_child) +PROOF_RETURN + DEFINE_FUNC(jterm, 1simplify) WITH_FOUR_ARGS(jenv, jterm, jtermArray, int) ENV_ARG(1) TERM_ARG(2) diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApi.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApi.java index 28300c3a67..041b42fb63 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApi.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApi.java @@ -788,6 +788,24 @@ private static native int msat_all_sat( public static native long[] msat_get_unsat_core(long e); + public static native long msat_get_proof_manager(long env); + + public static native void msat_destroy_proof_manager(long proofManager); + + public static native long msat_get_proof(long proofManager); + + public static native long msat_proof_id(long proof); + + public static native int msat_proof_is_term(long proof); + + public static native long msat_proof_get_term(long proof); + + public static native String msat_proof_get_name(long proof); + + public static native long msat_proof_get_arity(long proof); + + public static native long msat_proof_get_child(long proof, long index); + /* * Special functions */ diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java index d9021f64cd..34a63e6bd6 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java @@ -17,13 +17,17 @@ import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_decl_get_name; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_destroy_config; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_destroy_model_iterator; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_destroy_proof_manager; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_from_smtlib2; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_enum_constants; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_enum_type; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_integer_type; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_model; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_model_value; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_proof; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_proof_manager; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_rational_type; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_unsat_core; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_is_enum_type; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_is_integer_type; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_make_asin; @@ -43,11 +47,13 @@ import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_model_iterator_has_next; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_model_iterator_next; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_pop_backtrack_point; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_get_term; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_push_backtrack_point; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_set_option_checked; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_term_get_type; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_term_is_pi; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_term_repr; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_to_smtlib2; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_type_equals; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_type_repr; @@ -79,6 +85,7 @@ public void createEnvironment() { long cfg = msat_create_config(); msat_set_option_checked(cfg, "model_generation", "true"); + msat_set_option_checked(cfg, "proof_generation", "true"); // msat_set_option_checked(cfg, "theory.la.split_rat_eq", "false"); env = msat_create_env(cfg); @@ -526,4 +533,28 @@ public void enumTypeTest() throws SolverException, InterruptedException { assertThat(msat_check_sat(env)).isFalse(); msat_pop_backtrack_point(env); } + + @Test + public void printProofTest() throws SolverException, InterruptedException { + //long config = msat_create_config(); + //msat_set_option_checked(config, "proof_generation", "true"); + //long env = msat_create_env(config); + long q1 = msat_from_smtlib2(env, "(set-logic QF_UF)\n" + + "(declare-fun q1 () Bool)\n" + + "(declare-fun q2 () Bool)\n" + + "(assert (or (not q1) q2))\n" + + "(assert q1)+\n" + + "(assert (not q2))"); + msat_assert_formula(env, msat_make_not(env, q1)); + System.out.println("sat: " + msat_check_sat(env)); + long model = msat_get_model(env); + //assertThat(msat_check_sat(env)).isFalse(); + + //long pm = msat_get_proof_manager(env); + //long proof = msat_get_proof(pm); + //long termProof = msat_proof_get_term(proof); + //String res = msat_to_smtlib2(env, termProof); + //System.out.println("proof: " + res); + //msat_destroy_proof_manager(pm); + } } diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java index d1fc18c9ff..2baefeda04 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java @@ -24,6 +24,7 @@ import java.util.Set; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.sosy_lab.common.ShutdownManager; import org.sosy_lab.common.configuration.Configuration; @@ -39,6 +40,7 @@ import org.sosy_lab.java_smt.basicimpl.AbstractFormulaManager; import org.sosy_lab.java_smt.basicimpl.AbstractNumeralFormulaManager.NonLinearArithmetic; +@Ignore("prevent this class being executed as testcase by ant") public class SmtInterpolProofsTest { private SmtInterpolSolverContext context; diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java index b983f0d1fe..76476d3a2d 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java @@ -14,6 +14,7 @@ import java.util.Set; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.sosy_lab.common.NativeLibraries; import org.sosy_lab.common.ShutdownManager; @@ -29,7 +30,7 @@ import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.AbstractNumeralFormulaManager.NonLinearArithmetic; - +@Ignore("prevent this class being executed as testcase by ant") public class Z3ProofsTest { private Z3SolverContext context; From a6a3efd1c08bc14ecb276411258a2f485a11854a Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 17 Mar 2025 14:49:15 +0100 Subject: [PATCH 009/132] Z3: The transitivity proof step from Z3 is now able to be converted to multiple resolution steps. --- src/org/sosy_lab/java_smt/ResProofRule.java | 11 +- .../sosy_lab/java_smt/ResolutionProofDAG.java | 22 +- .../java_smt/ResolutionProofNode.java | 7 +- .../sosy_lab/java_smt/SourceProofNode.java | 5 +- .../mathsat5/Mathsat5NativeApiTest.java | 18 +- .../solvers/smtinterpol/ProofTermParser.java | 1 + .../SmtInterpolAbstractProver.java | 6 +- .../smtinterpol/SmtInterpolProofNode.java | 6 +- .../smtinterpol/SmtInterpolProofsTest.java | 5 +- .../java_smt/solvers/z3/ProofConverter.java | 263 ++++++++++++++++++ .../java_smt/solvers/z3/Z3ProofParser.java | 3 +- .../java_smt/solvers/z3/Z3ProofRule.java | 3 +- .../java_smt/solvers/z3/Z3ProofsTest.java | 25 +- 13 files changed, 333 insertions(+), 42 deletions(-) create mode 100644 src/org/sosy_lab/java_smt/solvers/z3/ProofConverter.java diff --git a/src/org/sosy_lab/java_smt/ResProofRule.java b/src/org/sosy_lab/java_smt/ResProofRule.java index 8c81c29f03..698f7591f3 100644 --- a/src/org/sosy_lab/java_smt/ResProofRule.java +++ b/src/org/sosy_lab/java_smt/ResProofRule.java @@ -113,10 +113,12 @@ public enum ResAxiom implements ProofRule { formula = pFormula; } + @Override public String getName() { return name; } + @Override public String getFormula() { return formula; } @@ -126,14 +128,21 @@ public String getFormula() { * Retrieves a ProofRule by its name. * * @param name The name of the proof rule. - * @return The matching ProofRule, or null if not found. + * @return The matching ProofRule. + * @throws NullPointerException if the name is null. + * @throws IllegalArgumentException if the name does not match any rule. */ public static ResAxiom getResAxiomRuleByName(String name) { + if (name == null) { + throw new NullPointerException("Rule name cannot be null"); + } + for (ResAxiom rule : ResAxiom.values()) { if (rule.getName().equalsIgnoreCase(name)) { return rule; } } + throw new IllegalArgumentException("Rule not found or not specified: " + name); } diff --git a/src/org/sosy_lab/java_smt/ResolutionProofDAG.java b/src/org/sosy_lab/java_smt/ResolutionProofDAG.java index 534ee99e3b..74f899de14 100644 --- a/src/org/sosy_lab/java_smt/ResolutionProofDAG.java +++ b/src/org/sosy_lab/java_smt/ResolutionProofDAG.java @@ -20,20 +20,15 @@ import org.sosy_lab.java_smt.basicimpl.AbstractProofDAG; import org.sosy_lab.java_smt.solvers.smtinterpol.ProofTermParser; +@SuppressWarnings("all") public class ResolutionProofDAG extends AbstractProofDAG { + /* public ResolutionProofDAG() { super(); } - /** - * Converts the proof Term returned from SMTInterpol into a ResolutionProofDAG. - * This version traverses AnnotatedTerm instances looking for annotations with key - * ProofConstants.ANNOTKEY_PROVES and uses the associated clause string. - * - * @param proof the proof term - * @return a ResolutionProofDAG representing the proof - */ + public static ResolutionProofDAG fromTerm( Term proof, FormulaManager pManager, Map pAnnotatedTerms) { @@ -42,13 +37,6 @@ public static ResolutionProofDAG fromTerm( return ProofTermParser.convert(proof, pManager, pAnnotatedTerms); } - /** - * Recursively traverses the annotated proof term. - * - * @param term the current term - * @param dag the proof DAG being constructed - * @param parentClause the clause from the parent annotation (if available) - */ private static void traverseTerm(Term term, ResolutionProofDAG dag, ProofNode parentClause) { if (term instanceof AnnotatedTerm) { AnnotatedTerm annotatedTerm = (AnnotatedTerm) term; @@ -66,7 +54,7 @@ private static void traverseTerm(Term term, ResolutionProofDAG dag, ProofNode pa } } - */ + } } } @@ -87,4 +75,6 @@ public ProofNode getNode(int nodeId) { public void addEdge(int parentNodeId, int childNodeId) { super.addEdge(parentNodeId, childNodeId); } + + */ } diff --git a/src/org/sosy_lab/java_smt/ResolutionProofNode.java b/src/org/sosy_lab/java_smt/ResolutionProofNode.java index 6f823aa9b9..d6c66aa826 100644 --- a/src/org/sosy_lab/java_smt/ResolutionProofNode.java +++ b/src/org/sosy_lab/java_smt/ResolutionProofNode.java @@ -10,6 +10,7 @@ package org.sosy_lab.java_smt; +import java.util.Objects; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.api.proofs.ProofRule; @@ -22,11 +23,12 @@ public class ResolutionProofNode extends AbstractProofNode private final Formula pivot; public ResolutionProofNode(Formula formula, Formula pivot) { - super(ResAxiom.RESOLUTION, formula); - this.pivot = pivot; + super(ResAxiom.RESOLUTION, Objects.requireNonNull(formula, "Formula must not be null")); + this.pivot = Objects.requireNonNull(pivot, "Pivot must not be null"); } + @Override public boolean isSource() { return false; @@ -36,6 +38,7 @@ public Formula getPivot() { return pivot; } + @Override public ProofRule getRule() { return super.getRule(); } diff --git a/src/org/sosy_lab/java_smt/SourceProofNode.java b/src/org/sosy_lab/java_smt/SourceProofNode.java index 58714114a4..d1b3420cc9 100644 --- a/src/org/sosy_lab/java_smt/SourceProofNode.java +++ b/src/org/sosy_lab/java_smt/SourceProofNode.java @@ -10,6 +10,7 @@ package org.sosy_lab.java_smt; +import java.util.Objects; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; @@ -20,7 +21,9 @@ public class SourceProofNode extends AbstractProofNode public SourceProofNode(ResAxiom rule, Formula formula) { - super(rule, formula); + super( + Objects.requireNonNull(rule, "Rule must not be null"), + Objects.requireNonNull(formula, "Formula must not be null")); } diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java index 34a63e6bd6..b57333e309 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java @@ -534,23 +534,23 @@ public void enumTypeTest() throws SolverException, InterruptedException { msat_pop_backtrack_point(env); } + @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) @Test public void printProofTest() throws SolverException, InterruptedException { - //long config = msat_create_config(); - //msat_set_option_checked(config, "proof_generation", "true"); - //long env = msat_create_env(config); - long q1 = msat_from_smtlib2(env, "(set-logic QF_UF)\n" + + long config = msat_create_config(); + msat_set_option_checked(config, "proof_generation", "true"); + long env = msat_create_env(config); + long q1 = msat_from_smtlib2(env, "(declare-fun q1 () Bool)\n" + "(declare-fun q2 () Bool)\n" + "(assert (or (not q1) q2))\n" + "(assert q1)+\n" + "(assert (not q2))"); - msat_assert_formula(env, msat_make_not(env, q1)); - System.out.println("sat: " + msat_check_sat(env)); - long model = msat_get_model(env); - //assertThat(msat_check_sat(env)).isFalse(); + msat_assert_formula(env, q1); + //long model = msat_get_model(env); + assertThat(msat_check_sat(env)).isFalse(); - //long pm = msat_get_proof_manager(env); + long pm = msat_get_proof_manager(env); //long proof = msat_get_proof(pm); //long termProof = msat_proof_get_term(proof); //String res = msat_to_smtlib2(env, termProof); diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java index 917652ca81..a91275a9d3 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java @@ -16,6 +16,7 @@ //TODO: Correct parsing of the proof terms is missing, i.e. creation of nodes in the DAG and // parsing annotations. Add relevant javadocs +@SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) public class ProofTermParser { private final ResolutionProofDAG proofDag; diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java index da36a53ae9..6480d47339 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java @@ -37,7 +37,6 @@ import org.sosy_lab.common.collect.Collections3; import org.sosy_lab.common.collect.PathCopyingPersistentTreeMap; import org.sosy_lab.common.collect.PersistentMap; -import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.ResolutionProofDAG; import org.sosy_lab.java_smt.api.BasicProverEnvironment; import org.sosy_lab.java_smt.api.BooleanFormula; @@ -216,6 +215,7 @@ public ImmutableMap getStatistics() { return builder.buildOrThrow(); } + @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) @Override public ProofDAG getProof() { checkState(!closed); @@ -225,7 +225,7 @@ public ProofDAG getProof() { final ProofDAG proofDAG; try { proof = env.getProof(); - proofDAG = ResolutionProofDAG.fromTerm(proof, mgr, annotatedTerms.peek()); + //proofDAG = ResolutionProofDAG.fromTerm(proof, mgr, annotatedTerms.peek()); } catch (SMTLIBException e) { if (e.getMessage().contains("Context is inconsistent")) { throw new IllegalStateException("Cannot get proof from satisfiable environment", e); @@ -235,7 +235,7 @@ public ProofDAG getProof() { } //ResolutionProofDAG proofDag = fromSmtInterpol(proof, creator, getAssertedFormulas()); - return proofDAG; + return null; } //TODO: Delete this method diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNode.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNode.java index 274abc4a22..a206490ce8 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNode.java @@ -29,7 +29,7 @@ import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; - +@SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) class SmtInterpolProofNode extends AbstractProofNode { static class ResolutionProofDAGBuilder { private final SmtInterpolFormulaCreator creator; @@ -89,7 +89,7 @@ public void processResNode(SmtInterpolProofNode node) { if (node.getLeft() == null && node.getRight() == null) { throw new UnsupportedOperationException("Cannot process leaf node"); } else { - ResolutionNode rn = (ResolutionNode) node.node; + ResolutionNode rn = (ResolutionNode) SmtInterpolProofNode.node; Antecedent[] antecedents = rn.getAntecedents(); Literal pivot = antecedents[0].mPivot; node.transformed = new ResolutionProofNode(node.getFormula(), @@ -198,7 +198,7 @@ public void setRight(SmtInterpolProofNode node) { } private void setProofNode(ProofNode pNode) { - this.node = pNode; + node = pNode; } private static String getTermName(AnnotatedTerm pTerm) { diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java index 2baefeda04..ccbf46a352 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java @@ -19,7 +19,6 @@ import de.uni_freiburg.informatik.ultimate.smtinterpol.dpll.Clause; import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.ProofNode; import de.uni_freiburg.informatik.ultimate.smtinterpol.smtlib2.SMTInterpol; -import java.io.StringReader; import java.lang.reflect.Method; import java.util.Set; import org.junit.After; @@ -33,13 +32,11 @@ import org.sosy_lab.common.log.LogManager; import org.sosy_lab.java_smt.ResolutionProofDAG; import org.sosy_lab.java_smt.api.BooleanFormula; -import org.sosy_lab.java_smt.api.FormulaManager; -import org.sosy_lab.java_smt.api.NumeralFormula.IntegerFormula; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; -import org.sosy_lab.java_smt.basicimpl.AbstractFormulaManager; import org.sosy_lab.java_smt.basicimpl.AbstractNumeralFormulaManager.NonLinearArithmetic; +@SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) @Ignore("prevent this class being executed as testcase by ant") public class SmtInterpolProofsTest { diff --git a/src/org/sosy_lab/java_smt/solvers/z3/ProofConverter.java b/src/org/sosy_lab/java_smt/solvers/z3/ProofConverter.java new file mode 100644 index 0000000000..744f45f907 --- /dev/null +++ b/src/org/sosy_lab/java_smt/solvers/z3/ProofConverter.java @@ -0,0 +1,263 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.solvers.z3; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.transform.Source; +import org.sosy_lab.java_smt.ResProofRule.ResAxiom; +import org.sosy_lab.java_smt.ResolutionProofDAG; +import org.sosy_lab.java_smt.ResolutionProofNode; +import org.sosy_lab.java_smt.SourceProofNode; +import org.sosy_lab.java_smt.api.BooleanFormula; +import org.sosy_lab.java_smt.api.BooleanFormulaManager; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.FunctionDeclaration; +import org.sosy_lab.java_smt.api.QuantifiedFormulaManager.Quantifier; +import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.visitors.BooleanFormulaVisitor; +import org.sosy_lab.java_smt.api.visitors.TraversalProcess; +import org.sosy_lab.java_smt.solvers.z3.Z3ProofNode; +import org.sosy_lab.java_smt.solvers.z3.Z3ProofRule; + +import java.util.HashMap; +import java.util.Map; + + +@SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) +public class ProofConverter { + + private final Z3FormulaManager formulaManager; + + private final BooleanFormulaManager bfm; + + public ProofConverter(Z3FormulaManager creator) { + formulaManager = creator; + bfm = formulaManager.getBooleanFormulaManager(); + } + + private static final Map ruleMapping = new HashMap<>(); +/* + static { + ruleMapping.put(Z3ProofRule.UNDEF, ResAxiom.ORACLE); + ruleMapping.put(Z3ProofRule.TRUE, ResAxiom.TRUE_POSITIVE); + ruleMapping.put(Z3ProofRule.ASSERTED, ResAxiom.ASSUME); + ruleMapping.put(Z3ProofRule.GOAL, ResAxiom.ASSUME); + ruleMapping.put(Z3ProofRule.REFLEXIVITY, ResAxiom.REFLEXIVITY); + ruleMapping.put(Z3ProofRule.SYMMETRY, ResAxiom.SYMMETRY); + ruleMapping.put(Z3ProofRule.TRANSITIVITY, ResAxiom.TRANSITIVITY); + ruleMapping.put(Z3ProofRule.TRANSITIVITY_STAR, ResAxiom.TRANSITIVITY_STAR); + ruleMapping.put(Z3ProofRule.MONOTONICITY, ResAxiom.MONOTONICITY); + ruleMapping.put(Z3ProofRule.QUANT_INTRO, ResAxiom.QUANT_INTRO); + ruleMapping.put(Z3ProofRule.BIND, ResAxiom.BIND); + ruleMapping.put(Z3ProofRule.DISTRIBUTIVITY, ResAxiom.DISTRIBUTIVITY); + ruleMapping.put(Z3ProofRule.AND_ELIM, ResAxiom.AND_POSITIVE); + ruleMapping.put(Z3ProofRule.NOT_OR_ELIM, ResAxiom.NOT_NEGATIVE); + ruleMapping.put(Z3ProofRule.REWRITE, ResAxiom.REWRITE); + ruleMapping.put(Z3ProofRule.REWRITE_STAR, ResAxiom.REWRITE_STAR); + ruleMapping.put(Z3ProofRule.PULL_QUANT, ResAxiom.PULL_QUANT); + ruleMapping.put(Z3ProofRule.PUSH_QUANT, ResAxiom.PUSH_QUANT); + ruleMapping.put(Z3ProofRule.ELIM_UNUSED_VARS, ResAxiom.ELIM_UNUSED_VARS); + ruleMapping.put(Z3ProofRule.DER, ResAxiom.DER); + ruleMapping.put(Z3ProofRule.QUANT_INST, ResAxiom.QUANT_INST); + ruleMapping.put(Z3ProofRule.HYPOTHESIS, ResAxiom.HYPOTHESIS); + ruleMapping.put(Z3ProofRule.LEMMA, ResAxiom.LEMMA); + ruleMapping.put(Z3ProofRule.UNIT_RESOLUTION, ResAxiom.UNIT_RESOLUTION); + ruleMapping.put(Z3ProofRule.IFF_TRUE, ResAxiom.IFF_TRUE); + ruleMapping.put(Z3ProofRule.IFF_FALSE, ResAxiom.IFF_FALSE); + ruleMapping.put(Z3ProofRule.COMMUTATIVITY, ResAxiom.COMMUTATIVITY); + ruleMapping.put(Z3ProofRule.DEF_AXIOM, ResAxiom.DEF_AXIOM); + ruleMapping.put(Z3ProofRule.ASSUMPTION_ADD, ResAxiom.ASSUMPTION_ADD); + ruleMapping.put(Z3ProofRule.LEMMA_ADD, ResAxiom.LEMMA_ADD); + ruleMapping.put(Z3ProofRule.REDUNDANT_DEL, ResAxiom.REDUNDANT_DEL); + ruleMapping.put(Z3ProofRule.CLAUSE_TRAIL, ResAxiom.CLAUSE_TRAIL); + ruleMapping.put(Z3ProofRule.DEF_INTRO, ResAxiom.DEF_INTRO); + ruleMapping.put(Z3ProofRule.APPLY_DEF, ResAxiom.APPLY_DEF); + ruleMapping.put(Z3ProofRule.IFF_OEQ, ResAxiom.IFF_OEQ); + ruleMapping.put(Z3ProofRule.NNF_POS, ResAxiom.NNF_POS); + ruleMapping.put(Z3ProofRule.NNF_NEG, ResAxiom.NNF_NEG); + ruleMapping.put(Z3ProofRule.SKOLEMIZE, ResAxiom.SKOLEMIZE); + ruleMapping.put(Z3ProofRule.MODUS_PONENS_OEQ, ResAxiom.MODUS_PONENS_OEQ); + ruleMapping.put(Z3ProofRule.TH_LEMMA, ResAxiom.TH_LEMMA); + ruleMapping.put(Z3ProofRule.HYPER_RESOLVE, ResAxiom.HYPER_RESOLVE); + } + + */ + + /* + public static ResAxiom mapRule(Z3ProofRule z3Rule) { + return ruleMapping.getOrDefault(z3Rule, ResAxiom.OPERATION); + } + */ + + + public static ResolutionProofDAG convertToResolutionProofDAG(Z3ProofNode[] z3ProofNodes) { + ResolutionProofDAG dag = new ResolutionProofDAG(); + + for (Z3ProofNode z3Node : z3ProofNodes) { + if (z3Node.getRule() == Z3ProofRule.MODUS_PONENS) { + + } else { + Formula formula = z3Node.getFormula(); + //ResAxiom resAxiom = mapRule(z3Node.getRule()); + //SourceProofNode sourceNode = new SourceProofNode(resAxiom, formula); + //dag.addNode(sourceNode); + } + } + + return dag; + } + + private static class EquivalenceExtractor implements BooleanFormulaVisitor { + private final List equivalenceOperands = new ArrayList<>(); + + public List getEquivalenceOperands() { + return equivalenceOperands; + } + + @Override + public TraversalProcess visitEquivalence(BooleanFormula left, BooleanFormula right) { + equivalenceOperands.add(left); + equivalenceOperands.add(right); + return TraversalProcess.CONTINUE; + } + + @Override + public TraversalProcess visitImplication(BooleanFormula operand1, BooleanFormula operand2) { + return TraversalProcess.CONTINUE; + } + + @Override + public TraversalProcess visitConstant(boolean value) { + return TraversalProcess.CONTINUE; + } + + @Override + public TraversalProcess visitBoundVar(BooleanFormula var, int deBruijnIdx) { + return TraversalProcess.CONTINUE; + } + + @Override + public TraversalProcess visitNot(BooleanFormula operand) { + return TraversalProcess.CONTINUE; + } + + @Override + public TraversalProcess visitAnd(List operands) { + return TraversalProcess.CONTINUE; + } + + @Override + public TraversalProcess visitOr(List operands) { + return TraversalProcess.CONTINUE; + } + + @Override + public TraversalProcess visitXor(BooleanFormula operand1, BooleanFormula operand2) { + return TraversalProcess.CONTINUE; + } + + @Override + public TraversalProcess visitIfThenElse( + BooleanFormula condition, + BooleanFormula thenFormula, + BooleanFormula elseFormula) { + return TraversalProcess.CONTINUE; + } + + @Override + public TraversalProcess visitQuantifier( + Quantifier quantifier, + BooleanFormula quantifiedAST, + List boundVars, + BooleanFormula body) { + return TraversalProcess.CONTINUE; + } + + @Override + public TraversalProcess visitAtom( + BooleanFormula atom, + FunctionDeclaration funcDecl) { + return TraversalProcess.CONTINUE; + } + } + + public List extractEquivalenceOperands(BooleanFormula formula) { + EquivalenceExtractor extractor = new EquivalenceExtractor(); + bfm.visitRecursively(formula, extractor); + return extractor.getEquivalenceOperands(); + } + + ProofNode handleTrans(Z3ProofNode node) { + + BooleanFormula t1 = (BooleanFormula) node.getChildren().get(0).getFormula(); + BooleanFormula t2 = (BooleanFormula) node.getChildren().get(1).getFormula(); + + List equivalenceOperands1 = extractEquivalenceOperands(t1); + List equivalenceOperands2 = extractEquivalenceOperands(t2); + + assert equivalenceOperands1.get(1).equals(equivalenceOperands2.get(0)); + + BooleanFormula transRes = + bfm.equivalence(equivalenceOperands1.get(0), equivalenceOperands2.get(1)); + BooleanFormula transClause = bfm.or(bfm.not(t1), + bfm.not(t2), equivalenceOperands2.get(1)); + + SourceProofNode pn = new SourceProofNode(ResAxiom.TRANSITIVITY, transClause); + + ResolutionProofNode transResNode = new ResolutionProofNode(transRes, + t2); + ResolutionProofNode trnAnte1 = + new ResolutionProofNode(t2, t2); + BooleanFormula trn2Formula = bfm.or(bfm.not(t2), transRes); + ResolutionProofNode trnAnte2 = new ResolutionProofNode(trn2Formula, t1); + ResolutionProofNode trnAnte2Ante = new ResolutionProofNode(t1, t1); + + transResNode.addChild(trnAnte1); + transResNode.addChild(trnAnte2); + trnAnte2.addChild(trnAnte2Ante); + trnAnte2.addChild(pn); + + + return transResNode; + } + + void printProof(ProofNode node, int indentLevel) { + String indent = " ".repeat(indentLevel); + + if (node instanceof SourceProofNode) { + SourceProofNode sourceNode = (SourceProofNode) node; + System.out.println(indent + "Formula: " + sourceNode.getFormula()); + System.out.println(indent + "Rule: " + sourceNode.getRule()); + System.out.println(indent + "No. Children: " + sourceNode.getChildren().size()); + int i = 0; + for (ProofNode child : sourceNode.getChildren()) { + System.out.println(indent + "Child " + (++i) + ":"); + printProof(child, indentLevel + 1); + } + } else if (node instanceof ResolutionProofNode) { + ResolutionProofNode resolutionNode = (ResolutionProofNode) node; + System.out.println(indent + "Formula: " + resolutionNode.getFormula()); + System.out.println(indent + "Pivot: " + resolutionNode.getPivot()); + System.out.println(indent + "Rule: " + resolutionNode.getRule()); + System.out.println(indent + "No. Children: " + resolutionNode.getChildren().size()); + int i = 0; + for (ProofNode child : resolutionNode.getChildren()) { + System.out.println(indent + "Child " + (++i) + ":"); + printProof(child, indentLevel + 1); + } + } else { + throw new AssertionError("Unknown proof node type"); + } + } + + +} diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofParser.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofParser.java index a752e16c36..15430080bf 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofParser.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofParser.java @@ -16,9 +16,9 @@ import com.microsoft.z3.enumerations.Z3_sort_kind; import java.util.HashMap; import java.util.Map; -import org.checkerframework.checker.nullness.qual.Nullable; import org.sosy_lab.java_smt.api.Formula; +@SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) public class Z3ProofParser { private final long z3context; private final long z3solver; @@ -188,6 +188,7 @@ private Formula generateFormula(long proof) { } return formula; } + } diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java index acf56a181d..e6fa958eb1 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java @@ -10,7 +10,6 @@ package org.sosy_lab.java_smt.solvers.z3; -import javax.annotation.Nullable; import org.sosy_lab.java_smt.api.proofs.ProofRule; //TODO correctly document the formula strings @@ -94,10 +93,12 @@ public enum Z3ProofRule implements ProofRule { this.formula = formula; } + @Override public String getName() { return name; } + @Override public String getFormula() { return formula; } diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java index 76476d3a2d..b4230d85d4 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java @@ -30,6 +30,7 @@ import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.AbstractNumeralFormulaManager.NonLinearArithmetic; +@SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) @Ignore("prevent this class being executed as testcase by ant") public class Z3ProofsTest { @@ -85,7 +86,7 @@ public void printParsedProofTest() throws SolverException, InterruptedException long proof = prover.getZ3Proof(); Z3ProofParser parser = new Z3ProofParser(mgr.getEnvironment(), prover.getZ3solver(), - (Z3FormulaCreator) mgr.getFormulaCreator(), prover ); + (Z3FormulaCreator) mgr.getFormulaCreator(), prover); Z3ProofNode root = parser.fromAST(proof); System.out.println(root.Z3ProofAsString()); @@ -140,5 +141,27 @@ public void printZ3ProofAstTest() { } } + @Test + public void handleTransTest() { + BooleanFormula f1 = bmgr.makeVariable("f1"); + BooleanFormula f2 = bmgr.makeVariable("f2"); + BooleanFormula f3 = bmgr.makeVariable("f3"); + BooleanFormula equiv1 = bmgr.equivalence(f1, f2); + BooleanFormula equiv2 = bmgr.equivalence(f2, f3); + BooleanFormula equiv3 = bmgr.equivalence(f1, f3); + + Z3ProofNode pn = new Z3ProofNode(equiv3, Z3ProofRule.TRANSITIVITY); + pn.addChild(new Z3ProofNode(equiv1, Z3ProofRule.ASSERTED)); + pn.addChild(new Z3ProofNode(equiv2, Z3ProofRule.ASSERTED)); + + ProofConverter pc = new ProofConverter(mgr); + + ProofNode res = pc.handleTrans(pn); + + pc.printProof(res, 0); + + + } + } From 2015b46090f38b502c392fa0384cad77e7fe672b Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 17 Mar 2025 17:06:59 +0100 Subject: [PATCH 010/132] Z3: Small correction when converting the transitivity proof rule to resolution steps. --- src/org/sosy_lab/java_smt/solvers/z3/ProofConverter.java | 8 ++++---- src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/z3/ProofConverter.java b/src/org/sosy_lab/java_smt/solvers/z3/ProofConverter.java index 744f45f907..43d21407b1 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/ProofConverter.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/ProofConverter.java @@ -200,6 +200,7 @@ ProofNode handleTrans(Z3ProofNode node) { BooleanFormula t1 = (BooleanFormula) node.getChildren().get(0).getFormula(); BooleanFormula t2 = (BooleanFormula) node.getChildren().get(1).getFormula(); + BooleanFormula formula = (BooleanFormula) node.getFormula(); List equivalenceOperands1 = extractEquivalenceOperands(t1); List equivalenceOperands2 = extractEquivalenceOperands(t2); @@ -207,9 +208,9 @@ ProofNode handleTrans(Z3ProofNode node) { assert equivalenceOperands1.get(1).equals(equivalenceOperands2.get(0)); BooleanFormula transRes = - bfm.equivalence(equivalenceOperands1.get(0), equivalenceOperands2.get(1)); + formula; BooleanFormula transClause = bfm.or(bfm.not(t1), - bfm.not(t2), equivalenceOperands2.get(1)); + bfm.not(t2), formula); SourceProofNode pn = new SourceProofNode(ResAxiom.TRANSITIVITY, transClause); @@ -225,8 +226,7 @@ ProofNode handleTrans(Z3ProofNode node) { transResNode.addChild(trnAnte2); trnAnte2.addChild(trnAnte2Ante); trnAnte2.addChild(pn); - - + return transResNode; } diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java index b4230d85d4..8f0f1c2a37 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java @@ -154,6 +154,8 @@ public void handleTransTest() { pn.addChild(new Z3ProofNode(equiv1, Z3ProofRule.ASSERTED)); pn.addChild(new Z3ProofNode(equiv2, Z3ProofRule.ASSERTED)); + System.out.println(pn.Z3ProofAsString()); + ProofConverter pc = new ProofConverter(mgr); ProofNode res = pc.handleTrans(pn); From a4bbe6243cd4ac82c968ee4538ca9f97e766c939 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 17 Mar 2025 20:07:41 +0100 Subject: [PATCH 011/132] Z3: True, Asserted, Goal, MP, Reflexivity and Symmetry proof rules can now be converted to resolution proof rules. --- ...ofConverter.java => Z3ProofConverter.java} | 336 +++++++++++++++++- .../java_smt/solvers/z3/Z3ProofsTest.java | 5 +- 2 files changed, 330 insertions(+), 11 deletions(-) rename src/org/sosy_lab/java_smt/solvers/z3/{ProofConverter.java => Z3ProofConverter.java} (57%) diff --git a/src/org/sosy_lab/java_smt/solvers/z3/ProofConverter.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofConverter.java similarity index 57% rename from src/org/sosy_lab/java_smt/solvers/z3/ProofConverter.java rename to src/org/sosy_lab/java_smt/solvers/z3/Z3ProofConverter.java index 43d21407b1..f37e8a74ab 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/ProofConverter.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofConverter.java @@ -10,9 +10,10 @@ package org.sosy_lab.java_smt.solvers.z3; +import static org.sosy_lab.java_smt.solvers.z3.Z3ProofRule.MODUS_PONENS; + import java.util.ArrayList; import java.util.List; -import javax.xml.transform.Source; import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.ResolutionProofDAG; import org.sosy_lab.java_smt.ResolutionProofNode; @@ -25,21 +26,19 @@ import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.api.visitors.BooleanFormulaVisitor; import org.sosy_lab.java_smt.api.visitors.TraversalProcess; -import org.sosy_lab.java_smt.solvers.z3.Z3ProofNode; -import org.sosy_lab.java_smt.solvers.z3.Z3ProofRule; import java.util.HashMap; import java.util.Map; @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) -public class ProofConverter { +public class Z3ProofConverter { private final Z3FormulaManager formulaManager; private final BooleanFormulaManager bfm; - public ProofConverter(Z3FormulaManager creator) { + public Z3ProofConverter(Z3FormulaManager creator) { formulaManager = creator; bfm = formulaManager.getBooleanFormulaManager(); } @@ -103,7 +102,7 @@ public static ResolutionProofDAG convertToResolutionProofDAG(Z3ProofNode[] z3Pro ResolutionProofDAG dag = new ResolutionProofDAG(); for (Z3ProofNode z3Node : z3ProofNodes) { - if (z3Node.getRule() == Z3ProofRule.MODUS_PONENS) { + if (z3Node.getRule() == MODUS_PONENS) { } else { Formula formula = z3Node.getFormula(); @@ -196,7 +195,182 @@ public List extractEquivalenceOperands(BooleanFormula formula) { return extractor.getEquivalenceOperands(); } - ProofNode handleTrans(Z3ProofNode node) { + ProofNode handleNode(Z3ProofNode node) { + Z3ProofRule rule = (Z3ProofRule) node.getRule(); + + switch (rule) { + case TRUE: + return handleTrue(node); + + case ASSERTED: + return handleAsserted(node); + + case GOAL: + return handleAsserted(node); + + case MODUS_PONENS: + return handleModusPonens(node); + + case REFLEXIVITY: + return handleReflexivity(node); + + case SYMMETRY: + return handleSymmetry(node); + + case TRANSITIVITY: + return handleTransitivity(node); + + case TRANSITIVITY_STAR: + return handleTransitivityStar(node); + + case MONOTONICITY: + return handleMonotonicity(node); + + case QUANT_INTRO: + return handleQuantIntro(node); + + case BIND: + return handleBind(node); + + case DISTRIBUTIVITY: + return handleDistributivity(node); + + case AND_ELIM: + return handleAndElim(node); + + case NOT_OR_ELIM: + return handleNotOrElim(node); + + case REWRITE: + return handleRewrite(node); + + case REWRITE_STAR: + return handleRewriteStar(node); + + case PULL_QUANT: + return handlePullQuant(node); + + case PUSH_QUANT: + return handlePushQuant(node); + + case ELIM_UNUSED_VARS: + return handleElimUnusedVars(node); + + case DER: + return handleDer(node); + + case QUANT_INST: + return handleQuantInst(node); + + case HYPOTHESIS: + return handleHypothesis(node); + + case LEMMA: + return handleLemma(node); + + case UNIT_RESOLUTION: + return handleUnitResolution(node); + + case IFF_TRUE: + return handleIffTrue(node); + + case IFF_FALSE: + return handleIffFalse(node); + + case COMMUTATIVITY: + return handleCommutativity(node); + + case DEF_AXIOM: + return handleDefAxiom(node); + + case ASSUMPTION_ADD: + return handleAssumptionAdd(node); + + case LEMMA_ADD: + return handleLemmaAdd(node); + + case REDUNDANT_DEL: + return handleRedundantDel(node); + + case CLAUSE_TRAIL: + return handleClauseTrail(node); + + case DEF_INTRO: + return handleDefIntro(node); + + case APPLY_DEF: + return handleApplyDef(node); + + case IFF_OEQ: + return handleIffOeq(node); + + case NNF_POS: + return handleNnfPos(node); + + case NNF_NEG: + return handleNnfNeg(node); + + case SKOLEMIZE: + return handleSkolemize(node); + + case MODUS_PONENS_OEQ: + return handleModusPonensOeq(node); + + case TH_LEMMA: + return handleThLemma(node); + + case HYPER_RESOLVE: + return handleHyperResolve(node); + + case OPERATION: + return handleOperation(node); + + default: + return handleDefault(node); + } + } + + ProofNode handleTrue(Z3ProofNode node) { + BooleanFormula formula = (BooleanFormula) node.getFormula(); + SourceProofNode pn = new SourceProofNode(ResAxiom.TRUE_POSITIVE, formula); + return pn; + } + + ProofNode handleAsserted(Z3ProofNode node) { + BooleanFormula formula = (BooleanFormula) node.getFormula(); + SourceProofNode pn = new SourceProofNode(ResAxiom.ASSUME, formula); + return pn; + } + + ProofNode handleModusPonens(Z3ProofNode node) { + BooleanFormula formula = (BooleanFormula) node.getFormula(); + BooleanFormula pivot = (BooleanFormula) node.getChildren().get(0).getFormula(); + ResolutionProofNode pn = new ResolutionProofNode(formula, pivot); + ProofNode c1 = handleNode((Z3ProofNode) node.getChildren().get(0)); + ProofNode c2 = handleNode((Z3ProofNode) node.getChildren().get(1)); + return pn; + } + + ProofNode handleReflexivity(Z3ProofNode node) { + BooleanFormula formula = (BooleanFormula) node.getFormula(); + SourceProofNode pn = new SourceProofNode(ResAxiom.REFLEXIVITY, formula); + return pn; + } + + ProofNode handleSymmetry(Z3ProofNode node) { + BooleanFormula formula = (BooleanFormula) node.getFormula(); + BooleanFormula pivot = (BooleanFormula) node.getChildren().get(0).getFormula(); + BooleanFormula snFormula = bfm.or(bfm.not(pivot), formula); + + ResolutionProofNode pn = new ResolutionProofNode(formula, pivot); + SourceProofNode sn = new SourceProofNode(ResAxiom.SYMMETRY, snFormula); + pn.addChild(sn); + pn.addChild(handleNode((Z3ProofNode) node.getChildren().get(0))); + return pn; + } + + + ProofNode handleTransitivity(Z3ProofNode node) { BooleanFormula t1 = (BooleanFormula) node.getChildren().get(0).getFormula(); BooleanFormula t2 = (BooleanFormula) node.getChildren().get(1).getFormula(); @@ -226,10 +400,156 @@ ProofNode handleTrans(Z3ProofNode node) { transResNode.addChild(trnAnte2); trnAnte2.addChild(trnAnte2Ante); trnAnte2.addChild(pn); - + return transResNode; } + ProofNode handleTransitivityStar(Z3ProofNode node) { + return null; + } + + ProofNode handleMonotonicity(Z3ProofNode node) { + return null; + } + + ProofNode handleQuantIntro(Z3ProofNode node) { + return null; + } + + ProofNode handleBind(Z3ProofNode node) { + return null; + } + + ProofNode handleDistributivity(Z3ProofNode node) { + return null; + } + + ProofNode handleAndElim(Z3ProofNode node) { + return null; + } + + ProofNode handleNotOrElim(Z3ProofNode node) { + return null; + } + + ProofNode handleRewrite(Z3ProofNode node) { + return null; + } + + ProofNode handleRewriteStar(Z3ProofNode node) { + return null; + } + + ProofNode handlePullQuant(Z3ProofNode node) { + return null; + } + + ProofNode handleElimUnusedVars(Z3ProofNode node) { + return null; + } + + ProofNode handlePushQuant(Z3ProofNode node) { + return null; + } + + ProofNode handleDer(Z3ProofNode node) { + return null; + } + + ProofNode handleQuantInst(Z3ProofNode node) { + return null; + } + + ProofNode handleHypothesis(Z3ProofNode node) { + return null; + } + + ProofNode handleLemma(Z3ProofNode node) { + return null; + } + + ProofNode handleUnitResolution(Z3ProofNode node) { + return null; + } + + ProofNode handleIffTrue(Z3ProofNode node) { + return null; + } + + ProofNode handleIffFalse(Z3ProofNode node) { + return null; + } + + ProofNode handleCommutativity(Z3ProofNode node) { + return null; + } + + ProofNode handleDefAxiom(Z3ProofNode node) { + return null; + } + + ProofNode handleAssumptionAdd(Z3ProofNode node) { + return null; + } + + ProofNode handleLemmaAdd(Z3ProofNode node) { + return null; + } + + ProofNode handleRedundantDel(Z3ProofNode node) { + return null; + } + + ProofNode handleClauseTrail(Z3ProofNode node) { + return null; + } + + ProofNode handleDefIntro(Z3ProofNode node) { + return null; + } + + ProofNode handleApplyDef(Z3ProofNode node) { + return null; + } + + ProofNode handleIffOeq(Z3ProofNode node) { + return null; + } + + ProofNode handleNnfPos(Z3ProofNode node) { + return null; + } + + ProofNode handleNnfNeg(Z3ProofNode node) { + return null; + } + + ProofNode handleSkolemize(Z3ProofNode node) { + return null; + } + + ProofNode handleModusPonensOeq(Z3ProofNode node) { + return null; + } + + ProofNode handleThLemma(Z3ProofNode node) { + return null; + } + + ProofNode handleHyperResolve(Z3ProofNode node) { + return null; + } + + ProofNode handleOperation(Z3ProofNode node) { + return null; + } + + ProofNode handleDefault(Z3ProofNode node) { + return null; + } + + + void printProof(ProofNode node, int indentLevel) { String indent = " ".repeat(indentLevel); diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java index 8f0f1c2a37..456aa84402 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java @@ -25,7 +25,6 @@ import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.FloatingPointRoundingMode; -import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.AbstractNumeralFormulaManager.NonLinearArithmetic; @@ -156,9 +155,9 @@ public void handleTransTest() { System.out.println(pn.Z3ProofAsString()); - ProofConverter pc = new ProofConverter(mgr); + Z3ProofConverter pc = new Z3ProofConverter(mgr); - ProofNode res = pc.handleTrans(pn); + ProofNode res = pc.handleTransitivity(pn); pc.printProof(res, 0); From 59621397f45cfd9f954b55946fa164f0a4228302 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Wed, 19 Mar 2025 12:49:02 +0100 Subject: [PATCH 012/132] Refactor proof traversal, add tests, and add CVC5 support - Renamed some classes for clarity - Z3: Made proof traversal non-recursive for efficiency.Added tests for proof-related functionality - CVC5: Implemented necessary classes for proof production - Improved documentation - Added test for retrieving proofs in ProverEnvironmentTest.java --- .../java_smt/api/BasicProverEnvironment.java | 4 +- .../java_smt/api/proofs/ProofNode.java | 20 ++ .../java_smt/api/proofs/ProofRule.java | 9 + .../java_smt/basicimpl/AbstractProofNode.java | 6 +- .../java_smt/solvers/cvc5/CVC5ProofNode.java | 25 +++ .../solvers/cvc5/CVC5ProofParser.java | 14 ++ .../java_smt/solvers/cvc5/CVC5ProofRule.java | 27 +++ .../java_smt/solvers/cvc5/CVC5ProofsTest.java | 55 +++++ .../SmtInterpolAbstractProver.java | 4 +- .../z3/Z3NonRecursiveProofProcessor.java | 212 ++++++++++++++++++ ...ProofParser.java => Z3ProofProcessor.java} | 4 +- .../java_smt/solvers/z3/Z3ProofsTest.java | 135 ++++++++++- .../java_smt/solvers/z3/Z3SolverContext.java | 3 +- .../java_smt/solvers/z3/Z3TheoremProver.java | 21 +- ...r.java => Z3ToResoluteProofConverter.java} | 41 +++- .../java_smt/test/ProverEnvironmentTest.java | 34 ++- .../java_smt/test/SolverBasedTest0.java | 10 + 17 files changed, 584 insertions(+), 40 deletions(-) create mode 100644 src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java create mode 100644 src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofParser.java create mode 100644 src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofRule.java create mode 100644 src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java create mode 100644 src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java rename src/org/sosy_lab/java_smt/solvers/z3/{Z3ProofParser.java => Z3ProofProcessor.java} (99%) rename src/org/sosy_lab/java_smt/solvers/z3/{Z3ProofConverter.java => Z3ToResoluteProofConverter.java} (92%) diff --git a/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java b/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java index 9e99e84d1b..b446497397 100644 --- a/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java @@ -16,7 +16,7 @@ import java.util.Optional; import org.checkerframework.checker.nullness.qual.Nullable; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; -import org.sosy_lab.java_smt.api.proofs.ProofDAG; +import org.sosy_lab.java_smt.api.proofs.ProofNode; /** * Super interface for {@link ProverEnvironment} and {@link InterpolatingProverEnvironment} that @@ -154,7 +154,7 @@ default ImmutableMap getStatistics() { * Get proof of unsatisfiability of the conjuction of the current satck of all formulas. Should * only be called after {@link #isUnsat()} returned true. */ - default ProofDAG getProof() { + default ProofNode getProof() { try { throw new UnsupportedOperationException("Proof generation isn't enabled."); } catch (UnsupportedOperationException e) { diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java b/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java index e36aa6ebbf..4de58c5836 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java @@ -21,11 +21,31 @@ * @author Gabriel Carpio */ public interface ProofNode { + + /** + * Get the children of the proof node. + */ List getChildren(); + void addChild(ProofNode child); + boolean isSource(); + boolean isSink(); + void accept(ProofVisitor visitor); + + /** + * Get the formula of the proof node. + * + * @return The formula of the proof node. + */ Formula getFormula(); + + /** + * Get the id of the proof node. + * + * @return The id of the proof node. + */ int getId(); } diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofRule.java b/src/org/sosy_lab/java_smt/api/proofs/ProofRule.java index 1aa6227662..e853de39fe 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofRule.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofRule.java @@ -10,9 +10,18 @@ package org.sosy_lab.java_smt.api.proofs; +/** + * A proof rule from a given proof format. + */ public interface ProofRule { + /** + * Get the name of the proof rule. + */ String getName(); + /** + * Get the formula of the proof rule. + */ String getFormula(); } diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java index f50dc4be45..8935e8b807 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java @@ -18,11 +18,7 @@ import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.api.proofs.visitors.ProofVisitor; -/** - * A proof node in the proof DAG of a proof. - * - * @author Gabriel Carpio - */ + public abstract class AbstractProofNode implements ProofNode { private final List children; private ProofRule rule; diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java new file mode 100644 index 0000000000..8fcf4e0646 --- /dev/null +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java @@ -0,0 +1,25 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.solvers.cvc5; + +import org.sosy_lab.java_smt.api.proofs.ProofRule; +import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; +import org.sosy_lab.java_smt.api.Formula; + + +public class CVC5ProofNode extends AbstractProofNode { + + public CVC5ProofNode(ProofRule pProofRule, Formula formula) { + + super(pProofRule, formula); + } + +} diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofParser.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofParser.java new file mode 100644 index 0000000000..f88fb9eda1 --- /dev/null +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofParser.java @@ -0,0 +1,14 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.solvers.cvc5; + +public class CVC5ProofParser { +} diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofRule.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofRule.java new file mode 100644 index 0000000000..416629bcc0 --- /dev/null +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofRule.java @@ -0,0 +1,27 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.solvers.cvc5; + +import org.sosy_lab.java_smt.api.proofs.ProofRule; + +public enum CVC5ProofRule implements ProofRule { + ACI_RULE(); + + @Override + public String getName() { + return ""; + } + + @Override + public String getFormula() { + return ""; + } +} diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java new file mode 100644 index 0000000000..90e82ec3b9 --- /dev/null +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java @@ -0,0 +1,55 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.solvers.cvc5; + +import io.github.cvc5.CVC5ApiException; +import io.github.cvc5.Solver; +import org.junit.AssumptionViolatedException; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.sosy_lab.common.NativeLibraries; + +@Ignore +public class CVC5ProofsTest { + @BeforeClass + public static void loadCVC5() { + try { + CVC5SolverContext.loadLibrary(NativeLibraries::loadLibrary); + } catch (UnsatisfiedLinkError e) { + throw new AssumptionViolatedException("CVC5 is not available", e); + } + } + + private Solver solver; + + @Before + public void init() throws CVC5ApiException { + solver = createEnvironment(); + } + + private static Solver createEnvironment() throws CVC5ApiException { + Solver newSolver = new Solver(); + newSolver.setLogic("ALL"); + + // options + newSolver.setOption("incremental", "true"); + newSolver.setOption("produce-models", "true"); + newSolver.setOption("finite-model-find", "true"); + newSolver.setOption("sets-ext", "true"); + newSolver.setOption("output-language", "smtlib2"); + newSolver.setOption("strings-exp", "true"); + newSolver.setOption("produce-proofs", "true"); + + return newSolver; + } + +} diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java index 6480d47339..43c2537c9a 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java @@ -37,12 +37,12 @@ import org.sosy_lab.common.collect.Collections3; import org.sosy_lab.common.collect.PathCopyingPersistentTreeMap; import org.sosy_lab.common.collect.PersistentMap; -import org.sosy_lab.java_smt.ResolutionProofDAG; import org.sosy_lab.java_smt.api.BasicProverEnvironment; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; import org.sosy_lab.java_smt.api.proofs.ProofDAG; +import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.AbstractProver; import org.sosy_lab.java_smt.basicimpl.CachingModel; import org.sosy_lab.java_smt.basicimpl.FormulaCreator; @@ -217,7 +217,7 @@ public ImmutableMap getStatistics() { @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) @Override - public ProofDAG getProof() { + public ProofNode getProof() { checkState(!closed); checkGenerateProofs(); diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java new file mode 100644 index 0000000000..493c6247f2 --- /dev/null +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java @@ -0,0 +1,212 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.solvers.z3; + +import com.microsoft.z3.Native; +import com.microsoft.z3.enumerations.Z3_decl_kind; +import com.microsoft.z3.enumerations.Z3_sort_kind; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; +import org.sosy_lab.java_smt.api.Formula; + +/** + * This class is used to process the proof generated by Z3 and store it as a ProofNode. It + * is a non-recursive + * implementation of + * the proof processor. + */ +@SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) +class Z3NonRecursiveProofProcessor { + private final long z3context; + private final long z3solver; + private final Z3FormulaCreator formulaCreator; + private final Z3AbstractProver prover; + private final Map parsed = new HashMap<>(); + + Z3NonRecursiveProofProcessor( + long ctx, long solver, Z3FormulaCreator creator, + Z3AbstractProver pProver) { + z3context = ctx; + z3solver = solver; + formulaCreator = creator; + prover = pProver; + } + + Z3ProofNode fromASTIterative(long rootProof) { + + Deque stack = new ArrayDeque<>(); + + Map computed = new HashMap<>(); + + stack.push(new Frame(rootProof)); + + while (!stack.isEmpty()) { + Frame frame = stack.peek(); + + if (!frame.visited) { + + Native.incRef(z3context, frame.proof); + frame.numArgs = Native.getAppNumArgs(z3context, frame.proof); + frame.visited = true; + + for (int i = frame.numArgs - 2; i >= 0; i--) { + long arg = Native.getAppArg(z3context, frame.proof, i); + + if (!computed.containsKey(arg)) { + stack.push(new Frame(arg)); + } + } + } else { + + stack.pop(); + int numArgs = frame.numArgs; + Formula formula; + + long sort = Native.getSort(z3context, frame.proof); + long sortKind = Native.getSortKind(z3context, sort); + Z3_sort_kind sk = Z3_sort_kind.fromInt((int) sortKind); + if (sk != Z3_sort_kind.Z3_UNKNOWN_SORT) { + formula = generateFormula(frame.proof); + } else { + long z3expr = Native.getAppArg(z3context, frame.proof, numArgs - 1); + formula = generateFormula(z3expr); + } + int declKind = Native.getDeclKind(z3context, Native.getAppDecl(z3context, frame.proof)); + Z3ProofRule proofRule = getPRfromDK(declKind); + Z3ProofNode node = new Z3ProofNode(formula, proofRule); + + for (int i = 0; i < numArgs - 1; i++) { + long arg = Native.getAppArg(z3context, frame.proof, i); + if (computed.containsKey(arg)) { + node.addChild(computed.get(arg)); + } + } + computed.put(frame.proof, node); + Native.decRef(z3context, frame.proof); + } + } + return computed.get(rootProof); + } + + private Z3ProofRule getPRfromDK(int declKind) { + Z3_decl_kind dk = Z3_decl_kind.fromInt(declKind); + switch (dk) { + case Z3_OP_PR_UNDEF: + return Z3ProofRule.UNDEF; + case Z3_OP_PR_TRUE: + return Z3ProofRule.TRUE; + case Z3_OP_PR_ASSERTED: + return Z3ProofRule.ASSERTED; + case Z3_OP_PR_GOAL: + return Z3ProofRule.GOAL; + case Z3_OP_PR_MODUS_PONENS: + return Z3ProofRule.MODUS_PONENS; + case Z3_OP_PR_REFLEXIVITY: + return Z3ProofRule.REFLEXIVITY; + case Z3_OP_PR_SYMMETRY: + return Z3ProofRule.SYMMETRY; + case Z3_OP_PR_TRANSITIVITY: + return Z3ProofRule.TRANSITIVITY; + case Z3_OP_PR_TRANSITIVITY_STAR: + return Z3ProofRule.TRANSITIVITY_STAR; + case Z3_OP_PR_MONOTONICITY: + return Z3ProofRule.MONOTONICITY; + case Z3_OP_PR_QUANT_INTRO: + return Z3ProofRule.QUANT_INTRO; + case Z3_OP_PR_BIND: + return Z3ProofRule.BIND; + case Z3_OP_PR_DISTRIBUTIVITY: + return Z3ProofRule.DISTRIBUTIVITY; + case Z3_OP_PR_AND_ELIM: + return Z3ProofRule.AND_ELIM; + case Z3_OP_PR_NOT_OR_ELIM: + return Z3ProofRule.NOT_OR_ELIM; + case Z3_OP_PR_REWRITE: + return Z3ProofRule.REWRITE; + case Z3_OP_PR_REWRITE_STAR: + return Z3ProofRule.REWRITE_STAR; + case Z3_OP_PR_PULL_QUANT: + return Z3ProofRule.PULL_QUANT; + case Z3_OP_PR_PUSH_QUANT: + return Z3ProofRule.PUSH_QUANT; + case Z3_OP_PR_ELIM_UNUSED_VARS: + return Z3ProofRule.ELIM_UNUSED_VARS; + case Z3_OP_PR_DER: + return Z3ProofRule.DER; + case Z3_OP_PR_QUANT_INST: + return Z3ProofRule.QUANT_INST; + case Z3_OP_PR_HYPOTHESIS: + return Z3ProofRule.HYPOTHESIS; + case Z3_OP_PR_LEMMA: + return Z3ProofRule.LEMMA; + case Z3_OP_PR_UNIT_RESOLUTION: + return Z3ProofRule.UNIT_RESOLUTION; + case Z3_OP_PR_IFF_TRUE: + return Z3ProofRule.IFF_TRUE; + case Z3_OP_PR_IFF_FALSE: + return Z3ProofRule.IFF_FALSE; + case Z3_OP_PR_COMMUTATIVITY: + return Z3ProofRule.COMMUTATIVITY; + case Z3_OP_PR_DEF_AXIOM: + return Z3ProofRule.DEF_AXIOM; + case Z3_OP_PR_ASSUMPTION_ADD: + return Z3ProofRule.ASSUMPTION_ADD; + case Z3_OP_PR_LEMMA_ADD: + return Z3ProofRule.LEMMA_ADD; + case Z3_OP_PR_REDUNDANT_DEL: + return Z3ProofRule.REDUNDANT_DEL; + case Z3_OP_PR_CLAUSE_TRAIL: + return Z3ProofRule.CLAUSE_TRAIL; + case Z3_OP_PR_DEF_INTRO: + return Z3ProofRule.DEF_INTRO; + case Z3_OP_PR_APPLY_DEF: + return Z3ProofRule.APPLY_DEF; + case Z3_OP_PR_IFF_OEQ: + return Z3ProofRule.IFF_OEQ; + case Z3_OP_PR_NNF_POS: + return Z3ProofRule.NNF_POS; + case Z3_OP_PR_NNF_NEG: + return Z3ProofRule.NNF_NEG; + case Z3_OP_PR_SKOLEMIZE: + return Z3ProofRule.SKOLEMIZE; + case Z3_OP_PR_MODUS_PONENS_OEQ: + return Z3ProofRule.MODUS_PONENS_OEQ; + case Z3_OP_PR_TH_LEMMA: + return Z3ProofRule.TH_LEMMA; + case Z3_OP_PR_HYPER_RESOLVE: + return Z3ProofRule.HYPER_RESOLVE; + default: + return Z3ProofRule.OPERATION; + } + } + + private Formula generateFormula(long proof) { + Formula formula = null; + if (formula == null) { + formula = formulaCreator.encapsulate(formulaCreator.getFormulaType(proof), proof); + } + return formula; + } + + private static class Frame { + final long proof; + int numArgs; + boolean visited; + + Frame(long proof) { + this.proof = proof; + this.visited = false; + } + } +} + diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofParser.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofProcessor.java similarity index 99% rename from src/org/sosy_lab/java_smt/solvers/z3/Z3ProofParser.java rename to src/org/sosy_lab/java_smt/solvers/z3/Z3ProofProcessor.java index 15430080bf..470711ac06 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofParser.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofProcessor.java @@ -19,7 +19,7 @@ import org.sosy_lab.java_smt.api.Formula; @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) -public class Z3ProofParser { + class Z3ProofProcessor { private final long z3context; private final long z3solver; private final Z3FormulaCreator formulaCreator; @@ -27,7 +27,7 @@ public class Z3ProofParser { private final Map parsed = new HashMap<>(); - Z3ProofParser( + Z3ProofProcessor( long ctx, long solver, Z3FormulaCreator creator, Z3AbstractProver pProver) { z3context = ctx; diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java index 456aa84402..97532544f4 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java @@ -4,6 +4,8 @@ import com.microsoft.z3.*; +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import com.microsoft.z3.Context; @@ -25,6 +27,7 @@ import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.FloatingPointRoundingMode; +import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.SolverException; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.AbstractNumeralFormulaManager.NonLinearArithmetic; @@ -67,8 +70,58 @@ public void closeSolver() { } @Test - public void printParsedProofTest() throws SolverException, InterruptedException { - //example from the 2022 paper + public void getProofTest() throws InterruptedException { + //example from the 2022 RESOLUTE paper + BooleanFormula q1 = bmgr.makeVariable("q1"); + BooleanFormula q2 = bmgr.makeVariable("q2"); + + ProverEnvironment prover = context.newProverEnvironment0(Set.of()); + //Z3TheoremProver prover = + // (Z3TheoremProver) context.newProverEnvironment0(Set.of(ProverOptions + // .GENERATE_UNSAT_CORE)); + try { + System.out.println("proofs enabled: " + context.getGenerateProofs()); + prover.addConstraint(bmgr.or(bmgr.not(q1), q2)); + prover.addConstraint(q1); + prover.addConstraint(bmgr.not(q2)); + assertTrue(prover.isUnsat()); + + ProofNode proof = prover.getProof(); + assertThat(proof).isNotNull(); + } catch (SolverException pE) { + throw new RuntimeException(pE); + } + } + + @Test + public void printProofTest() throws InterruptedException { + //example from the 2022 RESOLUTE paper + BooleanFormula q1 = bmgr.makeVariable("q1"); + BooleanFormula q2 = bmgr.makeVariable("q2"); + + ProverEnvironment prover = context.newProverEnvironment0(Set.of()); + //Z3TheoremProver prover = + // (Z3TheoremProver) context.newProverEnvironment0(Set.of(ProverOptions + // .GENERATE_UNSAT_CORE)); + try { + System.out.println("proofs enabled: " + context.getGenerateProofs()); + prover.addConstraint(bmgr.or(bmgr.not(q1), q2)); + prover.addConstraint(q1); + prover.addConstraint(bmgr.not(q2)); + assertTrue(prover.isUnsat()); + + ProofNode proof = prover.getProof(); + assertThat(proof).isNotNull(); + + System.out.println(((Z3ProofNode) proof).Z3ProofAsString()); + } catch (SolverException pE) { + throw new RuntimeException(pE); + } + } + + @Test + public void internalPrintProcessedProofTest() throws SolverException, InterruptedException { + //example from the 2022 RESOLUTE paper BooleanFormula q1 = bmgr.makeVariable("q1"); BooleanFormula q2 = bmgr.makeVariable("q2"); @@ -84,7 +137,8 @@ public void printParsedProofTest() throws SolverException, InterruptedException assertTrue(prover.isUnsat()); long proof = prover.getZ3Proof(); - Z3ProofParser parser = new Z3ProofParser(mgr.getEnvironment(), prover.getZ3solver(), + Z3ProofProcessor + parser = new Z3ProofProcessor(mgr.getEnvironment(), prover.getZ3solver(), (Z3FormulaCreator) mgr.getFormulaCreator(), prover); Z3ProofNode root = parser.fromAST(proof); @@ -96,6 +150,75 @@ public void printParsedProofTest() throws SolverException, InterruptedException } } + @Test + public void nonRecursivePrintParsedProofTest() throws SolverException, InterruptedException { + //example from the 2022 RESOLUTE paper + BooleanFormula q1 = bmgr.makeVariable("q1"); + BooleanFormula q2 = bmgr.makeVariable("q2"); + + Z3TheoremProver prover = (Z3TheoremProver) context.newProverEnvironment0(Set.of()); + //Z3TheoremProver prover = + // (Z3TheoremProver) context.newProverEnvironment0(Set.of(ProverOptions + // .GENERATE_UNSAT_CORE)); + try { + System.out.println("proofs enabled: " + context.getGenerateProofs()); + prover.addConstraint(bmgr.or(bmgr.not(q1), q2)); + prover.addConstraint(q1); + prover.addConstraint(bmgr.not(q2)); + assertTrue(prover.isUnsat()); + + long proof = prover.getZ3Proof(); + Z3NonRecursiveProofProcessor + parser = new Z3NonRecursiveProofProcessor(mgr.getEnvironment(), prover.getZ3solver(), + (Z3FormulaCreator) mgr.getFormulaCreator(), prover); + Z3ProofNode root = parser.fromASTIterative(proof); + + System.out.println(root.Z3ProofAsString()); + + + } finally { + prover.close(); + } + } + + @Test + public void compareRecursiveAndNonRecursiveOutputsTest() + throws SolverException, InterruptedException { + //example from the 2022 RESOLUTE paper + BooleanFormula q1 = bmgr.makeVariable("q1"); + BooleanFormula q2 = bmgr.makeVariable("q2"); + + Z3TheoremProver prover = (Z3TheoremProver) context.newProverEnvironment0(Set.of()); + //Z3TheoremProver prover = + // (Z3TheoremProver) context.newProverEnvironment0(Set.of(ProverOptions + // .GENERATE_UNSAT_CORE)); + try { + System.out.println("proofs enabled: " + context.getGenerateProofs()); + prover.addConstraint(bmgr.or(bmgr.not(q1), q2)); + prover.addConstraint(q1); + prover.addConstraint(bmgr.not(q2)); + assertTrue(prover.isUnsat()); + + long proof = prover.getZ3Proof(); + + Z3ProofProcessor + parser = new Z3ProofProcessor(mgr.getEnvironment(), prover.getZ3solver(), + (Z3FormulaCreator) mgr.getFormulaCreator(), prover); + Z3ProofNode root = parser.fromAST(proof); + + Z3NonRecursiveProofProcessor + nrParser = new Z3NonRecursiveProofProcessor(mgr.getEnvironment(), prover.getZ3solver(), + (Z3FormulaCreator) mgr.getFormulaCreator(), prover); + Z3ProofNode nRroot = nrParser.fromASTIterative(proof); + + assertEquals(root.Z3ProofAsString(), nRroot.Z3ProofAsString()); + + + } finally { + prover.close(); + } + } + public static Context createContextWithRawPointer(long m_ctx) { try { Constructor constructor = Context.class.getDeclaredConstructor(long.class); @@ -141,7 +264,7 @@ public void printZ3ProofAstTest() { } @Test - public void handleTransTest() { + public void Z3handleTransTest() { BooleanFormula f1 = bmgr.makeVariable("f1"); BooleanFormula f2 = bmgr.makeVariable("f2"); BooleanFormula f3 = bmgr.makeVariable("f3"); @@ -155,11 +278,11 @@ public void handleTransTest() { System.out.println(pn.Z3ProofAsString()); - Z3ProofConverter pc = new Z3ProofConverter(mgr); + Z3ToResoluteProofConverter pc = new Z3ToResoluteProofConverter(mgr); ProofNode res = pc.handleTransitivity(pn); - pc.printProof(res, 0); + pc.printProof(res, 0); } diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java index 746e9b08fa..a9fc995dcc 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java @@ -282,7 +282,8 @@ public void close() { } } - public boolean getGenerateProofs() { + //Method exlcusively used for testing + boolean getGenerateProofs() { return GENERATE_PROOFS; } diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java index 4e350821f5..662da97d58 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java @@ -21,12 +21,11 @@ import org.sosy_lab.common.ShutdownNotifier.ShutdownRequestListener; import org.sosy_lab.common.io.PathCounterTemplate; import org.sosy_lab.java_smt.api.BooleanFormula; -import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; import org.sosy_lab.java_smt.api.UserPropagator; -import org.sosy_lab.java_smt.api.proofs.ProofDAG; +import org.sosy_lab.java_smt.api.proofs.ProofNode; class Z3TheoremProver extends Z3AbstractProver implements ProverEnvironment { @@ -149,21 +148,19 @@ protected long getZ3Model() { } @Override - public ProofDAG getProof() { - return null; + public ProofNode getProof() { + long proofAst = Native.solverGetProof(z3context, z3solver); + return new Z3ProofProcessor(z3context, z3solver, creator, this).fromAST(proofAst); } - Formula getZ3ProofAsFormula(){ - long proof = Native.solverGetProof(z3context, z3solver); - return creator.encapsulate(creator.getFormulaType(proof), proof); - } - - long getZ3Proof(){ + // This method is used to get the Z3 proof as a long for testing exclusively + long getZ3Proof() { return Native.solverGetProof(z3context, z3solver); } - long getZ3solver(){ - return z3solver; + // This method is used to get the Z3 solver object for testing exclusively + long getZ3solver() { + return z3solver; } @Override diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofConverter.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java similarity index 92% rename from src/org/sosy_lab/java_smt/solvers/z3/Z3ProofConverter.java rename to src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java index f37e8a74ab..441b56c1a0 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofConverter.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java @@ -13,6 +13,7 @@ import static org.sosy_lab.java_smt.solvers.z3.Z3ProofRule.MODUS_PONENS; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.ResolutionProofDAG; @@ -30,15 +31,18 @@ import java.util.HashMap; import java.util.Map; +/** + * Converts a Z3 proof to a RESOLUTE proof. + */ @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) -public class Z3ProofConverter { +public class Z3ToResoluteProofConverter { private final Z3FormulaManager formulaManager; private final BooleanFormulaManager bfm; - public Z3ProofConverter(Z3FormulaManager creator) { + Z3ToResoluteProofConverter(Z3FormulaManager creator) { formulaManager = creator; bfm = formulaManager.getBooleanFormulaManager(); } @@ -98,7 +102,7 @@ public static ResAxiom mapRule(Z3ProofRule z3Rule) { */ - public static ResolutionProofDAG convertToResolutionProofDAG(Z3ProofNode[] z3ProofNodes) { + static ResolutionProofDAG convertToResolutionProofDAG(Z3ProofNode[] z3ProofNodes) { ResolutionProofDAG dag = new ResolutionProofDAG(); for (Z3ProofNode z3Node : z3ProofNodes) { @@ -405,7 +409,36 @@ ProofNode handleTransitivity(Z3ProofNode node) { } ProofNode handleTransitivityStar(Z3ProofNode node) { - return null; + BooleanFormula resPivot = null; + Collection formulas = new ArrayList<>(); + List> formulaList = new ArrayList<>(); + int numChildren = node.getChildren().size(); + + for (int i = 0; i < numChildren; i++) { + Collection newCollection = new ArrayList<>(); + formulas.add(bfm.not((BooleanFormula) node.getChildren().get(i).getFormula())); + if (i == numChildren - 1) { + resPivot = (BooleanFormula) node.getChildren().get(i).getFormula(); + } + } + + assert resPivot != null; + ResolutionProofNode resNode = new ResolutionProofNode(node.getFormula(), resPivot); + + + formulas.add((BooleanFormula) node.getFormula()); + BooleanFormula transitivityFormula = bfm.or(formulas); + SourceProofNode sn = new SourceProofNode(ResAxiom.TRANSITIVITY, transitivityFormula); + + for (int i = 0; i < formulas.size()-2; i++){ + //ResolutionProofNode pn1 = new ResolutionProofNode(transitivityFormula., + //formulaList.get(i)) + } + + + + + return resNode; } ProofNode handleMonotonicity(Z3ProofNode node) { diff --git a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java index 861d441372..b79de02546 100644 --- a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java +++ b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java @@ -30,6 +30,7 @@ import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; +import org.sosy_lab.java_smt.api.proofs.ProofNode; public class ProverEnvironmentTest extends SolverBasedTest0.ParameterizedSolverBasedTest0 { @@ -83,7 +84,7 @@ public void unsatCoreTestForInterpolation() throws SolverException, InterruptedE requireUnsatCore(); requireInterpolation(); try (BasicProverEnvironment pe = - context.newProverEnvironmentWithInterpolation(GENERATE_UNSAT_CORE)) { + context.newProverEnvironmentWithInterpolation(GENERATE_UNSAT_CORE)) { unsatCoreTest0(pe); } } @@ -93,7 +94,7 @@ public void unsatCoreTestForOptimizationProver() throws SolverException, Interru requireUnsatCore(); requireOptimization(); try (BasicProverEnvironment pe = - context.newOptimizationProverEnvironment(GENERATE_UNSAT_CORE)) { + context.newOptimizationProverEnvironment(GENERATE_UNSAT_CORE)) { unsatCoreTest0(pe); } } @@ -123,7 +124,7 @@ public void unsatCoreWithAssumptionsNullTest() { .isNoneOf(PRINCESS, CVC4, CVC5, OPENSMT); try (ProverEnvironment pe = - context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { + context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { assertThrows(NullPointerException.class, () -> pe.unsatCoreOverAssumptions(null)); } } @@ -138,7 +139,7 @@ public void unsatCoreWithAssumptionsTest() throws SolverException, InterruptedEx .that(solverToUse()) .isNoneOf(PRINCESS, CVC4, CVC5, OPENSMT); try (ProverEnvironment pe = - context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { + context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { pe.push(); pe.addConstraint(imgr.equal(imgr.makeVariable("y"), imgr.makeNumber(2))); BooleanFormula selector = bmgr.makeVariable("b"); @@ -160,12 +161,13 @@ public void testSatWithUnsatUnsatCoreOptions() throws InterruptedException, Solv requireUnsatCoreOverAssumptions(); try (ProverEnvironment prover = - context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { + context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { checkSimpleQuery(prover); } try (ProverEnvironment prover = - context.newProverEnvironment(GENERATE_UNSAT_CORE, GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { + context.newProverEnvironment(GENERATE_UNSAT_CORE, + GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { checkSimpleQuery(prover); } } @@ -187,4 +189,24 @@ private void checkSimpleQuery(ProverEnvironment pProver) pProver.pop(); } } + + @Test + public void testGetProof() throws InterruptedException { + requireProofGeneration(); // Ensures proofs are supported + BooleanFormula q1 = bmgr.makeVariable("q1"); + BooleanFormula q2 = bmgr.makeVariable("q2"); + + try (ProverEnvironment prover = context.newProverEnvironment(ProverOptions.GENERATE_PROOFS)) { + prover.addConstraint(bmgr.or(bmgr.not(q1), q2)); + prover.addConstraint(q1); + prover.addConstraint(bmgr.not(q2)); + + assertThat(prover.isUnsat()).isTrue(); + + ProofNode proof = prover.getProof(); + assertThat(proof).isNotNull(); + } catch (SolverException pE) { + throw new RuntimeException(pE); + } + } } diff --git a/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java b/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java index de2715e3f2..576bee8c54 100644 --- a/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java +++ b/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java @@ -129,6 +129,9 @@ protected ConfigurationBuilder createTestConfigBuilder() { if (solverToUse() == Solvers.OPENSMT) { newConfig.setOption("solver.opensmt.logic", logicToUse().toString()); } + if (solverToUse() == Solvers.Z3) { + newConfig.setOption("solver.z3.requireProofs", "true"); + } return newConfig; } @@ -377,6 +380,13 @@ protected void requireUserPropagators() { .isEqualTo(Solvers.Z3); } + protected void requireProofGeneration(){ + assume() + .withMessage("Solver %s does not support proof generation", solverToUse()) + .that(solverToUse()) + .isNoneOf(Solvers.BOOLECTOR, Solvers.BITWUZLA, Solvers.YICES2); + } + /** * Use this for checking assertions about BooleanFormulas with Truth: * assertThatFormula(formula).is...(). From e7940f105acef1e116cb452a7a5e8f15f175e5e0 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Wed, 19 Mar 2025 12:59:21 +0100 Subject: [PATCH 013/132] Renamed some classes --- ...solutionProofDAG.java => ResolutionProofDag.java} | 12 ++---------- .../api/proofs/{ProofDAG.java => ProofDag.java} | 2 +- .../api/proofs/visitors/ProofTraversalVisitor.java | 4 ++-- .../java_smt/api/proofs/visitors/ProofVisitor.java | 4 ++-- .../solvers/smtinterpol/ProofTermParser.java | 8 ++++---- .../smtinterpol/SmtInterpolAbstractProver.java | 4 ++-- .../solvers/smtinterpol/SmtInterpolProofNode.java | 4 ++-- .../solvers/smtinterpol/SmtInterpolProofsTest.java | 6 +++--- .../solvers/z3/{Z3ProofDAG.java => Z3ProofDag.java} | 4 ++-- .../solvers/z3/Z3ToResoluteProofConverter.java | 6 +++--- 10 files changed, 23 insertions(+), 31 deletions(-) rename src/org/sosy_lab/java_smt/{ResolutionProofDAG.java => ResolutionProofDag.java} (76%) rename src/org/sosy_lab/java_smt/api/proofs/{ProofDAG.java => ProofDag.java} (95%) rename src/org/sosy_lab/java_smt/solvers/z3/{Z3ProofDAG.java => Z3ProofDag.java} (73%) diff --git a/src/org/sosy_lab/java_smt/ResolutionProofDAG.java b/src/org/sosy_lab/java_smt/ResolutionProofDag.java similarity index 76% rename from src/org/sosy_lab/java_smt/ResolutionProofDAG.java rename to src/org/sosy_lab/java_smt/ResolutionProofDag.java index 74f899de14..177e531be4 100644 --- a/src/org/sosy_lab/java_smt/ResolutionProofDAG.java +++ b/src/org/sosy_lab/java_smt/ResolutionProofDag.java @@ -10,18 +10,10 @@ package org.sosy_lab.java_smt; -import de.uni_freiburg.informatik.ultimate.logic.AnnotatedTerm; -import de.uni_freiburg.informatik.ultimate.logic.Annotation; -import de.uni_freiburg.informatik.ultimate.logic.Term; -import java.util.Map; -import org.sosy_lab.java_smt.api.BooleanFormula; -import org.sosy_lab.java_smt.api.FormulaManager; -import org.sosy_lab.java_smt.api.proofs.ProofNode; -import org.sosy_lab.java_smt.basicimpl.AbstractProofDAG; -import org.sosy_lab.java_smt.solvers.smtinterpol.ProofTermParser; +import org.sosy_lab.java_smt.basicimpl.AbstractProofDag; @SuppressWarnings("all") -public class ResolutionProofDAG extends AbstractProofDAG { +public class ResolutionProofDag extends AbstractProofDag { /* public ResolutionProofDAG() { diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java b/src/org/sosy_lab/java_smt/api/proofs/ProofDag.java similarity index 95% rename from src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java rename to src/org/sosy_lab/java_smt/api/proofs/ProofDag.java index 7ffe6015bc..9adf9e99d7 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofDag.java @@ -13,7 +13,7 @@ import java.util.Collection; import org.sosy_lab.java_smt.api.proofs.visitors.ProofVisitor; -public interface ProofDAG { +public interface ProofDag { void addNode(ProofNode node); ProofNode getNode(int nodeId); void addEdge(int parentNodeId, int childNodeId); diff --git a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java index 114b69659b..9b25332735 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java +++ b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java @@ -12,7 +12,7 @@ import java.util.HashSet; import java.util.Set; -import org.sosy_lab.java_smt.api.proofs.ProofDAG; +import org.sosy_lab.java_smt.api.proofs.ProofDag; import org.sosy_lab.java_smt.api.proofs.ProofNode; public class ProofTraversalVisitor implements ProofVisitor { @@ -28,7 +28,7 @@ public void visitNode(ProofNode node) { } @Override - public void visitDAG(ProofDAG dag) { + public void visitDAG(ProofDag dag) { for (ProofNode node : dag.getNodes()) { if (!visited.contains(node)) { visitNode(node); diff --git a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofVisitor.java b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofVisitor.java index 5067b89e47..e496b69c18 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofVisitor.java +++ b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofVisitor.java @@ -10,10 +10,10 @@ package org.sosy_lab.java_smt.api.proofs.visitors; -import org.sosy_lab.java_smt.api.proofs.ProofDAG; +import org.sosy_lab.java_smt.api.proofs.ProofDag; import org.sosy_lab.java_smt.api.proofs.ProofNode; public interface ProofVisitor { void visitNode(ProofNode node); - void visitDAG(ProofDAG dag); + void visitDAG(ProofDag dag); } diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java index a91275a9d3..a001d9a437 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java @@ -9,7 +9,7 @@ import java.util.HashMap; import java.util.Map; import org.sosy_lab.java_smt.ResProofRule.ResAxiom; -import org.sosy_lab.java_smt.ResolutionProofDAG; +import org.sosy_lab.java_smt.ResolutionProofDag; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.FormulaManager; import org.sosy_lab.java_smt.api.proofs.ProofNode; @@ -19,7 +19,7 @@ @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) public class ProofTermParser { - private final ResolutionProofDAG proofDag; + private final ResolutionProofDag proofDag; private final Map annotatedTerms; private final Map letBindings = new HashMap<>(); private final Map termToNode = new HashMap<>(); @@ -28,11 +28,11 @@ public class ProofTermParser { public ProofTermParser(Map pAnnotatedTerms, FormulaManager pMgr) { annotatedTerms = pAnnotatedTerms; mgr = pMgr; - proofDag = new ResolutionProofDAG(); + proofDag = new ResolutionProofDag(); } - public static ResolutionProofDAG convert( + public static ResolutionProofDag convert( Term proof, FormulaManager pManager, Map pAnnotatedTerms) { diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java index 43c2537c9a..97e32636e1 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java @@ -41,7 +41,7 @@ import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; -import org.sosy_lab.java_smt.api.proofs.ProofDAG; +import org.sosy_lab.java_smt.api.proofs.ProofDag; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.AbstractProver; import org.sosy_lab.java_smt.basicimpl.CachingModel; @@ -222,7 +222,7 @@ public ProofNode getProof() { checkGenerateProofs(); final Term proof; - final ProofDAG proofDAG; + final ProofDag proofDAG; try { proof = env.getProof(); //proofDAG = ResolutionProofDAG.fromTerm(proof, mgr, annotatedTerms.peek()); diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNode.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNode.java index a206490ce8..7c01ce3c7e 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNode.java @@ -23,7 +23,7 @@ import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.ResolutionNode; import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.ResolutionNode.Antecedent; -import org.sosy_lab.java_smt.ResolutionProofDAG; +import org.sosy_lab.java_smt.ResolutionProofDag; import org.sosy_lab.java_smt.ResolutionProofNode; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.ProofRule; @@ -70,7 +70,7 @@ public static ResolutionProofDAG buildDag(SmtInterpolProofNode root) { */ // Recursively adds nodes and edges from the tree to the dag. - private static void addDagEdges(SmtInterpolProofNode node, ResolutionProofDAG dag) { + private static void addDagEdges(SmtInterpolProofNode node, ResolutionProofDag dag) { if (node == null) { return; } diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java index ccbf46a352..6f445d8daa 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java @@ -30,7 +30,7 @@ import org.sosy_lab.common.configuration.InvalidConfigurationException; import org.sosy_lab.common.log.BasicLogManager; import org.sosy_lab.common.log.LogManager; -import org.sosy_lab.java_smt.ResolutionProofDAG; +import org.sosy_lab.java_smt.ResolutionProofDag; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; @@ -183,8 +183,8 @@ public void testProofTermParserIntegration() throws Exception { // Convert the retrieved proof term to a ResolutionProofDAG using the context's formula creator // and the asserted formulas. - ResolutionProofDAG dag = - (ResolutionProofDAG) prover.getProof(); + ResolutionProofDag dag = + (ResolutionProofDag) prover.getProof(); assertNotNull(dag); // Optionally, additional assertions on the dag structure can be added here. diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDAG.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDag.java similarity index 73% rename from src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDAG.java rename to src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDag.java index 52e5c44725..f635020e88 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDAG.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDag.java @@ -11,9 +11,9 @@ package org.sosy_lab.java_smt.solvers.z3; -import org.sosy_lab.java_smt.basicimpl.AbstractProofDAG; +import org.sosy_lab.java_smt.basicimpl.AbstractProofDag; -public class Z3ProofDAG extends AbstractProofDAG { +public class Z3ProofDag extends AbstractProofDag { } diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java index 441b56c1a0..ab9f63a112 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java @@ -16,7 +16,7 @@ import java.util.Collection; import java.util.List; import org.sosy_lab.java_smt.ResProofRule.ResAxiom; -import org.sosy_lab.java_smt.ResolutionProofDAG; +import org.sosy_lab.java_smt.ResolutionProofDag; import org.sosy_lab.java_smt.ResolutionProofNode; import org.sosy_lab.java_smt.SourceProofNode; import org.sosy_lab.java_smt.api.BooleanFormula; @@ -102,8 +102,8 @@ public static ResAxiom mapRule(Z3ProofRule z3Rule) { */ - static ResolutionProofDAG convertToResolutionProofDAG(Z3ProofNode[] z3ProofNodes) { - ResolutionProofDAG dag = new ResolutionProofDAG(); + static ResolutionProofDag convertToResolutionProofDAG(Z3ProofNode[] z3ProofNodes) { + ResolutionProofDag dag = new ResolutionProofDag(); for (Z3ProofNode z3Node : z3ProofNodes) { if (z3Node.getRule() == MODUS_PONENS) { From f988d6ad2f0681cfdd908af6b49c54332c292442 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Thu, 20 Mar 2025 18:22:46 +0100 Subject: [PATCH 014/132] Renaming some classes for clarity --- .../{AbstractProofDAG.java => AbstractProofDag.java} | 4 ++-- ...{CVC5ProofParser.java => CVC5ProofProcessor.java} | 2 +- .../java_smt/solvers/cvc5/CVC5ProofsTest.java | 1 + .../solvers/z3/Z3NonRecursiveProofProcessor.java | 1 - .../sosy_lab/java_smt/solvers/z3/Z3ProofNode.java | 8 ++++---- .../sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java | 12 ++++++------ .../solvers/z3/Z3ToResoluteProofConverter.java | 8 ++++---- 7 files changed, 18 insertions(+), 18 deletions(-) rename src/org/sosy_lab/java_smt/basicimpl/{AbstractProofDAG.java => AbstractProofDag.java} (91%) rename src/org/sosy_lab/java_smt/solvers/cvc5/{CVC5ProofParser.java => CVC5ProofProcessor.java} (89%) diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java similarity index 91% rename from src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java rename to src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java index 7454d1cc75..f854da0d0c 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java @@ -13,7 +13,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; -import org.sosy_lab.java_smt.api.proofs.ProofDAG; +import org.sosy_lab.java_smt.api.proofs.ProofDag; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.api.proofs.visitors.ProofVisitor; @@ -22,7 +22,7 @@ * * @author Gabriel Carpio */ -public abstract class AbstractProofDAG implements ProofDAG { +public abstract class AbstractProofDag implements ProofDag { private final Map nodes = new HashMap<>(); private int nodeIdCounter = 0; diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofParser.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java similarity index 89% rename from src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofParser.java rename to src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java index f88fb9eda1..37bf3c4435 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofParser.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java @@ -10,5 +10,5 @@ package org.sosy_lab.java_smt.solvers.cvc5; -public class CVC5ProofParser { +public class CVC5ProofProcessor { } diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java index 90e82ec3b9..662f066cdf 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java @@ -18,6 +18,7 @@ import org.junit.Ignore; import org.sosy_lab.common.NativeLibraries; +@SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) @Ignore public class CVC5ProofsTest { @BeforeClass diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java index 493c6247f2..4b459d2bba 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java @@ -31,7 +31,6 @@ class Z3NonRecursiveProofProcessor { private final long z3solver; private final Z3FormulaCreator formulaCreator; private final Z3AbstractProver prover; - private final Map parsed = new HashMap<>(); Z3NonRecursiveProofProcessor( long ctx, long solver, Z3FormulaCreator creator, diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofNode.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofNode.java index f34d762ec7..3dcd6de3fd 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofNode.java @@ -11,11 +11,11 @@ class Z3ProofNode extends AbstractProofNode { super(pProofRule, pFormula); } - String Z3ProofAsString() { - return Z3ProofAsString(0); + String asString() { + return asString(0); } - private String Z3ProofAsString(int indentLevel) { + private String asString(int indentLevel) { StringBuilder proof = new StringBuilder(); String indent = " ".repeat(indentLevel); @@ -26,7 +26,7 @@ private String Z3ProofAsString(int indentLevel) { int i = 0; for (ProofNode child : getChildren()) { proof.append(indent).append("Child ").append(++i).append(":\n"); - proof.append(((Z3ProofNode) child).Z3ProofAsString(indentLevel + 1)); + proof.append(((Z3ProofNode) child).asString(indentLevel + 1)); } return proof.toString(); diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java index 97532544f4..2d13a11a7f 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java @@ -113,7 +113,7 @@ public void printProofTest() throws InterruptedException { ProofNode proof = prover.getProof(); assertThat(proof).isNotNull(); - System.out.println(((Z3ProofNode) proof).Z3ProofAsString()); + System.out.println(((Z3ProofNode) proof).asString()); } catch (SolverException pE) { throw new RuntimeException(pE); } @@ -142,7 +142,7 @@ public void internalPrintProcessedProofTest() throws SolverException, Interrupte (Z3FormulaCreator) mgr.getFormulaCreator(), prover); Z3ProofNode root = parser.fromAST(proof); - System.out.println(root.Z3ProofAsString()); + System.out.println(root.asString()); } finally { @@ -173,7 +173,7 @@ public void nonRecursivePrintParsedProofTest() throws SolverException, Interrupt (Z3FormulaCreator) mgr.getFormulaCreator(), prover); Z3ProofNode root = parser.fromASTIterative(proof); - System.out.println(root.Z3ProofAsString()); + System.out.println(root.asString()); } finally { @@ -211,7 +211,7 @@ public void compareRecursiveAndNonRecursiveOutputsTest() (Z3FormulaCreator) mgr.getFormulaCreator(), prover); Z3ProofNode nRroot = nrParser.fromASTIterative(proof); - assertEquals(root.Z3ProofAsString(), nRroot.Z3ProofAsString()); + assertEquals(root.asString(), nRroot.asString()); } finally { @@ -264,7 +264,7 @@ public void printZ3ProofAstTest() { } @Test - public void Z3handleTransTest() { + public void Z3handleTransitivityTest() { BooleanFormula f1 = bmgr.makeVariable("f1"); BooleanFormula f2 = bmgr.makeVariable("f2"); BooleanFormula f3 = bmgr.makeVariable("f3"); @@ -276,7 +276,7 @@ public void Z3handleTransTest() { pn.addChild(new Z3ProofNode(equiv1, Z3ProofRule.ASSERTED)); pn.addChild(new Z3ProofNode(equiv2, Z3ProofRule.ASSERTED)); - System.out.println(pn.Z3ProofAsString()); + System.out.println(pn.asString()); Z3ToResoluteProofConverter pc = new Z3ToResoluteProofConverter(mgr); diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java index ab9f63a112..a030633826 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java @@ -35,7 +35,7 @@ * Converts a Z3 proof to a RESOLUTE proof. */ -@SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) +@SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access","ModifiedButNotUsed"}) public class Z3ToResoluteProofConverter { private final Z3FormulaManager formulaManager; @@ -102,7 +102,7 @@ public static ResAxiom mapRule(Z3ProofRule z3Rule) { */ - static ResolutionProofDag convertToResolutionProofDAG(Z3ProofNode[] z3ProofNodes) { + static ResolutionProofDag convertToResolutionProofDag(Z3ProofNode[] z3ProofNodes) { ResolutionProofDag dag = new ResolutionProofDag(); for (Z3ProofNode z3Node : z3ProofNodes) { @@ -593,7 +593,7 @@ void printProof(ProofNode node, int indentLevel) { System.out.println(indent + "No. Children: " + sourceNode.getChildren().size()); int i = 0; for (ProofNode child : sourceNode.getChildren()) { - System.out.println(indent + "Child " + (++i) + ":"); + System.out.println(indent + "Child " + ++i + ":"); printProof(child, indentLevel + 1); } } else if (node instanceof ResolutionProofNode) { @@ -604,7 +604,7 @@ void printProof(ProofNode node, int indentLevel) { System.out.println(indent + "No. Children: " + resolutionNode.getChildren().size()); int i = 0; for (ProofNode child : resolutionNode.getChildren()) { - System.out.println(indent + "Child " + (++i) + ":"); + System.out.println(indent + "Child " + ++i + ":"); printProof(child, indentLevel + 1); } } else { From fcdf44f270d73c583870e13211309d47518528bb Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Thu, 20 Mar 2025 18:23:42 +0100 Subject: [PATCH 015/132] Method `getFormula()` in the `ProofRule` interface has default implementation for when no formula is available. --- src/org/sosy_lab/java_smt/api/proofs/ProofRule.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofRule.java b/src/org/sosy_lab/java_smt/api/proofs/ProofRule.java index e853de39fe..1b17b494ac 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofRule.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofRule.java @@ -23,5 +23,7 @@ public interface ProofRule { /** * Get the formula of the proof rule. */ - String getFormula(); + default String getFormula() { + return "no formula available"; + } } From 1d9ab98a5124b0b63bd1476d76fe14ea49a40349 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Thu, 20 Mar 2025 18:24:20 +0100 Subject: [PATCH 016/132] Added Mathsat5ProofRule class --- .../solvers/mathsat5/Mathsat5ProofRule.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java new file mode 100644 index 0000000000..9efa4c7e93 --- /dev/null +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java @@ -0,0 +1,27 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.solvers.mathsat5; + +import org.sosy_lab.java_smt.api.proofs.ProofRule; + +public class Mathsat5ProofRule implements ProofRule { + + private String name; + + Mathsat5ProofRule(String pName) { + name = pName; + } + + @Override + public String getName() { + return name; + } +} From 2fec458741e774d44d9e953eb0d0f1f2c1ff9397 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Thu, 20 Mar 2025 18:24:52 +0100 Subject: [PATCH 017/132] Added Mathsat5ProofProcessor class for processing the proofs straight from Mathsat5 --- .../mathsat5/Mathsat5ProofProcessor.java | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofProcessor.java diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofProcessor.java new file mode 100644 index 0000000000..e7720c1ec0 --- /dev/null +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofProcessor.java @@ -0,0 +1,101 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.solvers.mathsat5; + +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_get_arity; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_get_child; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_get_name; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_is_term; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.Nullable; +import org.sosy_lab.java_smt.api.Formula; + +public class Mathsat5ProofProcessor { + private final Mathsat5SolverContext context; + private final long curEnv; + private final Mathsat5FormulaCreator formulaCreator; + private final Mathsat5TheoremProver theoremProver; + + Mathsat5ProofProcessor( + Mathsat5SolverContext ctx, long pCurEnv, Mathsat5FormulaCreator creator, + Mathsat5TheoremProver prover) { + context = ctx; + curEnv = pCurEnv; + formulaCreator = creator; + theoremProver = prover; + } + + public Mathsat5ProofNode fromMsatProof(long rootProof) { + Deque stack = new ArrayDeque<>(); + Map computed = new HashMap<>(); + + stack.push(new Frame(rootProof)); + + while (!stack.isEmpty()) { + Frame frame = stack.peek(); + + if (!frame.visited) { + frame.numArgs = msat_proof_get_arity(frame.proof); + frame.visited = true; + // Push children first so that the leaves are processed first. + for (int i = 0; i < frame.numArgs; i++) { + long child = msat_proof_get_child(frame.proof, i); + if (!computed.containsKey(child)) { + stack.push(new Frame(child)); + } + } + } else { + // Process the node after all its children have been processed. + stack.pop(); + + // Generate the formula and proof rule. + Formula formula = generateFormula(frame.proof); + Mathsat5ProofRule proofRule = new Mathsat5ProofRule(msat_proof_get_name(frame.proof)); + Mathsat5ProofNode node = new Mathsat5ProofNode(proofRule, formula); + + // Retrieve computed child nodes and attach them. + for (int i = 0; i < frame.numArgs; i++) { + long child = msat_proof_get_child(frame.proof, i); + Mathsat5ProofNode childNode = computed.get(child); + if (childNode != null) { + node.addChild(childNode); + } + } + computed.put(frame.proof, node); + } + } + return computed.get(rootProof); + } + + @Nullable + private Formula generateFormula(long proof) { + Formula formula = null; + if (msat_proof_is_term(proof)) { + formula = formulaCreator.encapsulate(formulaCreator.getFormulaType(proof), proof); + } + return formula; + } + + private static class Frame { + final long proof; + int numArgs; + boolean visited; + + Frame(long proof) { + this.proof = proof; + this.visited = false; + } + } +} From 7c207616069c3e2f989193099566392cfd98669b Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Thu, 20 Mar 2025 18:25:08 +0100 Subject: [PATCH 018/132] Added Mathsat5ProofNode class for storing the proofs in JavaSMT --- .../solvers/mathsat5/Mathsat5ProofNode.java | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java new file mode 100644 index 0000000000..d17d95519f --- /dev/null +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java @@ -0,0 +1,45 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.solvers.mathsat5; + +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.ProofRule; +import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; + +public class Mathsat5ProofNode extends AbstractProofNode { + + protected Mathsat5ProofNode( + ProofRule rule, + Formula formula) { + super(rule, formula); + } + + public String asString() { + return asString(0); + } + + private String asString(int indentLevel) { + StringBuilder proof = new StringBuilder(); + String indent = " ".repeat(indentLevel); + + proof.append(indent).append("Formula: ").append(getFormula().toString()).append("\n"); + proof.append(indent).append("Rule: ").append(getRule().getName()).append("\n"); + proof.append(indent).append("No. Children: ").append(getChildren().size()).append("\n"); + + int i = 0; + for (ProofNode child : getChildren()) { + proof.append(indent).append("Child ").append(++i).append(":\n"); + proof.append(((Mathsat5ProofNode) child).asString(indentLevel + 1)); + } + return proof.toString(); + } +} From 3d8981015e45035182d19c6350227cb1e4633ef5 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Thu, 20 Mar 2025 20:46:39 +0100 Subject: [PATCH 019/132] Mathsat5: proofs are enabled by setting `ProverOptions.GENERATE_PROOFS` --- .../java_smt/solvers/mathsat5/Mathsat5AbstractProver.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5AbstractProver.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5AbstractProver.java index 39ace99503..1ee58bc5fa 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5AbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5AbstractProver.java @@ -15,7 +15,10 @@ import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_create_config; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_destroy_config; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_destroy_env; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_destroy_proof_manager; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_free_termination_callback; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_proof; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_proof_manager; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_search_stats; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_unsat_assumptions; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_unsat_core; @@ -48,6 +51,7 @@ import org.sosy_lab.java_smt.api.Model; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; +import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.AbstractProver; import org.sosy_lab.java_smt.basicimpl.CachingModel; import org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.AllSatModelCallback; @@ -81,6 +85,7 @@ private long buildConfig(Set opts) { || opts.contains(ProverOptions.GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS); config.put("model_generation", opts.contains(ProverOptions.GENERATE_MODELS) ? "true" : "false"); config.put("unsat_core_generation", generateUnsatCore ? "1" : "0"); + config.put("proof_generation", opts.contains(ProverOptions.GENERATE_PROOFS) ? "true" : "false"); if (generateUnsatCore) { config.put("theory.bv.eager", "false"); } From d88ecb2ca203a91e108d310c7138a707b6a88ecd Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Thu, 20 Mar 2025 20:48:02 +0100 Subject: [PATCH 020/132] Mathsat5: method `getProof()` now can be called to get a `ProofNode` object. --- .../solvers/mathsat5/Mathsat5ProofNode.java | 5 +++-- .../solvers/mathsat5/Mathsat5ProofProcessor.java | 7 +++++-- .../solvers/mathsat5/Mathsat5TheoremProver.java | 14 ++++++++++++++ 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java index d17d95519f..037d9b0203 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java @@ -30,8 +30,9 @@ public String asString() { private String asString(int indentLevel) { StringBuilder proof = new StringBuilder(); String indent = " ".repeat(indentLevel); - - proof.append(indent).append("Formula: ").append(getFormula().toString()).append("\n"); + if (getFormula() != null) { + proof.append(indent).append("Formula: ").append(getFormula().toString()).append("\n"); + } proof.append(indent).append("Rule: ").append(getRule().getName()).append("\n"); proof.append(indent).append("No. Children: ").append(getChildren().size()).append("\n"); diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofProcessor.java index e7720c1ec0..617a6f4b45 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofProcessor.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofProcessor.java @@ -13,6 +13,7 @@ import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_get_arity; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_get_child; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_get_name; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_get_term; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_is_term; import java.util.ArrayDeque; @@ -57,7 +58,8 @@ public Mathsat5ProofNode fromMsatProof(long rootProof) { } } } else { - // Process the node after all its children have been processed. + // Process the node after all its children have been processed. This should help to + // recreate the formula for the node correctly. stack.pop(); // Generate the formula and proof rule. @@ -83,7 +85,8 @@ public Mathsat5ProofNode fromMsatProof(long rootProof) { private Formula generateFormula(long proof) { Formula formula = null; if (msat_proof_is_term(proof)) { - formula = formulaCreator.encapsulate(formulaCreator.getFormulaType(proof), proof); + long proofTerm = msat_proof_get_term(proof); + formula = formulaCreator.encapsulate(formulaCreator.getFormulaType(proofTerm), proofTerm); } return formula; } diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java index 4801c5904f..21d692561e 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java @@ -10,6 +10,9 @@ import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5FormulaManager.getMsatTerm; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_assert_formula; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_destroy_proof_manager; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_proof; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_proof_manager; import com.google.common.base.Preconditions; import java.util.Map; @@ -19,6 +22,7 @@ import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; +import org.sosy_lab.java_smt.api.proofs.ProofNode; class Mathsat5TheoremProver extends Mathsat5AbstractProver implements ProverEnvironment { @@ -43,4 +47,14 @@ protected Void addConstraintImpl(BooleanFormula constraint) throws InterruptedEx msat_assert_formula(curEnv, getMsatTerm(constraint)); return null; } + + @Override + public ProofNode getProof() { + ProofNode pn; + long pm = msat_get_proof_manager(curEnv); + Mathsat5ProofProcessor pp = new Mathsat5ProofProcessor(context, curEnv, creator, this); + pn = pp.fromMsatProof(msat_get_proof(pm)); + msat_destroy_proof_manager(pm); + return pn; + } } From e87f469ba9f28afd735c4bbe99c7a3cf112413f3 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 21 Mar 2025 19:43:31 +0100 Subject: [PATCH 021/132] Checkstyle --- src/org/sosy_lab/java_smt/ResProofRule.java | 10 +- .../java_smt/ResolutionProofNode.java | 7 +- .../sosy_lab/java_smt/SourceProofNode.java | 7 +- .../sosy_lab/java_smt/api/SolverContext.java | 4 +- .../java_smt/api/proofs/ProofDag.java | 4 + .../java_smt/api/proofs/ProofFactory.java | 2 +- .../java_smt/api/proofs/ProofNode.java | 5 +- .../visitors/ProofTraversalVisitor.java | 2 +- .../api/proofs/visitors/ProofVisitor.java | 1 + .../java_smt/basicimpl/AbstractProofDag.java | 2 +- .../java_smt/basicimpl/AbstractProofNode.java | 3 +- .../java_smt/solvers/cvc5/CVC5ProofNode.java | 4 +- .../mathsat5/Mathsat5AbstractProver.java | 4 - .../solvers/mathsat5/Mathsat5ProofNode.java | 4 +- .../mathsat5/Mathsat5ProofProcessor.java | 4 +- .../solvers/smtinterpol/ProofTermParser.java | 13 +- .../SmtInterpolAbstractProver.java | 6 +- .../smtinterpol/SmtInterpolProofNode.java | 7 +- .../smtinterpol/SmtInterpolProofsTest.java | 102 +++++----- .../smtinterpol/SmtInterpolSolverContext.java | 2 - .../z3/Z3NonRecursiveProofProcessor.java | 10 +- .../java_smt/solvers/z3/Z3ProofDag.java | 6 +- .../java_smt/solvers/z3/Z3ProofNode.java | 3 +- .../java_smt/solvers/z3/Z3ProofProcessor.java | 20 +- .../java_smt/solvers/z3/Z3ProofsTest.java | 91 +++++---- .../java_smt/solvers/z3/Z3SolverContext.java | 8 +- .../z3/Z3ToResoluteProofConverter.java | 178 ++++++++---------- .../java_smt/test/ProverEnvironmentTest.java | 13 +- .../java_smt/test/SolverBasedTest0.java | 10 +- 29 files changed, 236 insertions(+), 296 deletions(-) diff --git a/src/org/sosy_lab/java_smt/ResProofRule.java b/src/org/sosy_lab/java_smt/ResProofRule.java index 698f7591f3..a2603b22e4 100644 --- a/src/org/sosy_lab/java_smt/ResProofRule.java +++ b/src/org/sosy_lab/java_smt/ResProofRule.java @@ -19,11 +19,9 @@ */ public class ResProofRule { - /** - * Any operation that proves a term. - */ + /** Any operation that proves a term. */ public enum ResAxiom implements ProofRule { - //Resolution Rule + // Resolution Rule RESOLUTION("res", "(res t proof1 proof2)"), ASSUME("assume", "(assume t)"), @@ -102,7 +100,8 @@ public enum ResAxiom implements ProofRule { DT_TEST_CONS_PRIME("dt_test_cons_prime", "(~ ((_ is cons') (cons a1 ... an)))"), DT_EXHAUST("dt_exhaust", "((_ is cons1) x), ..., ((_ is consn) x)"), DT_ACYCLIC("dt_acyclic", "(~ (= (cons ... x ...) x))"), - DT_MATCH("dt_match", + DT_MATCH( + "dt_match", "(= (match t ((p1 x1) c1) ...) (ite ((_ is p1) t) (let (x1 (sel1 t)) c1) ...))"); private final String name; @@ -145,5 +144,4 @@ public static ResAxiom getResAxiomRuleByName(String name) { throw new IllegalArgumentException("Rule not found or not specified: " + name); } - } diff --git a/src/org/sosy_lab/java_smt/ResolutionProofNode.java b/src/org/sosy_lab/java_smt/ResolutionProofNode.java index d6c66aa826..8b5111d107 100644 --- a/src/org/sosy_lab/java_smt/ResolutionProofNode.java +++ b/src/org/sosy_lab/java_smt/ResolutionProofNode.java @@ -11,14 +11,13 @@ package org.sosy_lab.java_smt; import java.util.Objects; +import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; -import org.sosy_lab.java_smt.ResProofRule.ResAxiom; -public class ResolutionProofNode extends AbstractProofNode - implements ProofNode { +public class ResolutionProofNode extends AbstractProofNode implements ProofNode { private final Formula pivot; @@ -27,8 +26,6 @@ public ResolutionProofNode(Formula formula, Formula pivot) { this.pivot = Objects.requireNonNull(pivot, "Pivot must not be null"); } - - @Override public boolean isSource() { return false; diff --git a/src/org/sosy_lab/java_smt/SourceProofNode.java b/src/org/sosy_lab/java_smt/SourceProofNode.java index d1b3420cc9..06c6aa029d 100644 --- a/src/org/sosy_lab/java_smt/SourceProofNode.java +++ b/src/org/sosy_lab/java_smt/SourceProofNode.java @@ -11,14 +11,12 @@ package org.sosy_lab.java_smt; import java.util.Objects; +import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; -import org.sosy_lab.java_smt.ResProofRule.ResAxiom; - -public class SourceProofNode extends AbstractProofNode - implements ProofNode { +public class SourceProofNode extends AbstractProofNode implements ProofNode { public SourceProofNode(ResAxiom rule, Formula formula) { super( @@ -26,7 +24,6 @@ public SourceProofNode(ResAxiom rule, Formula formula) { Objects.requireNonNull(formula, "Formula must not be null")); } - @Override public boolean isSource() { return true; diff --git a/src/org/sosy_lab/java_smt/api/SolverContext.java b/src/org/sosy_lab/java_smt/api/SolverContext.java index a963269fc0..574dd6b2be 100644 --- a/src/org/sosy_lab/java_smt/api/SolverContext.java +++ b/src/org/sosy_lab/java_smt/api/SolverContext.java @@ -52,9 +52,7 @@ enum ProverOptions { */ GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS, - /** - * Whether the solver should generate proofs for unsatisfiable formulas. - */ + /** Whether the solver should generate proofs for unsatisfiable formulas. */ GENERATE_PROOFS, /** Whether the solver should enable support for formulae build in SL theory. */ diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofDag.java b/src/org/sosy_lab/java_smt/api/proofs/ProofDag.java index 9adf9e99d7..3dc326d891 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofDag.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofDag.java @@ -15,8 +15,12 @@ public interface ProofDag { void addNode(ProofNode node); + ProofNode getNode(int nodeId); + void addEdge(int parentNodeId, int childNodeId); + Collection getNodes(); + void accept(ProofVisitor visitor); // To allow traversal of the entire DAG } diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java index 659960da3d..09188ef70a 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java @@ -10,10 +10,10 @@ package org.sosy_lab.java_smt.api.proofs; +import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.ResolutionProofNode; import org.sosy_lab.java_smt.SourceProofNode; import org.sosy_lab.java_smt.api.Formula; -import org.sosy_lab.java_smt.ResProofRule.ResAxiom; public class ProofFactory { public static ProofNode createSourceNode(ResAxiom rule, Formula formula) { diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java b/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java index 4de58c5836..218e672f29 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java @@ -10,7 +10,6 @@ package org.sosy_lab.java_smt.api.proofs; - import java.util.List; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.visitors.ProofVisitor; @@ -22,9 +21,7 @@ */ public interface ProofNode { - /** - * Get the children of the proof node. - */ + /** Get the children of the proof node. */ List getChildren(); void addChild(ProofNode child); diff --git a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java index 9b25332735..dc9f2f54ed 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java +++ b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java @@ -35,4 +35,4 @@ public void visitDAG(ProofDag dag) { } } } -} \ No newline at end of file +} diff --git a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofVisitor.java b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofVisitor.java index e496b69c18..562412bfd9 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofVisitor.java +++ b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofVisitor.java @@ -15,5 +15,6 @@ public interface ProofVisitor { void visitNode(ProofNode node); + void visitDAG(ProofDag dag); } diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java index f854da0d0c..657628dab7 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java @@ -54,4 +54,4 @@ public Collection getNodes() { public void accept(ProofVisitor visitor) { visitor.visitDAG(this); } -} \ No newline at end of file +} diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java index 8935e8b807..ea1b2f8feb 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java @@ -18,7 +18,6 @@ import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.api.proofs.visitors.ProofVisitor; - public abstract class AbstractProofNode implements ProofNode { private final List children; private ProofRule rule; @@ -79,4 +78,4 @@ public void setRule(ProofRule rule) { public void setFormula(Formula pFormula) { formula = pFormula; } -} \ No newline at end of file +} diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java index 8fcf4e0646..6d3ad5945b 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java @@ -10,10 +10,9 @@ package org.sosy_lab.java_smt.solvers.cvc5; +import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; -import org.sosy_lab.java_smt.api.Formula; - public class CVC5ProofNode extends AbstractProofNode { @@ -21,5 +20,4 @@ public CVC5ProofNode(ProofRule pProofRule, Formula formula) { super(pProofRule, formula); } - } diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5AbstractProver.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5AbstractProver.java index 1ee58bc5fa..9fa0469b84 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5AbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5AbstractProver.java @@ -15,10 +15,7 @@ import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_create_config; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_destroy_config; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_destroy_env; -import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_destroy_proof_manager; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_free_termination_callback; -import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_proof; -import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_proof_manager; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_search_stats; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_unsat_assumptions; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_unsat_core; @@ -51,7 +48,6 @@ import org.sosy_lab.java_smt.api.Model; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; -import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.AbstractProver; import org.sosy_lab.java_smt.basicimpl.CachingModel; import org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.AllSatModelCallback; diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java index 037d9b0203..866789c571 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java @@ -17,9 +17,7 @@ public class Mathsat5ProofNode extends AbstractProofNode { - protected Mathsat5ProofNode( - ProofRule rule, - Formula formula) { + protected Mathsat5ProofNode(ProofRule rule, Formula formula) { super(rule, formula); } diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofProcessor.java index 617a6f4b45..a11e97f96c 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofProcessor.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofProcessor.java @@ -30,7 +30,9 @@ public class Mathsat5ProofProcessor { private final Mathsat5TheoremProver theoremProver; Mathsat5ProofProcessor( - Mathsat5SolverContext ctx, long pCurEnv, Mathsat5FormulaCreator creator, + Mathsat5SolverContext ctx, + long pCurEnv, + Mathsat5FormulaCreator creator, Mathsat5TheoremProver prover) { context = ctx; curEnv = pCurEnv; diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java index a001d9a437..56088c74c6 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java @@ -14,7 +14,7 @@ import org.sosy_lab.java_smt.api.FormulaManager; import org.sosy_lab.java_smt.api.proofs.ProofNode; -//TODO: Correct parsing of the proof terms is missing, i.e. creation of nodes in the DAG and +// TODO: Correct parsing of the proof terms is missing, i.e. creation of nodes in the DAG and // parsing annotations. Add relevant javadocs @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) public class ProofTermParser { @@ -31,11 +31,8 @@ public ProofTermParser(Map pAnnotatedTerms, FormulaManag proofDag = new ResolutionProofDag(); } - public static ResolutionProofDag convert( - Term proof, - FormulaManager pManager, - Map pAnnotatedTerms) { + Term proof, FormulaManager pManager, Map pAnnotatedTerms) { ProofTermParser parser = new ProofTermParser(pAnnotatedTerms, pManager); ProofNode rootNode = parser.parseProofTerm(proof); if (rootNode != null) { @@ -44,7 +41,6 @@ public static ResolutionProofDag convert( return parser.proofDag; } - public ProofNode parseProofTerm(Term term) { if (termToNode.containsKey(term)) { return termToNode.get(term); @@ -69,7 +65,8 @@ public ProofNode parseProofTerm(Term term) { private ProofNode parseAnnotatedTerm(AnnotatedTerm term) { for (Annotation annotation : term.getAnnotations()) { - if (annotation.getKey().equals(":proves") || annotation.getKey().equals(":rup") + if (annotation.getKey().equals(":proves") + || annotation.getKey().equals(":rup") || annotation.getKey().equals(":input")) { Term formulaTerm = extractFormulaFromAnnotation(annotation); BooleanFormula formula = getBooleanFormulaFromTerm(formulaTerm); @@ -195,4 +192,4 @@ private ResAxiom mapTheoryLemmaToAxiom(String lemmaType) { return ResAxiom.RESOLUTION; } } -} \ No newline at end of file +} diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java index 97e32636e1..bafc1aab8e 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java @@ -225,7 +225,7 @@ public ProofNode getProof() { final ProofDag proofDAG; try { proof = env.getProof(); - //proofDAG = ResolutionProofDAG.fromTerm(proof, mgr, annotatedTerms.peek()); + // proofDAG = ResolutionProofDAG.fromTerm(proof, mgr, annotatedTerms.peek()); } catch (SMTLIBException e) { if (e.getMessage().contains("Context is inconsistent")) { throw new IllegalStateException("Cannot get proof from satisfiable environment", e); @@ -234,11 +234,11 @@ public ProofNode getProof() { } } - //ResolutionProofDAG proofDag = fromSmtInterpol(proof, creator, getAssertedFormulas()); + // ResolutionProofDAG proofDag = fromSmtInterpol(proof, creator, getAssertedFormulas()); return null; } - //TODO: Delete this method + // TODO: Delete this method protected Term smtInterpolGetProof() { return env.getProof(); } diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNode.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNode.java index 7c01ce3c7e..a7560bb632 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNode.java @@ -20,7 +20,6 @@ import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.LeafNode; import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.ProofNode; import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.ProofRules; - import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.ResolutionNode; import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.ResolutionNode.Antecedent; import org.sosy_lab.java_smt.ResolutionProofDag; @@ -92,8 +91,9 @@ public void processResNode(SmtInterpolProofNode node) { ResolutionNode rn = (ResolutionNode) SmtInterpolProofNode.node; Antecedent[] antecedents = rn.getAntecedents(); Literal pivot = antecedents[0].mPivot; - node.transformed = new ResolutionProofNode(node.getFormula(), - creator.encapsulateBoolean(pivot.getSMTFormula(theory))); + node.transformed = + new ResolutionProofNode( + node.getFormula(), creator.encapsulateBoolean(pivot.getSMTFormula(theory))); } } @@ -113,7 +113,6 @@ public void processSourceNode(SmtInterpolProofNode node) { private SmtInterpolProofNode right; private org.sosy_lab.java_smt.api.proofs.ProofNode transformed; - protected SmtInterpolProofNode(ProofRule rule, Formula formula) { super(rule, formula); } diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java index 6f445d8daa..bfe26ad3a8 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java @@ -52,13 +52,14 @@ public void setupSolver() throws InvalidConfigurationException { ShutdownManager shutdown = ShutdownManager.create(); // Create new context with SMTInterpol - context = SmtInterpolSolverContext.create( - config, - logger, - shutdown.getNotifier(), - null, // no logfile - 42, // randomSeed - NonLinearArithmetic.USE); + context = + SmtInterpolSolverContext.create( + config, + logger, + shutdown.getNotifier(), + null, // no logfile + 42, // randomSeed + NonLinearArithmetic.USE); // Get managers for creating formulas mgr = (SmtInterpolFormulaManager) context.getFormulaManager(); @@ -75,28 +76,27 @@ public void closeSolver() { @Test public void testGetProofTerm() throws SolverException, InterruptedException { - //example from the 2022 paper + // example from the 2022 paper BooleanFormula q1 = bmgr.makeVariable("q1"); BooleanFormula q2 = bmgr.makeVariable("q2"); BooleanFormula notQ1OrQ2 = bmgr.or(bmgr.not(q1), q2); BooleanFormula q1True = bmgr.equivalence(q1, bmgr.makeTrue()); BooleanFormula q2False = bmgr.equivalence(q2, bmgr.makeFalse()); - SmtInterpolTheoremProver prover = (SmtInterpolTheoremProver) context.newProverEnvironment0( - Set.of(ProverOptions.GENERATE_PROOFS)); + SmtInterpolTheoremProver prover = + (SmtInterpolTheoremProver) + context.newProverEnvironment0(Set.of(ProverOptions.GENERATE_PROOFS)); try { prover.addConstraint(notQ1OrQ2); prover.addConstraint(q1True); prover.addConstraint(q2False); assertThat(prover.isUnsat()).isTrue(); - Term proof = prover.smtInterpolGetProof(); assertThat(proof).isNotNull(); - - //String proofStr = proof.toString(); - //System.out.println(proofStr); + // String proofStr = proof.toString(); + // System.out.println(proofStr); System.out.println(proof); } finally { prover.close(); @@ -105,26 +105,25 @@ public void testGetProofTerm() throws SolverException, InterruptedException { @Test public void testGetProofClause() throws Exception { - //example from the 2022 paper - String constraint1 = "(set-logic QF_UF)\n" + - "(declare-fun q1 () Bool)\n" + - "(declare-fun q2 () Bool)\n" + - "(assert (or (not q1) q2))"; + // example from the 2022 paper + String constraint1 = + "(set-logic QF_UF)\n" + + "(declare-fun q1 () Bool)\n" + + "(declare-fun q2 () Bool)\n" + + "(assert (or (not q1) q2))"; String constraint2 = "(assert q1)"; String constraint3 = "(assert (not q2))"; + BooleanFormula formula1 = context.getFormulaManager().parse(constraint1); - BooleanFormula formula1 = - context.getFormulaManager().parse(constraint1); - - BooleanFormula formula2 = - context.getFormulaManager().parse(constraint2); + BooleanFormula formula2 = context.getFormulaManager().parse(constraint2); - BooleanFormula formula3 = - context.getFormulaManager().parse(constraint3); + BooleanFormula formula3 = context.getFormulaManager().parse(constraint3); - SmtInterpolTheoremProver prover = (SmtInterpolTheoremProver) context.newProverEnvironment0( - Set.of(ProverOptions.GENERATE_PROOFS, ProverOptions.GENERATE_MODELS)); + SmtInterpolTheoremProver prover = + (SmtInterpolTheoremProver) + context.newProverEnvironment0( + Set.of(ProverOptions.GENERATE_PROOFS, ProverOptions.GENERATE_MODELS)); SMTInterpol smtinterpol = (SMTInterpol) prover.env; try { @@ -139,8 +138,7 @@ public void testGetProofClause() throws Exception { assertThat(proof).isNotNull(); - - //String proofStr = proof.toString(); + // String proofStr = proof.toString(); System.out.println(invokeGetProofMode(smtinterpol).toString()); System.out.println(proof.toTerm(smtinterpol.getTheory())); System.out.println(proof); @@ -154,10 +152,11 @@ public void testGetProofClause() throws Exception { @Test public void testProofTermParserIntegration() throws Exception { // Arrange: parse constraints as in the SmtInterpolProofsTest. - String constraint1 = "(set-logic QF_UF)\n" - + "(declare-fun q1 () Bool)\n" - + "(declare-fun q2 () Bool)\n" - + "(assert (or (not q1) q2))"; + String constraint1 = + "(set-logic QF_UF)\n" + + "(declare-fun q1 () Bool)\n" + + "(declare-fun q2 () Bool)\n" + + "(assert (or (not q1) q2))"; String constraint2 = "(assert q1)"; String constraint3 = "(assert (not q2))"; @@ -167,8 +166,9 @@ public void testProofTermParserIntegration() throws Exception { // Create a prover with proof and model generation enabled. SmtInterpolTheoremProver prover = - (SmtInterpolTheoremProver) context.newProverEnvironment0( - ImmutableSet.of(ProverOptions.GENERATE_PROOFS, ProverOptions.GENERATE_MODELS)); + (SmtInterpolTheoremProver) + context.newProverEnvironment0( + ImmutableSet.of(ProverOptions.GENERATE_PROOFS, ProverOptions.GENERATE_MODELS)); SMTInterpol smtInterpol = (SMTInterpol) prover.env; try { // Act: add constraints and check unsat. @@ -181,10 +181,10 @@ public void testProofTermParserIntegration() throws Exception { Term proofTerm = smtInterpol.getProof(); assertNotNull(proofTerm); - // Convert the retrieved proof term to a ResolutionProofDAG using the context's formula creator + // Convert the retrieved proof term to a ResolutionProofDAG using the context's formula + // creator // and the asserted formulas. - ResolutionProofDag dag = - (ResolutionProofDag) prover.getProof(); + ResolutionProofDag dag = (ResolutionProofDag) prover.getProof(); assertNotNull(dag); // Optionally, additional assertions on the dag structure can be added here. @@ -196,10 +196,11 @@ public void testProofTermParserIntegration() throws Exception { @Test public void testSmtInterpolProof() throws Exception { // Arrange: parse constraints as in the SmtInterpolProofsTest. - String constraint1 = "(set-logic QF_UF)\n" - + "(declare-fun q1 () Bool)\n" - + "(declare-fun q2 () Bool)\n" - + "(assert (or (not q1) q2))"; + String constraint1 = + "(set-logic QF_UF)\n" + + "(declare-fun q1 () Bool)\n" + + "(declare-fun q2 () Bool)\n" + + "(assert (or (not q1) q2))"; String constraint2 = "(assert q1)"; String constraint3 = "(assert (not q2))"; @@ -208,8 +209,9 @@ public void testSmtInterpolProof() throws Exception { // Create a prover with proof and model generation enabled. SmtInterpolTheoremProver prover = - (SmtInterpolTheoremProver) context.newProverEnvironment0( - ImmutableSet.of(ProverOptions.GENERATE_PROOFS, ProverOptions.GENERATE_MODELS)); + (SmtInterpolTheoremProver) + context.newProverEnvironment0( + ImmutableSet.of(ProverOptions.GENERATE_PROOFS, ProverOptions.GENERATE_MODELS)); SMTInterpol smtInterpol = (SMTInterpol) prover.env; try { // Act: add constraints and check unsat. @@ -225,9 +227,8 @@ public void testSmtInterpolProof() throws Exception { Term proof = prover.smtInterpolGetProof(); assertThat(proof).isNotNull(); - - //String proofStr = proof.toString(); - //System.out.println(proofStr); + // String proofStr = proof.toString(); + // System.out.println(proofStr); System.out.println(proof); // Optionally, additional assertions on the dag structure can be added here. @@ -241,7 +242,4 @@ public static Object invokeGetProofMode(SMTInterpol instance) throws Exception { getProofModeMethod.setAccessible(true); return getProofModeMethod.invoke(instance); } - - - -} \ No newline at end of file +} diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolSolverContext.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolSolverContext.java index 5432a2d5af..f469173d67 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolSolverContext.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolSolverContext.java @@ -10,9 +10,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; -import static de.uni_freiburg.informatik.ultimate.smtinterpol.smtlib2.SMTInterpol.ProofMode; -import ap.Prover; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import de.uni_freiburg.informatik.ultimate.logic.LoggingScript; diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java index 4b459d2bba..646aa8e3ff 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java @@ -20,10 +20,8 @@ import org.sosy_lab.java_smt.api.Formula; /** - * This class is used to process the proof generated by Z3 and store it as a ProofNode. It - * is a non-recursive - * implementation of - * the proof processor. + * This class is used to process the proof generated by Z3 and store it as a ProofNode. It is a + * non-recursive implementation of the proof processor. */ @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) class Z3NonRecursiveProofProcessor { @@ -33,8 +31,7 @@ class Z3NonRecursiveProofProcessor { private final Z3AbstractProver prover; Z3NonRecursiveProofProcessor( - long ctx, long solver, Z3FormulaCreator creator, - Z3AbstractProver pProver) { + long ctx, long solver, Z3FormulaCreator creator, Z3AbstractProver pProver) { z3context = ctx; z3solver = solver; formulaCreator = creator; @@ -208,4 +205,3 @@ private static class Frame { } } } - diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDag.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDag.java index f635020e88..e008ce8c92 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDag.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDag.java @@ -10,10 +10,6 @@ package org.sosy_lab.java_smt.solvers.z3; - import org.sosy_lab.java_smt.basicimpl.AbstractProofDag; - -public class Z3ProofDag extends AbstractProofDag { - -} +public class Z3ProofDag extends AbstractProofDag {} diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofNode.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofNode.java index 3dcd6de3fd..26fda40dfd 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofNode.java @@ -31,5 +31,4 @@ private String asString(int indentLevel) { return proof.toString(); } - -} \ No newline at end of file +} diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofProcessor.java index 470711ac06..2d19389d89 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofProcessor.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofProcessor.java @@ -10,7 +10,6 @@ package org.sosy_lab.java_smt.solvers.z3; - import com.microsoft.z3.Native; import com.microsoft.z3.enumerations.Z3_decl_kind; import com.microsoft.z3.enumerations.Z3_sort_kind; @@ -19,17 +18,14 @@ import org.sosy_lab.java_smt.api.Formula; @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) - class Z3ProofProcessor { +class Z3ProofProcessor { private final long z3context; private final long z3solver; private final Z3FormulaCreator formulaCreator; private final Z3AbstractProver prover; private final Map parsed = new HashMap<>(); - - Z3ProofProcessor( - long ctx, long solver, Z3FormulaCreator creator, - Z3AbstractProver pProver) { + Z3ProofProcessor(long ctx, long solver, Z3FormulaCreator creator, Z3AbstractProver pProver) { z3context = ctx; z3solver = solver; formulaCreator = creator; @@ -44,8 +40,7 @@ Z3ProofNode fromAST(long proof) { Native.incRef(z3context, proof); long sort = Native.getSort(z3context, proof); long sortKind = Native.getSortKind(z3context, sort); - int declKind = Native.getDeclKind(z3context, - Native.getAppDecl(z3context, proof)); + int declKind = Native.getDeclKind(z3context, Native.getAppDecl(z3context, proof)); int numArgs = Native.getAppNumArgs(z3context, proof); Z3_sort_kind sort_kind = Z3_sort_kind.fromInt((int) sortKind); Formula formula; @@ -170,8 +165,8 @@ private Z3ProofRule getPRfromDK(int declKind) { } } - //@Nullable - //private Formula getFromStoredConstraints(long proof) { + // @Nullable + // private Formula getFromStoredConstraints(long proof) { // String varName = Native.astToString(z3context, proof); // if (prover.getStoredConstraints().peek().containsKey(varName)) { // return prover.getStoredConstraints().peek().get(varName); @@ -182,13 +177,10 @@ private Z3ProofRule getPRfromDK(int declKind) { private Formula generateFormula(long proof) { Formula formula = null; - //Formula formula = getFromStoredConstraints(proof); + // Formula formula = getFromStoredConstraints(proof); if (formula == null) { formula = formulaCreator.encapsulate(formulaCreator.getFormulaType(proof), proof); } return formula; } - } - - diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java index 2d13a11a7f..415c0914e2 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java @@ -1,16 +1,12 @@ - package org.sosy_lab.java_smt.solvers.z3; -import com.microsoft.z3.*; - - import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import com.microsoft.z3.*; import com.microsoft.z3.Context; import com.microsoft.z3.Solver; - import java.lang.reflect.Constructor; import java.util.HashMap; import java.util.Set; @@ -23,10 +19,8 @@ import org.sosy_lab.common.configuration.Configuration; import org.sosy_lab.common.log.BasicLogManager; import org.sosy_lab.common.log.LogManager; - import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.FloatingPointRoundingMode; - import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.SolverException; import org.sosy_lab.java_smt.api.proofs.ProofNode; @@ -48,16 +42,16 @@ public void setUpSolver() throws Exception { ShutdownManager shutdown = ShutdownManager.create(); // Create new context with SMTInterpol - context = Z3SolverContext.create( - logger, - config, - shutdown.getNotifier(), - null, // no logfile - 42, // random seed value - FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN, - NonLinearArithmetic.USE, - NativeLibraries::loadLibrary - ); + context = + Z3SolverContext.create( + logger, + config, + shutdown.getNotifier(), + null, // no logfile + 42, // random seed value + FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN, + NonLinearArithmetic.USE, + NativeLibraries::loadLibrary); mgr = (Z3FormulaManager) context.getFormulaManager(); bmgr = (Z3BooleanFormulaManager) mgr.getBooleanFormulaManager(); } @@ -71,12 +65,12 @@ public void closeSolver() { @Test public void getProofTest() throws InterruptedException { - //example from the 2022 RESOLUTE paper + // example from the 2022 RESOLUTE paper BooleanFormula q1 = bmgr.makeVariable("q1"); BooleanFormula q2 = bmgr.makeVariable("q2"); ProverEnvironment prover = context.newProverEnvironment0(Set.of()); - //Z3TheoremProver prover = + // Z3TheoremProver prover = // (Z3TheoremProver) context.newProverEnvironment0(Set.of(ProverOptions // .GENERATE_UNSAT_CORE)); try { @@ -95,12 +89,12 @@ public void getProofTest() throws InterruptedException { @Test public void printProofTest() throws InterruptedException { - //example from the 2022 RESOLUTE paper + // example from the 2022 RESOLUTE paper BooleanFormula q1 = bmgr.makeVariable("q1"); BooleanFormula q2 = bmgr.makeVariable("q2"); ProverEnvironment prover = context.newProverEnvironment0(Set.of()); - //Z3TheoremProver prover = + // Z3TheoremProver prover = // (Z3TheoremProver) context.newProverEnvironment0(Set.of(ProverOptions // .GENERATE_UNSAT_CORE)); try { @@ -121,12 +115,12 @@ public void printProofTest() throws InterruptedException { @Test public void internalPrintProcessedProofTest() throws SolverException, InterruptedException { - //example from the 2022 RESOLUTE paper + // example from the 2022 RESOLUTE paper BooleanFormula q1 = bmgr.makeVariable("q1"); BooleanFormula q2 = bmgr.makeVariable("q2"); Z3TheoremProver prover = (Z3TheoremProver) context.newProverEnvironment0(Set.of()); - //Z3TheoremProver prover = + // Z3TheoremProver prover = // (Z3TheoremProver) context.newProverEnvironment0(Set.of(ProverOptions // .GENERATE_UNSAT_CORE)); try { @@ -137,14 +131,16 @@ public void internalPrintProcessedProofTest() throws SolverException, Interrupte assertTrue(prover.isUnsat()); long proof = prover.getZ3Proof(); - Z3ProofProcessor - parser = new Z3ProofProcessor(mgr.getEnvironment(), prover.getZ3solver(), - (Z3FormulaCreator) mgr.getFormulaCreator(), prover); + Z3ProofProcessor parser = + new Z3ProofProcessor( + mgr.getEnvironment(), + prover.getZ3solver(), + (Z3FormulaCreator) mgr.getFormulaCreator(), + prover); Z3ProofNode root = parser.fromAST(proof); System.out.println(root.asString()); - } finally { prover.close(); } @@ -152,12 +148,12 @@ public void internalPrintProcessedProofTest() throws SolverException, Interrupte @Test public void nonRecursivePrintParsedProofTest() throws SolverException, InterruptedException { - //example from the 2022 RESOLUTE paper + // example from the 2022 RESOLUTE paper BooleanFormula q1 = bmgr.makeVariable("q1"); BooleanFormula q2 = bmgr.makeVariable("q2"); Z3TheoremProver prover = (Z3TheoremProver) context.newProverEnvironment0(Set.of()); - //Z3TheoremProver prover = + // Z3TheoremProver prover = // (Z3TheoremProver) context.newProverEnvironment0(Set.of(ProverOptions // .GENERATE_UNSAT_CORE)); try { @@ -168,14 +164,16 @@ public void nonRecursivePrintParsedProofTest() throws SolverException, Interrupt assertTrue(prover.isUnsat()); long proof = prover.getZ3Proof(); - Z3NonRecursiveProofProcessor - parser = new Z3NonRecursiveProofProcessor(mgr.getEnvironment(), prover.getZ3solver(), - (Z3FormulaCreator) mgr.getFormulaCreator(), prover); + Z3NonRecursiveProofProcessor parser = + new Z3NonRecursiveProofProcessor( + mgr.getEnvironment(), + prover.getZ3solver(), + (Z3FormulaCreator) mgr.getFormulaCreator(), + prover); Z3ProofNode root = parser.fromASTIterative(proof); System.out.println(root.asString()); - } finally { prover.close(); } @@ -184,12 +182,12 @@ public void nonRecursivePrintParsedProofTest() throws SolverException, Interrupt @Test public void compareRecursiveAndNonRecursiveOutputsTest() throws SolverException, InterruptedException { - //example from the 2022 RESOLUTE paper + // example from the 2022 RESOLUTE paper BooleanFormula q1 = bmgr.makeVariable("q1"); BooleanFormula q2 = bmgr.makeVariable("q2"); Z3TheoremProver prover = (Z3TheoremProver) context.newProverEnvironment0(Set.of()); - //Z3TheoremProver prover = + // Z3TheoremProver prover = // (Z3TheoremProver) context.newProverEnvironment0(Set.of(ProverOptions // .GENERATE_UNSAT_CORE)); try { @@ -201,19 +199,24 @@ public void compareRecursiveAndNonRecursiveOutputsTest() long proof = prover.getZ3Proof(); - Z3ProofProcessor - parser = new Z3ProofProcessor(mgr.getEnvironment(), prover.getZ3solver(), - (Z3FormulaCreator) mgr.getFormulaCreator(), prover); + Z3ProofProcessor parser = + new Z3ProofProcessor( + mgr.getEnvironment(), + prover.getZ3solver(), + (Z3FormulaCreator) mgr.getFormulaCreator(), + prover); Z3ProofNode root = parser.fromAST(proof); - Z3NonRecursiveProofProcessor - nrParser = new Z3NonRecursiveProofProcessor(mgr.getEnvironment(), prover.getZ3solver(), - (Z3FormulaCreator) mgr.getFormulaCreator(), prover); + Z3NonRecursiveProofProcessor nrParser = + new Z3NonRecursiveProofProcessor( + mgr.getEnvironment(), + prover.getZ3solver(), + (Z3FormulaCreator) mgr.getFormulaCreator(), + prover); Z3ProofNode nRroot = nrParser.fromASTIterative(proof); assertEquals(root.asString(), nRroot.asString()); - } finally { prover.close(); } @@ -283,9 +286,5 @@ public void Z3handleTransitivityTest() { ProofNode res = pc.handleTransitivity(pn); pc.printProof(res, 0); - - } - } - diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java index a9fc995dcc..3e93d032f1 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java @@ -55,8 +55,10 @@ public final class Z3SolverContext extends AbstractSolverContext { @Options(prefix = "solver.z3") private static class ExtraOptions { - @Option(secure = true, description = "Require proofs from SMT solver", - values = {"true", "false"}) + @Option( + secure = true, + description = "Require proofs from SMT solver", + values = {"true", "false"}) boolean requireProofs = false; @Option( @@ -282,7 +284,7 @@ public void close() { } } - //Method exlcusively used for testing + // Method exlcusively used for testing boolean getGenerateProofs() { return GENERATE_PROOFS; } diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java index a030633826..17f7c8e3a2 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java @@ -14,7 +14,9 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.ResolutionProofDag; import org.sosy_lab.java_smt.ResolutionProofNode; @@ -28,72 +30,67 @@ import org.sosy_lab.java_smt.api.visitors.BooleanFormulaVisitor; import org.sosy_lab.java_smt.api.visitors.TraversalProcess; -import java.util.HashMap; -import java.util.Map; - -/** - * Converts a Z3 proof to a RESOLUTE proof. - */ - -@SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access","ModifiedButNotUsed"}) +/** Converts a Z3 proof to a RESOLUTE proof. */ +@SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access", "ModifiedButNotUsed"}) public class Z3ToResoluteProofConverter { private final Z3FormulaManager formulaManager; private final BooleanFormulaManager bfm; - Z3ToResoluteProofConverter(Z3FormulaManager creator) { + Z3ToResoluteProofConverter(Z3FormulaManager creator) { formulaManager = creator; bfm = formulaManager.getBooleanFormulaManager(); } private static final Map ruleMapping = new HashMap<>(); -/* - static { - ruleMapping.put(Z3ProofRule.UNDEF, ResAxiom.ORACLE); - ruleMapping.put(Z3ProofRule.TRUE, ResAxiom.TRUE_POSITIVE); - ruleMapping.put(Z3ProofRule.ASSERTED, ResAxiom.ASSUME); - ruleMapping.put(Z3ProofRule.GOAL, ResAxiom.ASSUME); - ruleMapping.put(Z3ProofRule.REFLEXIVITY, ResAxiom.REFLEXIVITY); - ruleMapping.put(Z3ProofRule.SYMMETRY, ResAxiom.SYMMETRY); - ruleMapping.put(Z3ProofRule.TRANSITIVITY, ResAxiom.TRANSITIVITY); - ruleMapping.put(Z3ProofRule.TRANSITIVITY_STAR, ResAxiom.TRANSITIVITY_STAR); - ruleMapping.put(Z3ProofRule.MONOTONICITY, ResAxiom.MONOTONICITY); - ruleMapping.put(Z3ProofRule.QUANT_INTRO, ResAxiom.QUANT_INTRO); - ruleMapping.put(Z3ProofRule.BIND, ResAxiom.BIND); - ruleMapping.put(Z3ProofRule.DISTRIBUTIVITY, ResAxiom.DISTRIBUTIVITY); - ruleMapping.put(Z3ProofRule.AND_ELIM, ResAxiom.AND_POSITIVE); - ruleMapping.put(Z3ProofRule.NOT_OR_ELIM, ResAxiom.NOT_NEGATIVE); - ruleMapping.put(Z3ProofRule.REWRITE, ResAxiom.REWRITE); - ruleMapping.put(Z3ProofRule.REWRITE_STAR, ResAxiom.REWRITE_STAR); - ruleMapping.put(Z3ProofRule.PULL_QUANT, ResAxiom.PULL_QUANT); - ruleMapping.put(Z3ProofRule.PUSH_QUANT, ResAxiom.PUSH_QUANT); - ruleMapping.put(Z3ProofRule.ELIM_UNUSED_VARS, ResAxiom.ELIM_UNUSED_VARS); - ruleMapping.put(Z3ProofRule.DER, ResAxiom.DER); - ruleMapping.put(Z3ProofRule.QUANT_INST, ResAxiom.QUANT_INST); - ruleMapping.put(Z3ProofRule.HYPOTHESIS, ResAxiom.HYPOTHESIS); - ruleMapping.put(Z3ProofRule.LEMMA, ResAxiom.LEMMA); - ruleMapping.put(Z3ProofRule.UNIT_RESOLUTION, ResAxiom.UNIT_RESOLUTION); - ruleMapping.put(Z3ProofRule.IFF_TRUE, ResAxiom.IFF_TRUE); - ruleMapping.put(Z3ProofRule.IFF_FALSE, ResAxiom.IFF_FALSE); - ruleMapping.put(Z3ProofRule.COMMUTATIVITY, ResAxiom.COMMUTATIVITY); - ruleMapping.put(Z3ProofRule.DEF_AXIOM, ResAxiom.DEF_AXIOM); - ruleMapping.put(Z3ProofRule.ASSUMPTION_ADD, ResAxiom.ASSUMPTION_ADD); - ruleMapping.put(Z3ProofRule.LEMMA_ADD, ResAxiom.LEMMA_ADD); - ruleMapping.put(Z3ProofRule.REDUNDANT_DEL, ResAxiom.REDUNDANT_DEL); - ruleMapping.put(Z3ProofRule.CLAUSE_TRAIL, ResAxiom.CLAUSE_TRAIL); - ruleMapping.put(Z3ProofRule.DEF_INTRO, ResAxiom.DEF_INTRO); - ruleMapping.put(Z3ProofRule.APPLY_DEF, ResAxiom.APPLY_DEF); - ruleMapping.put(Z3ProofRule.IFF_OEQ, ResAxiom.IFF_OEQ); - ruleMapping.put(Z3ProofRule.NNF_POS, ResAxiom.NNF_POS); - ruleMapping.put(Z3ProofRule.NNF_NEG, ResAxiom.NNF_NEG); - ruleMapping.put(Z3ProofRule.SKOLEMIZE, ResAxiom.SKOLEMIZE); - ruleMapping.put(Z3ProofRule.MODUS_PONENS_OEQ, ResAxiom.MODUS_PONENS_OEQ); - ruleMapping.put(Z3ProofRule.TH_LEMMA, ResAxiom.TH_LEMMA); - ruleMapping.put(Z3ProofRule.HYPER_RESOLVE, ResAxiom.HYPER_RESOLVE); - } - */ + /* + static { + ruleMapping.put(Z3ProofRule.UNDEF, ResAxiom.ORACLE); + ruleMapping.put(Z3ProofRule.TRUE, ResAxiom.TRUE_POSITIVE); + ruleMapping.put(Z3ProofRule.ASSERTED, ResAxiom.ASSUME); + ruleMapping.put(Z3ProofRule.GOAL, ResAxiom.ASSUME); + ruleMapping.put(Z3ProofRule.REFLEXIVITY, ResAxiom.REFLEXIVITY); + ruleMapping.put(Z3ProofRule.SYMMETRY, ResAxiom.SYMMETRY); + ruleMapping.put(Z3ProofRule.TRANSITIVITY, ResAxiom.TRANSITIVITY); + ruleMapping.put(Z3ProofRule.TRANSITIVITY_STAR, ResAxiom.TRANSITIVITY_STAR); + ruleMapping.put(Z3ProofRule.MONOTONICITY, ResAxiom.MONOTONICITY); + ruleMapping.put(Z3ProofRule.QUANT_INTRO, ResAxiom.QUANT_INTRO); + ruleMapping.put(Z3ProofRule.BIND, ResAxiom.BIND); + ruleMapping.put(Z3ProofRule.DISTRIBUTIVITY, ResAxiom.DISTRIBUTIVITY); + ruleMapping.put(Z3ProofRule.AND_ELIM, ResAxiom.AND_POSITIVE); + ruleMapping.put(Z3ProofRule.NOT_OR_ELIM, ResAxiom.NOT_NEGATIVE); + ruleMapping.put(Z3ProofRule.REWRITE, ResAxiom.REWRITE); + ruleMapping.put(Z3ProofRule.REWRITE_STAR, ResAxiom.REWRITE_STAR); + ruleMapping.put(Z3ProofRule.PULL_QUANT, ResAxiom.PULL_QUANT); + ruleMapping.put(Z3ProofRule.PUSH_QUANT, ResAxiom.PUSH_QUANT); + ruleMapping.put(Z3ProofRule.ELIM_UNUSED_VARS, ResAxiom.ELIM_UNUSED_VARS); + ruleMapping.put(Z3ProofRule.DER, ResAxiom.DER); + ruleMapping.put(Z3ProofRule.QUANT_INST, ResAxiom.QUANT_INST); + ruleMapping.put(Z3ProofRule.HYPOTHESIS, ResAxiom.HYPOTHESIS); + ruleMapping.put(Z3ProofRule.LEMMA, ResAxiom.LEMMA); + ruleMapping.put(Z3ProofRule.UNIT_RESOLUTION, ResAxiom.UNIT_RESOLUTION); + ruleMapping.put(Z3ProofRule.IFF_TRUE, ResAxiom.IFF_TRUE); + ruleMapping.put(Z3ProofRule.IFF_FALSE, ResAxiom.IFF_FALSE); + ruleMapping.put(Z3ProofRule.COMMUTATIVITY, ResAxiom.COMMUTATIVITY); + ruleMapping.put(Z3ProofRule.DEF_AXIOM, ResAxiom.DEF_AXIOM); + ruleMapping.put(Z3ProofRule.ASSUMPTION_ADD, ResAxiom.ASSUMPTION_ADD); + ruleMapping.put(Z3ProofRule.LEMMA_ADD, ResAxiom.LEMMA_ADD); + ruleMapping.put(Z3ProofRule.REDUNDANT_DEL, ResAxiom.REDUNDANT_DEL); + ruleMapping.put(Z3ProofRule.CLAUSE_TRAIL, ResAxiom.CLAUSE_TRAIL); + ruleMapping.put(Z3ProofRule.DEF_INTRO, ResAxiom.DEF_INTRO); + ruleMapping.put(Z3ProofRule.APPLY_DEF, ResAxiom.APPLY_DEF); + ruleMapping.put(Z3ProofRule.IFF_OEQ, ResAxiom.IFF_OEQ); + ruleMapping.put(Z3ProofRule.NNF_POS, ResAxiom.NNF_POS); + ruleMapping.put(Z3ProofRule.NNF_NEG, ResAxiom.NNF_NEG); + ruleMapping.put(Z3ProofRule.SKOLEMIZE, ResAxiom.SKOLEMIZE); + ruleMapping.put(Z3ProofRule.MODUS_PONENS_OEQ, ResAxiom.MODUS_PONENS_OEQ); + ruleMapping.put(Z3ProofRule.TH_LEMMA, ResAxiom.TH_LEMMA); + ruleMapping.put(Z3ProofRule.HYPER_RESOLVE, ResAxiom.HYPER_RESOLVE); + } + + */ /* public static ResAxiom mapRule(Z3ProofRule z3Rule) { @@ -101,8 +98,7 @@ public static ResAxiom mapRule(Z3ProofRule z3Rule) { } */ - - static ResolutionProofDag convertToResolutionProofDag(Z3ProofNode[] z3ProofNodes) { + static ResolutionProofDag convertToResolutionProofDag(Z3ProofNode[] z3ProofNodes) { ResolutionProofDag dag = new ResolutionProofDag(); for (Z3ProofNode z3Node : z3ProofNodes) { @@ -110,9 +106,9 @@ static ResolutionProofDag convertToResolutionProofDag(Z3ProofNode[] z3ProofNodes } else { Formula formula = z3Node.getFormula(); - //ResAxiom resAxiom = mapRule(z3Node.getRule()); - //SourceProofNode sourceNode = new SourceProofNode(resAxiom, formula); - //dag.addNode(sourceNode); + // ResAxiom resAxiom = mapRule(z3Node.getRule()); + // SourceProofNode sourceNode = new SourceProofNode(resAxiom, formula); + // dag.addNode(sourceNode); } } @@ -170,9 +166,7 @@ public TraversalProcess visitXor(BooleanFormula operand1, BooleanFormula operand @Override public TraversalProcess visitIfThenElse( - BooleanFormula condition, - BooleanFormula thenFormula, - BooleanFormula elseFormula) { + BooleanFormula condition, BooleanFormula thenFormula, BooleanFormula elseFormula) { return TraversalProcess.CONTINUE; } @@ -187,8 +181,7 @@ public TraversalProcess visitQuantifier( @Override public TraversalProcess visitAtom( - BooleanFormula atom, - FunctionDeclaration funcDecl) { + BooleanFormula atom, FunctionDeclaration funcDecl) { return TraversalProcess.CONTINUE; } } @@ -373,7 +366,6 @@ ProofNode handleSymmetry(Z3ProofNode node) { return pn; } - ProofNode handleTransitivity(Z3ProofNode node) { BooleanFormula t1 = (BooleanFormula) node.getChildren().get(0).getFormula(); @@ -385,17 +377,13 @@ ProofNode handleTransitivity(Z3ProofNode node) { assert equivalenceOperands1.get(1).equals(equivalenceOperands2.get(0)); - BooleanFormula transRes = - formula; - BooleanFormula transClause = bfm.or(bfm.not(t1), - bfm.not(t2), formula); + BooleanFormula transRes = formula; + BooleanFormula transClause = bfm.or(bfm.not(t1), bfm.not(t2), formula); SourceProofNode pn = new SourceProofNode(ResAxiom.TRANSITIVITY, transClause); - ResolutionProofNode transResNode = new ResolutionProofNode(transRes, - t2); - ResolutionProofNode trnAnte1 = - new ResolutionProofNode(t2, t2); + ResolutionProofNode transResNode = new ResolutionProofNode(transRes, t2); + ResolutionProofNode trnAnte1 = new ResolutionProofNode(t2, t2); BooleanFormula trn2Formula = bfm.or(bfm.not(t2), transRes); ResolutionProofNode trnAnte2 = new ResolutionProofNode(trn2Formula, t1); ResolutionProofNode trnAnte2Ante = new ResolutionProofNode(t1, t1); @@ -410,33 +398,29 @@ ProofNode handleTransitivity(Z3ProofNode node) { ProofNode handleTransitivityStar(Z3ProofNode node) { BooleanFormula resPivot = null; - Collection formulas = new ArrayList<>(); - List> formulaList = new ArrayList<>(); - int numChildren = node.getChildren().size(); - - for (int i = 0; i < numChildren; i++) { - Collection newCollection = new ArrayList<>(); - formulas.add(bfm.not((BooleanFormula) node.getChildren().get(i).getFormula())); - if (i == numChildren - 1) { - resPivot = (BooleanFormula) node.getChildren().get(i).getFormula(); - } - } + Collection formulas = new ArrayList<>(); + List> formulaList = new ArrayList<>(); + int numChildren = node.getChildren().size(); + + for (int i = 0; i < numChildren; i++) { + Collection newCollection = new ArrayList<>(); + formulas.add(bfm.not((BooleanFormula) node.getChildren().get(i).getFormula())); + if (i == numChildren - 1) { + resPivot = (BooleanFormula) node.getChildren().get(i).getFormula(); + } + } assert resPivot != null; ResolutionProofNode resNode = new ResolutionProofNode(node.getFormula(), resPivot); + formulas.add((BooleanFormula) node.getFormula()); + BooleanFormula transitivityFormula = bfm.or(formulas); + SourceProofNode sn = new SourceProofNode(ResAxiom.TRANSITIVITY, transitivityFormula); - formulas.add((BooleanFormula) node.getFormula()); - BooleanFormula transitivityFormula = bfm.or(formulas); - SourceProofNode sn = new SourceProofNode(ResAxiom.TRANSITIVITY, transitivityFormula); - - for (int i = 0; i < formulas.size()-2; i++){ - //ResolutionProofNode pn1 = new ResolutionProofNode(transitivityFormula., - //formulaList.get(i)) - } - - - + for (int i = 0; i < formulas.size() - 2; i++) { + // ResolutionProofNode pn1 = new ResolutionProofNode(transitivityFormula., + // formulaList.get(i)) + } return resNode; } @@ -581,8 +565,6 @@ ProofNode handleDefault(Z3ProofNode node) { return null; } - - void printProof(ProofNode node, int indentLevel) { String indent = " ".repeat(indentLevel); @@ -611,6 +593,4 @@ void printProof(ProofNode node, int indentLevel) { throw new AssertionError("Unknown proof node type"); } } - - } diff --git a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java index b79de02546..174334c0c0 100644 --- a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java +++ b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java @@ -84,7 +84,7 @@ public void unsatCoreTestForInterpolation() throws SolverException, InterruptedE requireUnsatCore(); requireInterpolation(); try (BasicProverEnvironment pe = - context.newProverEnvironmentWithInterpolation(GENERATE_UNSAT_CORE)) { + context.newProverEnvironmentWithInterpolation(GENERATE_UNSAT_CORE)) { unsatCoreTest0(pe); } } @@ -94,7 +94,7 @@ public void unsatCoreTestForOptimizationProver() throws SolverException, Interru requireUnsatCore(); requireOptimization(); try (BasicProverEnvironment pe = - context.newOptimizationProverEnvironment(GENERATE_UNSAT_CORE)) { + context.newOptimizationProverEnvironment(GENERATE_UNSAT_CORE)) { unsatCoreTest0(pe); } } @@ -124,7 +124,7 @@ public void unsatCoreWithAssumptionsNullTest() { .isNoneOf(PRINCESS, CVC4, CVC5, OPENSMT); try (ProverEnvironment pe = - context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { + context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { assertThrows(NullPointerException.class, () -> pe.unsatCoreOverAssumptions(null)); } } @@ -139,7 +139,7 @@ public void unsatCoreWithAssumptionsTest() throws SolverException, InterruptedEx .that(solverToUse()) .isNoneOf(PRINCESS, CVC4, CVC5, OPENSMT); try (ProverEnvironment pe = - context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { + context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { pe.push(); pe.addConstraint(imgr.equal(imgr.makeVariable("y"), imgr.makeNumber(2))); BooleanFormula selector = bmgr.makeVariable("b"); @@ -161,13 +161,12 @@ public void testSatWithUnsatUnsatCoreOptions() throws InterruptedException, Solv requireUnsatCoreOverAssumptions(); try (ProverEnvironment prover = - context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { + context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { checkSimpleQuery(prover); } try (ProverEnvironment prover = - context.newProverEnvironment(GENERATE_UNSAT_CORE, - GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { + context.newProverEnvironment(GENERATE_UNSAT_CORE, GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { checkSimpleQuery(prover); } } diff --git a/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java b/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java index 576bee8c54..ef58d2e377 100644 --- a/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java +++ b/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java @@ -380,11 +380,11 @@ protected void requireUserPropagators() { .isEqualTo(Solvers.Z3); } - protected void requireProofGeneration(){ - assume() - .withMessage("Solver %s does not support proof generation", solverToUse()) - .that(solverToUse()) - .isNoneOf(Solvers.BOOLECTOR, Solvers.BITWUZLA, Solvers.YICES2); + protected void requireProofGeneration() { + assume() + .withMessage("Solver %s does not support proof generation", solverToUse()) + .that(solverToUse()) + .isNoneOf(Solvers.BOOLECTOR, Solvers.BITWUZLA, Solvers.YICES2); } /** From 018d857b8b39e01da9f0d57a946398646b374aa4 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 21 Mar 2025 19:44:52 +0100 Subject: [PATCH 022/132] Class ProofRuleRegistry now allows to get a proof rule from any solver by the name of the rule --- .../sosy_lab/java_smt/ProofRuleRegistry.java | 29 +++ .../java_smt/solvers/cvc5/CVC5ProofRule.java | 176 +++++++++++++++++- .../java_smt/solvers/z3/Z3ProofRule.java | 24 ++- 3 files changed, 220 insertions(+), 9 deletions(-) create mode 100644 src/org/sosy_lab/java_smt/ProofRuleRegistry.java diff --git a/src/org/sosy_lab/java_smt/ProofRuleRegistry.java b/src/org/sosy_lab/java_smt/ProofRuleRegistry.java new file mode 100644 index 0000000000..a598689f0d --- /dev/null +++ b/src/org/sosy_lab/java_smt/ProofRuleRegistry.java @@ -0,0 +1,29 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt; + +import java.util.HashMap; +import java.util.Map; +import org.sosy_lab.java_smt.api.proofs.ProofRule; + +public class ProofRuleRegistry { + // Key: ProofRule class, Value: (Key: Name, Value: ProofRule) + private static final Map, Map> RULES = + new HashMap<>(); + + public static void register(Class clazz, ProofRule rule) { + RULES.computeIfAbsent(clazz, k -> new HashMap<>()).put(rule.getName(), rule); + } + + public static ProofRule fromName(Class clazz, String name) { + return RULES.getOrDefault(clazz, new HashMap<>()).get(name); + } +} diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofRule.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofRule.java index 416629bcc0..d49aa0b223 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofRule.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofRule.java @@ -10,10 +10,184 @@ package org.sosy_lab.java_smt.solvers.cvc5; +import java.util.HashMap; +import java.util.Map; +import org.sosy_lab.java_smt.ProofRuleRegistry; import org.sosy_lab.java_smt.api.proofs.ProofRule; +// TODO: Properly include the formulas for the proof rules. public enum CVC5ProofRule implements ProofRule { - ACI_RULE(); + ASSUME("assume", ""), + SCOPE("scope", ""), + SUBS("subs", ""), + MACRO_REWRITE("macro_rewrite", ""), + EVALUATE("evaluate", ""), + DISTINCT_VALUES("distinct_values", ""), + ACI_NORM("aci_norm", ""), + ABSORB("absorb", ""), + MACRO_SR_EQ_INTRO("macro_sr_eq_intro", ""), + MACRO_SR_PRED_INTRO("macro_sr_pred_intro", ""), + MACRO_SR_PRED_ELIM("macro_sr_pred_elim", ""), + MACRO_SR_PRED_TRANSFORM("macro_sr_pred_transform", ""), + ENCODE_EQ_INTRO("encode_eq_intro", ""), + DSL_REWRITE("dsl_rewrite", ""), + THEORY_REWRITE("theory_rewrite", ""), + ITE_EQ("ite_eq", ""), + TRUST("trust", ""), + TRUST_THEORY_REWRITE("trust_theory_rewrite", ""), + SAT_REFUTATION("sat_refutation", ""), + DRAT_REFUTATION("drat_refutation", ""), + SAT_EXTERNAL_PROVE("sat_external_prove", ""), + RESOLUTION("resolution", ""), + CHAIN_RESOLUTION("chain_resolution", ""), + FACTORING("factoring", ""), + REORDERING("reordering", ""), + MACRO_RESOLUTION("macro_resolution", ""), + MACRO_RESOLUTION_TRUST("macro_resolution_trust", ""), + SPLIT("split", ""), + EQ_RESOLVE("eq_resolve", ""), + MODUS_PONENS("modus_ponens", ""), + NOT_NOT_ELIM("not_not_elim", ""), + CONTRA("contra", ""), + AND_ELIM("and_elim", ""), + AND_INTRO("and_intro", ""), + NOT_OR_ELIM("not_or_elim", ""), + IMPLIES_ELIM("implies_elim", ""), + NOT_IMPLIES_ELIM1("not_implies_elim1", ""), + NOT_IMPLIES_ELIM2("not_implies_elim2", ""), + EQUIV_ELIM1("equiv_elim1", ""), + EQUIV_ELIM2("equiv_elim2", ""), + NOT_EQUIV_ELIM1("not_equiv_elim1", ""), + NOT_EQUIV_ELIM2("not_equiv_elim2", ""), + XOR_ELIM1("xor_elim1", ""), + XOR_ELIM2("xor_elim2", ""), + NOT_XOR_ELIM1("not_xor_elim1", ""), + NOT_XOR_ELIM2("not_xor_elim2", ""), + ITE_ELIM1("ite_elim1", ""), + ITE_ELIM2("ite_elim2", ""), + NOT_ITE_ELIM1("not_ite_elim1", ""), + NOT_ITE_ELIM2("not_ite_elim2", ""), + NOT_AND("not_and", ""), + CNF_AND_POS("cnf_and_pos", ""), + CNF_AND_NEG("cnf_and_neg", ""), + CNF_OR_POS("cnf_or_pos", ""), + CNF_OR_NEG("cnf_or_neg", ""), + CNF_IMPLIES_POS("cnf_implies_pos", ""), + CNF_IMPLIES_NEG1("cnf_implies_neg1", ""), + CNF_IMPLIES_NEG2("cnf_implies_neg2", ""), + CNF_EQUIV_POS1("cnf_equiv_pos1", ""), + CNF_EQUIV_POS2("cnf_equiv_pos2", ""), + CNF_EQUIV_NEG1("cnf_equiv_neg1", ""), + CNF_EQUIV_NEG2("cnf_equiv_neg2", ""), + CNF_XOR_POS1("cnf_xor_pos1", ""), + CNF_XOR_POS2("cnf_xor_pos2", ""), + CNF_XOR_NEG1("cnf_xor_neg1", ""), + CNF_XOR_NEG2("cnf_xor_neg2", ""), + CNF_ITE_POS1("cnf_ite_pos1", ""), + CNF_ITE_POS2("cnf_ite_pos2", ""), + CNF_ITE_POS3("cnf_ite_pos3", ""), + CNF_ITE_NEG1("cnf_ite_neg1", ""), + CNF_ITE_NEG2("cnf_ite_neg2", ""), + CNF_ITE_NEG3("cnf_ite_neg3", ""), + REFL("refl", ""), + SYMM("symm", ""), + TRANS("trans", ""), + CONG("cong", ""), + NARY_CONG("nary_cong", ""), + TRUE_INTRO("true_intro", ""), + TRUE_ELIM("true_elim", ""), + FALSE_INTRO("false_intro", ""), + FALSE_ELIM("false_elim", ""), + HO_APP_ENCODE("ho_app_encode", ""), + HO_CONG("ho_cong", ""), + ARRAYS_READ_OVER_WRITE("arrays_read_over_write", ""), + ARRAYS_READ_OVER_WRITE_CONTRA("arrays_read_over_write_contra", ""), + ARRAYS_READ_OVER_WRITE_1("arrays_read_over_write_1", ""), + ARRAYS_EXT("arrays_ext", ""), + MACRO_BV_BITBLAST("macro_bv_bitblast", ""), + BV_BITBLAST_STEP("bv_bitblast_step", ""), + BV_EAGER_ATOM("bv_eager_atom", ""), + BV_POLY_NORM("bv_poly_norm", ""), + BV_POLY_NORM_EQ("bv_poly_norm_eq", ""), + DT_SPLIT("dt_split", ""), + SKOLEM_INTRO("skolem_intro", ""), + SKOLEMIZE("skolemize", ""), + INSTANTIATE("instantiate", ""), + ALPHA_EQUIV("alpha_equiv", ""), + QUANT_VAR_REORDERING("quant_var_reordering", ""), + SETS_SINGLETON_INJ("sets_singleton_inj", ""), + SETS_EXT("sets_ext", ""), + SETS_FILTER_UP("sets_filter_up", ""), + SETS_FILTER_DOWN("sets_filter_down", ""), + CONCAT_EQ("concat_eq", ""), + CONCAT_UNIFY("concat_unify", ""), + CONCAT_SPLIT("concat_split", ""), + CONCAT_CSPLIT("concat_csplit", ""), + CONCAT_LPROP("concat_lprop", ""), + CONCAT_CPROP("concat_cprop", ""), + STRING_DECOMPOSE("string_decompose", ""), + STRING_LENGTH_POS("string_length_pos", ""), + STRING_LENGTH_NON_EMPTY("string_length_non_empty", ""), + STRING_REDUCTION("string_reduction", ""), + STRING_EAGER_REDUCTION("string_eager_reduction", ""), + RE_INTER("re_inter", ""), + RE_CONCAT("re_concat", ""), + RE_UNFOLD_POS("re_unfold_pos", ""), + RE_UNFOLD_NEG("re_unfold_neg", ""), + RE_UNFOLD_NEG_CONCAT_FIXED("re_unfold_neg_concat_fixed", ""), + STRING_CODE_INJ("string_code_inj", ""), + STRING_SEQ_UNIT_INJ("string_seq_unit_inj", ""), + STRING_EXT("string_ext", ""), + MACRO_STRING_INFERENCE("macro_string_inference", ""), + MACRO_ARITH_SCALE_SUM_UB("macro_arith_scale_sum_ub", ""), + ARITH_MULT_ABS_COMPARISON("arith_mult_abs_comparison", ""), + ARITH_SUM_UB("arith_sum_ub", ""), + INT_TIGHT_UB("int_tight_ub", ""), + INT_TIGHT_LB("int_tight_lb", ""), + ARITH_TRICHOTOMY("arith_trichotomy", ""), + ARITH_REDUCTION("arith_reduction", ""), + ARITH_POLY_NORM("arith_poly_norm", ""), + ARITH_POLY_NORM_REL("arith_poly_norm_rel", ""), + ARITH_MULT_SIGN("arith_mult_sign", ""), + ARITH_MULT_POS("arith_mult_pos", ""), + ARITH_MULT_NEG("arith_mult_neg", ""), + ARITH_MULT_TANGENT("arith_mult_tangent", ""), + ARITH_TRANS_PI("arith_trans_pi", ""), + ARITH_TRANS_EXP_NEG("arith_trans_exp_neg", ""), + ARITH_TRANS_EXP_POSITIVITY("arith_trans_exp_positivity", ""), + ARITH_TRANS_EXP_SUPER_LIN("arith_trans_exp_super_lin", ""), + ARITH_TRANS_EXP_ZERO("arith_trans_exp_zero", ""), + ARITH_TRANS_EXP_APPROX_ABOVE_NEG("arith_trans_exp_approx_above_neg", ""), + ARITH_TRANS_EXP_APPROX_ABOVE_POS("arith_trans_exp_approx_above_pos", ""), + ARITH_TRANS_EXP_APPROX_BELOW("arith_trans_exp_approx_below", ""), + ARITH_TRANS_SINE_BOUNDS("arith_trans_sine_bounds", ""), + ARITH_TRANS_SINE_SHIFT("arith_trans_sine_shift", ""), + ARITH_TRANS_SINE_SYMMETRY("arith_trans_sine_symmetry", ""), + ARITH_TRANS_SINE_TANGENT_ZERO("arith_trans_sine_tangent_zero", ""), + ARITH_TRANS_SINE_TANGENT_PI("arith_trans_sine_tangent_pi", ""), + ARITH_TRANS_SINE_APPROX_ABOVE_NEG("arith_trans_sine_approx_above_neg", ""), + ARITH_TRANS_SINE_APPROX_ABOVE_POS("arith_trans_sine_approx_above_pos", ""), + ARITH_TRANS_SINE_APPROX_BELOW_NEG("arith_trans_sine_approx_below_neg", ""), + ARITH_TRANS_SINE_APPROX_BELOW_POS("arith_trans_sine_approx_below_pos", ""), + LFSC_RULE("lfsc_rule", ""), + ALETHE_RULE("alethe_rule", ""), + UNKNOWN("unknown", ""); + + private final String name; + private final String formula; + + CVC5ProofRule(String pName, String pFormula) { + name = pName; + formula = pFormula; + } + + private static final Map NAME_TO_RULE_MAP = new HashMap<>(); + + static { + for (CVC5ProofRule rule : values()) { + ProofRuleRegistry.register(CVC5ProofRule.class, rule); + } + } @Override public String getName() { diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java index e6fa958eb1..753d55bf6d 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java @@ -10,9 +10,10 @@ package org.sosy_lab.java_smt.solvers.z3; +import org.sosy_lab.java_smt.ProofRuleRegistry; import org.sosy_lab.java_smt.api.proofs.ProofRule; -//TODO correctly document the formula strings +// TODO correctly document the formula strings public enum Z3ProofRule implements ProofRule { // Undefined proof object @@ -25,12 +26,12 @@ public enum Z3ProofRule implements ProofRule { // Logical inference rules MODUS_PONENS("modus_ponens", "(mp p (implies p q) q)"), - REFLEXIVITY("reflexivity", "reflexivity (R t t), R is element of {=, ~, iff}"), //no antecendts + REFLEXIVITY("reflexivity", "reflexivity (R t t), R is element of {=, ~, iff}"), // no antecendts SYMMETRY("symmetry", "symmetry (R t1 t2) (R t2 t1)"), TRANSITIVITY("transitivity", "trans (R t1 t2) (R t2 t3) (R t1 t3)"), TRANSITIVITY_STAR("transitivity*", "trans *(R t1 t2) ... (R t3 t4) (R t1 t4)"), - MONOTONICITY("monotonicity", "monotonicity (R t1 s1) ... (R tn sn) (R (f t1 ... tn) (f s1 ... " - + "sn))"), + MONOTONICITY( + "monotonicity", "monotonicity (R t1 s1) ... (R tn sn) (R (f t1 ... tn) (f s1 ... " + "sn))"), QUANT_INTRO("quant-intro", "quant-intro (~ p q) (~ (forall (x) p) (forall (x) q))"), BIND("bind", "(proof-bind f (forall (x) f))"), @@ -41,10 +42,11 @@ public enum Z3ProofRule implements ProofRule { NOT_OR_ELIM("not-or-elim", "not-or-elim (not (or p1 ... pn)) (not pi)"), // Rewriting and simplifications - REWRITE("rewrite", "rewrite (R t s), R is element of {=, iff}"), //no antededents + REWRITE("rewrite", "rewrite (R t s), R is element of {=, iff}"), // no antededents REWRITE_STAR("rewrite*", "rewrite* (= t1 t2) ... (= tn-1 tn) (= t1 tn)"), PULL_QUANT("pull_quant", "(= (f (forall x P(x)) R) (forall x (f P(x) R)))"), - PUSH_QUANT("push_quant", "(forall x (and P1(x) ... Pn(x))) (and (forall x P1(x)) ... (forall x Pn(x)))"), + PUSH_QUANT( + "push_quant", "(forall x (and P1(x) ... Pn(x))) (and (forall x P1(x)) ... (forall x Pn(x)))"), ELIM_UNUSED_VARS("elim_unused_vars", "(forall x y P(x)) (forall x P(x))"), DER("der", "(iff (forall x (or (not (= x t)) P(x))) P(t))"), QUANT_INST("quant_inst", "(or (not (forall x P(x))) P(a))"), @@ -52,7 +54,8 @@ public enum Z3ProofRule implements ProofRule { // Natural deduction style HYPOTHESIS("hypothesis", "(hypothesis p)"), LEMMA("lemma", "(or (not p1) ... (not pn))"), - UNIT_RESOLUTION("unit_resolution", "(or p1 ... pn q1 ... qm) (not p1) ... (not pn) (or q1 ... qm)"), + UNIT_RESOLUTION( + "unit_resolution", "(or p1 ... pn q1 ... qm) (not p1) ... (not pn) (or q1 ... qm)"), IFF_TRUE("iff_true", "(iff p true)"), IFF_FALSE("iff_false", "(iff p false)"), COMMUTATIVITY("commutativity", "(= (f a b) (f b a))"), @@ -93,6 +96,12 @@ public enum Z3ProofRule implements ProofRule { this.formula = formula; } + static { + for (Z3ProofRule rule : values()) { + ProofRuleRegistry.register(Z3ProofRule.class, rule); + } + } + @Override public String getName() { return name; @@ -103,4 +112,3 @@ public String getFormula() { return formula; } } - From 818fe70d687ae20c56d37acd7b899ff789f18bbd Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 21 Mar 2025 19:45:53 +0100 Subject: [PATCH 023/132] Class `ProofRuleRegistry` now allows to get a proof rule from any solver by the name of the rule thorugh `fromName` in `ProofRule` --- .../java_smt/api/proofs/ProofRule.java | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofRule.java b/src/org/sosy_lab/java_smt/api/proofs/ProofRule.java index 1b17b494ac..cfcec6859f 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofRule.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofRule.java @@ -10,20 +10,30 @@ package org.sosy_lab.java_smt.api.proofs; -/** - * A proof rule from a given proof format. - */ +import org.sosy_lab.java_smt.ProofRuleRegistry; + +/** A proof rule from a given proof format. */ public interface ProofRule { - /** - * Get the name of the proof rule. - */ + /** Get the name of the proof rule. */ String getName(); - /** - * Get the formula of the proof rule. - */ + /** Get the formula of the proof rule. */ default String getFormula() { return "no formula available"; } + + /** + * Get a proof rule from its name. + * + * @return A proof rule. + */ + static T fromName(Class clazz, String name) { + ProofRule rule = ProofRuleRegistry.fromName(clazz, name); + if (rule == null) { + throw new IllegalArgumentException( + "Unknown proof rule in " + clazz.getSimpleName() + ": " + name); + } + return clazz.cast(rule); + } } From 87159e8b9e74e0625a1569131ac261910258579d Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 21 Mar 2025 19:46:49 +0100 Subject: [PATCH 024/132] CVC5: Proofs are now processed and stored as `CVC5ProofNode` --- .../solvers/cvc5/CVC5ProofProcessor.java | 86 +++++++++++++++++ .../java_smt/solvers/cvc5/CVC5ProofsTest.java | 94 ++++++++++++++++++- 2 files changed, 176 insertions(+), 4 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java index 37bf3c4435..7b785a4748 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java @@ -10,5 +10,91 @@ package org.sosy_lab.java_smt.solvers.cvc5; +import io.github.cvc5.CVC5ApiException; +import io.github.cvc5.Proof; +import io.github.cvc5.Term; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.proofs.ProofRule; + public class CVC5ProofProcessor { + private final CVC5SolverContext context; + private final CVC5FormulaCreator formulaCreator; + private final CVC5AbstractProver prover; + + CVC5ProofProcessor( + CVC5SolverContext ctx, CVC5FormulaCreator creator, CVC5AbstractProver pProver) { + context = ctx; + formulaCreator = creator; + prover = pProver; + } + + CVC5ProofNode fromCVC5Proof(Proof rootProof) throws CVC5ApiException { + + Deque stack = new ArrayDeque<>(); + + Map computed = new HashMap<>(); + + stack.push(new Frame(rootProof)); + + while (!stack.isEmpty()) { + Frame frame = stack.peek(); + + // Skip processing the frame if its rule is "SCOPE" + // This rule seems to just help the processing by CVC5 + if (!frame.visited && frame.proof.getRule().getValue() == 1) { + // Pop the SCOPE frame and push its children onto the stack + stack.pop(); + frame.numChildren = rootProof.getChildren().length; + frame.visited = true; + + for (int i = frame.numChildren; i >= 0; i--) { + Proof child = rootProof.getChildren()[i]; + if (!computed.containsKey(child)) { + stack.push(new Frame(child)); + } + } + } else { + + stack.pop(); + int numChildren = frame.numChildren; + + CVC5ProofRule proofRule = + ProofRule.fromName(CVC5ProofRule.class, frame.proof.getRule().toString()); + CVC5ProofNode pn = new CVC5ProofNode(proofRule, generateFormula(frame.proof)); + for (int i = 0; i < numChildren - 1; i++) { + Proof child = frame.proof.getChildren()[i]; + + if (computed.containsKey(child)) { + pn.addChild(computed.get(child)); + } + } + computed.put(frame.proof, pn); + } + } + return computed.get(rootProof); + } + + private Formula generateFormula(Proof proof) { + Formula formula = null; + if (formula == null) { + Term term = proof.getResult(); + formula = formulaCreator.encapsulate(formulaCreator.getFormulaType(term), term); + } + return formula; + } + + private static class Frame { + final Proof proof; + int numChildren; + boolean visited; + + Frame(Proof pProof) { + proof = pProof; + visited = false; + } + } } diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java index 662f066cdf..1db287a8a7 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java @@ -10,17 +10,24 @@ package org.sosy_lab.java_smt.solvers.cvc5; +import static com.google.common.truth.Truth.assertThat; + import io.github.cvc5.CVC5ApiException; +import io.github.cvc5.Kind; +import io.github.cvc5.Proof; import io.github.cvc5.Solver; +import io.github.cvc5.Sort; +import io.github.cvc5.Term; +import io.github.cvc5.TermManager; import org.junit.AssumptionViolatedException; import org.junit.Before; import org.junit.BeforeClass; -import org.junit.Ignore; +import org.junit.Test; import org.sosy_lab.common.NativeLibraries; @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) -@Ignore public class CVC5ProofsTest { + @BeforeClass public static void loadCVC5() { try { @@ -30,22 +37,27 @@ public static void loadCVC5() { } } + private static TermManager tm; + private static Sort booleanSort; private Solver solver; @Before public void init() throws CVC5ApiException { + tm = new TermManager(); + booleanSort = tm.getBooleanSort(); solver = createEnvironment(); } private static Solver createEnvironment() throws CVC5ApiException { - Solver newSolver = new Solver(); + + Solver newSolver = new Solver(tm); newSolver.setLogic("ALL"); // options newSolver.setOption("incremental", "true"); newSolver.setOption("produce-models", "true"); newSolver.setOption("finite-model-find", "true"); - newSolver.setOption("sets-ext", "true"); + // newSolver.setOption("sets-ext", "true"); newSolver.setOption("output-language", "smtlib2"); newSolver.setOption("strings-exp", "true"); newSolver.setOption("produce-proofs", "true"); @@ -53,4 +65,78 @@ private static Solver createEnvironment() throws CVC5ApiException { return newSolver; } + private void processProof(Proof proof, int depth, int childNumber) throws CVC5ApiException { + String indent = " ".repeat(depth); // Indentation for readability + + System.out.println(indent + "Proof " + childNumber + ":"); + System.out.println(indent + " Result: " + proof.getResult()); + System.out.println(indent + " Rule: " + proof.getRule()); + System.out.println(indent + " Num args: " + proof.getArguments().length); + + // Display arguments + for (int j = 0; j < proof.getArguments().length; j++) { + System.out.println(indent + " Arg " + j + ": " + proof.getArguments()[j]); + } + + Proof[] proofChildren = proof.getChildren(); + System.out.println(indent + " Proof children length: " + proofChildren.length); + + for (int i = 0; i < proofChildren.length; i++) { + System.out.println(indent + " Child " + (i + 1) + " of Proof " + childNumber + ":"); + processProof(proofChildren[i], depth + 1, i + 1); + } + } + + @Test + public void proofTest() throws CVC5ApiException { + // (declare-fun q1 () Bool) + // (declare-fun q2 () Bool) + // (assert (or (not q1) q2)) + // (assert q1) + // (assert (not q2)) + Sort booleanSort = tm.getBooleanSort(); + Term q1 = solver.declareFun("q1", new Sort[] {}, booleanSort); + Term q2 = solver.declareFun("q2", new Sort[] {}, booleanSort); + + solver.assertFormula(tm.mkTerm(Kind.OR, (tm.mkTerm(Kind.NOT, q1)), q2)); + solver.assertFormula(q1); + solver.assertFormula(tm.mkTerm(Kind.NOT, q2)); + + assertThat(solver.checkSat().isUnsat()).isTrue(); + + Proof[] proof = solver.getProof(); + + System.out.println("Proof length: " + proof.length); + + // Process each proof in the array + for (int i = 0; i < proof.length; i++) { + processProof(proof[i], 0, i + 1); + } + } + + @Test + public void cvc5ProofToStringTest() { + // (declare-fun q1 () Bool) + // (declare-fun q2 () Bool) + // (assert (or (not q1) q2)) + // (assert q1) + // (assert (not q2)) + Sort booleanSort = tm.getBooleanSort(); + Term q1 = solver.declareFun("q1", new Sort[] {}, booleanSort); + Term q2 = solver.declareFun("q2", new Sort[] {}, booleanSort); + + solver.assertFormula(tm.mkTerm(Kind.OR, (tm.mkTerm(Kind.NOT, q1)), q2)); + solver.assertFormula(q1); + solver.assertFormula(tm.mkTerm(Kind.NOT, q2)); + + assertThat(solver.checkSat().isUnsat()).isTrue(); + + Proof[] proof = solver.getProof(); + + System.out.println("Proof length: " + proof.length); + + for (Proof p : proof) { + System.out.println(solver.proofToString(p)); + } + } } From c1eef9f1861e92fafb6dab38de6199e2827fa1fb Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 21 Mar 2025 20:26:08 +0100 Subject: [PATCH 025/132] CVC5: Added test for `getProof` --- .../solvers/cvc5/CVC5AbstractProver.java | 17 +++++ .../solvers/cvc5/CVC5ProofProcessor.java | 5 +- .../java_smt/solvers/cvc5/CVC5ProofsTest.java | 66 +++++++++++++++++-- .../solvers/mathsat5/Mathsat5NativeApi.java | 4 +- 4 files changed, 82 insertions(+), 10 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java index d2292667c1..ef87b21d6e 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java @@ -14,6 +14,7 @@ import com.google.common.collect.ImmutableMap; import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.github.cvc5.CVC5ApiException; +import io.github.cvc5.Proof; import io.github.cvc5.Result; import io.github.cvc5.Solver; import io.github.cvc5.Term; @@ -36,6 +37,7 @@ import org.sosy_lab.java_smt.api.Model.ValueAssignment; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; +import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.AbstractProverWithAllSat; abstract class CVC5AbstractProver extends AbstractProverWithAllSat { @@ -83,6 +85,10 @@ protected void setSolverOptions( if (pOptions.contains(ProverOptions.GENERATE_UNSAT_CORE)) { pSolver.setOption("produce-unsat-cores", "true"); } + if (pOptions.contains(ProverOptions.GENERATE_PROOFS)) { + pSolver.setOption("produce-proofs", "true"); + System.out.println("proofs enabled"); + } pSolver.setOption("produce-assertions", "true"); pSolver.setOption("dump-models", "true"); pSolver.setOption("output-language", "smt2"); @@ -235,6 +241,17 @@ public Optional> unsatCoreOverAssumptions( throw new UnsupportedOperationException(); } + @Override + public ProofNode getProof() { + Proof proof = solver.getProof()[0]; + CVC5ProofProcessor pp = new CVC5ProofProcessor(creator, this); + try { + return pp.fromCVC5Proof(proof); + } catch (CVC5ApiException pE) { + throw new RuntimeException(pE); + } + } + @Override public void close() { if (!closed) { diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java index 7b785a4748..337d72d351 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java @@ -21,13 +21,10 @@ import org.sosy_lab.java_smt.api.proofs.ProofRule; public class CVC5ProofProcessor { - private final CVC5SolverContext context; private final CVC5FormulaCreator formulaCreator; private final CVC5AbstractProver prover; - CVC5ProofProcessor( - CVC5SolverContext ctx, CVC5FormulaCreator creator, CVC5AbstractProver pProver) { - context = ctx; + CVC5ProofProcessor(CVC5FormulaCreator creator, CVC5AbstractProver pProver) { formulaCreator = creator; prover = pProver; } diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java index 1db287a8a7..02ddca50f6 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java @@ -11,6 +11,7 @@ package org.sosy_lab.java_smt.solvers.cvc5; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertTrue; import io.github.cvc5.CVC5ApiException; import io.github.cvc5.Kind; @@ -19,11 +20,25 @@ import io.github.cvc5.Sort; import io.github.cvc5.Term; import io.github.cvc5.TermManager; +import java.util.Set; import org.junit.AssumptionViolatedException; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.sosy_lab.common.NativeLibraries; +import org.sosy_lab.common.ShutdownManager; +import org.sosy_lab.common.configuration.Configuration; +import org.sosy_lab.common.log.BasicLogManager; +import org.sosy_lab.common.log.LogManager; +import org.sosy_lab.java_smt.api.BooleanFormula; +import org.sosy_lab.java_smt.api.FloatingPointRoundingMode; +import org.sosy_lab.java_smt.api.ProverEnvironment; +import org.sosy_lab.java_smt.api.SolverContext; +import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; +import org.sosy_lab.java_smt.api.SolverException; +import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.basicimpl.AbstractNumeralFormulaManager.NonLinearArithmetic; + @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) public class CVC5ProofsTest { @@ -40,6 +55,9 @@ public static void loadCVC5() { private static TermManager tm; private static Sort booleanSort; private Solver solver; + private SolverContext context; + private CVC5FormulaManager mgr; + private CVC5BooleanFormulaManager bmgr; @Before public void init() throws CVC5ApiException { @@ -48,6 +66,25 @@ public void init() throws CVC5ApiException { solver = createEnvironment(); } + @Before + public void setUpSolver() throws Exception { + Configuration config = Configuration.defaultConfiguration(); + LogManager logger = BasicLogManager.create(config); + ShutdownManager shutdown = ShutdownManager.create(); + + context = + CVC5SolverContext.create( + logger, + config, + shutdown.getNotifier(), + 42, // random seed value + NonLinearArithmetic.USE, + FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN, + NativeLibraries::loadLibrary); + mgr = (CVC5FormulaManager) context.getFormulaManager(); + bmgr = (CVC5BooleanFormulaManager) mgr.getBooleanFormulaManager(); + } + private static Solver createEnvironment() throws CVC5ApiException { Solver newSolver = new Solver(tm); @@ -65,6 +102,27 @@ private static Solver createEnvironment() throws CVC5ApiException { return newSolver; } + @Test + public void getProofTest() { + // example from the 2022 RESOLUTE paper + BooleanFormula q1 = bmgr.makeVariable("q1"); + BooleanFormula q2 = bmgr.makeVariable("q2"); + + ProverEnvironment prover = context.newProverEnvironment(ProverOptions.GENERATE_PROOFS); + try { + prover.addConstraint(bmgr.or(bmgr.not(q1), q2)); + prover.addConstraint(q1); + prover.addConstraint(bmgr.not(q2)); + assertTrue(prover.isUnsat()); + + ProofNode proof = prover.getProof(); + assertThat(proof).isNotNull(); + } catch (SolverException | InterruptedException pE) { + throw new RuntimeException(pE); + } + + } + private void processProof(Proof proof, int depth, int childNumber) throws CVC5ApiException { String indent = " ".repeat(depth); // Indentation for readability @@ -95,8 +153,8 @@ public void proofTest() throws CVC5ApiException { // (assert q1) // (assert (not q2)) Sort booleanSort = tm.getBooleanSort(); - Term q1 = solver.declareFun("q1", new Sort[] {}, booleanSort); - Term q2 = solver.declareFun("q2", new Sort[] {}, booleanSort); + Term q1 = solver.declareFun("q1", new Sort[]{}, booleanSort); + Term q2 = solver.declareFun("q2", new Sort[]{}, booleanSort); solver.assertFormula(tm.mkTerm(Kind.OR, (tm.mkTerm(Kind.NOT, q1)), q2)); solver.assertFormula(q1); @@ -122,8 +180,8 @@ public void cvc5ProofToStringTest() { // (assert q1) // (assert (not q2)) Sort booleanSort = tm.getBooleanSort(); - Term q1 = solver.declareFun("q1", new Sort[] {}, booleanSort); - Term q2 = solver.declareFun("q2", new Sort[] {}, booleanSort); + Term q1 = solver.declareFun("q1", new Sort[]{}, booleanSort); + Term q2 = solver.declareFun("q2", new Sort[]{}, booleanSort); solver.assertFormula(tm.mkTerm(Kind.OR, (tm.mkTerm(Kind.NOT, q1)), q2)); solver.assertFormula(q1); diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApi.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApi.java index 619041ac5a..d6f97ce58a 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApi.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApi.java @@ -814,13 +814,13 @@ private static native int msat_all_sat( public static native long msat_proof_id(long proof); - public static native int msat_proof_is_term(long proof); + public static native boolean msat_proof_is_term(long proof); public static native long msat_proof_get_term(long proof); public static native String msat_proof_get_name(long proof); - public static native long msat_proof_get_arity(long proof); + public static native int msat_proof_get_arity(long proof); public static native long msat_proof_get_child(long proof, long index); From 746d6537cc4c2d9e63b621ef4e43c060344eab4d Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sun, 23 Mar 2025 10:42:36 +0100 Subject: [PATCH 026/132] Z3: Documentation on the proof format transformation. --- .../z3/Z3ToResoluteProofConverter.java | 82 ++++++------------- 1 file changed, 27 insertions(+), 55 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java index 17f7c8e3a2..022b021674 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java @@ -30,7 +30,24 @@ import org.sosy_lab.java_smt.api.visitors.BooleanFormulaVisitor; import org.sosy_lab.java_smt.api.visitors.TraversalProcess; -/** Converts a Z3 proof to a RESOLUTE proof. */ +/** + * Converts a Z3 proof into a format based on the RESOLUTE proof format. + *

+ * The RESOLUTE format is a low-level proof format used by SMTInterpol. It exclusively relies on + * the resolution rule, with multiple axioms defined to support various theories. These axioms + * serve as the leaf nodes in the proof DAG. + *

+ * The strategy used is to transform each result from a Z3 proof into corresponding resolution + * proof nodes, aiming to maintain the formulas used as arguments for the Z3 proof rule as well + * as the result. Depending on the rule, the number of nodes may remain the same (e.g., for modus ponens) or increase + * (e.g., for transitivity star). For the transitivity star rule, the sub-proof grows + * approximately 2n-1 times, where n is the number of nodes in the + * sub-proof. + *

+ * + * @see Z3ProofRule for the list of Z3 proof rules. + * @see org.sosy_lab.java_smt.ResProofRule for the list of RESOLUTE axioms. + **/ @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access", "ModifiedButNotUsed"}) public class Z3ToResoluteProofConverter { @@ -45,58 +62,6 @@ public class Z3ToResoluteProofConverter { private static final Map ruleMapping = new HashMap<>(); - /* - static { - ruleMapping.put(Z3ProofRule.UNDEF, ResAxiom.ORACLE); - ruleMapping.put(Z3ProofRule.TRUE, ResAxiom.TRUE_POSITIVE); - ruleMapping.put(Z3ProofRule.ASSERTED, ResAxiom.ASSUME); - ruleMapping.put(Z3ProofRule.GOAL, ResAxiom.ASSUME); - ruleMapping.put(Z3ProofRule.REFLEXIVITY, ResAxiom.REFLEXIVITY); - ruleMapping.put(Z3ProofRule.SYMMETRY, ResAxiom.SYMMETRY); - ruleMapping.put(Z3ProofRule.TRANSITIVITY, ResAxiom.TRANSITIVITY); - ruleMapping.put(Z3ProofRule.TRANSITIVITY_STAR, ResAxiom.TRANSITIVITY_STAR); - ruleMapping.put(Z3ProofRule.MONOTONICITY, ResAxiom.MONOTONICITY); - ruleMapping.put(Z3ProofRule.QUANT_INTRO, ResAxiom.QUANT_INTRO); - ruleMapping.put(Z3ProofRule.BIND, ResAxiom.BIND); - ruleMapping.put(Z3ProofRule.DISTRIBUTIVITY, ResAxiom.DISTRIBUTIVITY); - ruleMapping.put(Z3ProofRule.AND_ELIM, ResAxiom.AND_POSITIVE); - ruleMapping.put(Z3ProofRule.NOT_OR_ELIM, ResAxiom.NOT_NEGATIVE); - ruleMapping.put(Z3ProofRule.REWRITE, ResAxiom.REWRITE); - ruleMapping.put(Z3ProofRule.REWRITE_STAR, ResAxiom.REWRITE_STAR); - ruleMapping.put(Z3ProofRule.PULL_QUANT, ResAxiom.PULL_QUANT); - ruleMapping.put(Z3ProofRule.PUSH_QUANT, ResAxiom.PUSH_QUANT); - ruleMapping.put(Z3ProofRule.ELIM_UNUSED_VARS, ResAxiom.ELIM_UNUSED_VARS); - ruleMapping.put(Z3ProofRule.DER, ResAxiom.DER); - ruleMapping.put(Z3ProofRule.QUANT_INST, ResAxiom.QUANT_INST); - ruleMapping.put(Z3ProofRule.HYPOTHESIS, ResAxiom.HYPOTHESIS); - ruleMapping.put(Z3ProofRule.LEMMA, ResAxiom.LEMMA); - ruleMapping.put(Z3ProofRule.UNIT_RESOLUTION, ResAxiom.UNIT_RESOLUTION); - ruleMapping.put(Z3ProofRule.IFF_TRUE, ResAxiom.IFF_TRUE); - ruleMapping.put(Z3ProofRule.IFF_FALSE, ResAxiom.IFF_FALSE); - ruleMapping.put(Z3ProofRule.COMMUTATIVITY, ResAxiom.COMMUTATIVITY); - ruleMapping.put(Z3ProofRule.DEF_AXIOM, ResAxiom.DEF_AXIOM); - ruleMapping.put(Z3ProofRule.ASSUMPTION_ADD, ResAxiom.ASSUMPTION_ADD); - ruleMapping.put(Z3ProofRule.LEMMA_ADD, ResAxiom.LEMMA_ADD); - ruleMapping.put(Z3ProofRule.REDUNDANT_DEL, ResAxiom.REDUNDANT_DEL); - ruleMapping.put(Z3ProofRule.CLAUSE_TRAIL, ResAxiom.CLAUSE_TRAIL); - ruleMapping.put(Z3ProofRule.DEF_INTRO, ResAxiom.DEF_INTRO); - ruleMapping.put(Z3ProofRule.APPLY_DEF, ResAxiom.APPLY_DEF); - ruleMapping.put(Z3ProofRule.IFF_OEQ, ResAxiom.IFF_OEQ); - ruleMapping.put(Z3ProofRule.NNF_POS, ResAxiom.NNF_POS); - ruleMapping.put(Z3ProofRule.NNF_NEG, ResAxiom.NNF_NEG); - ruleMapping.put(Z3ProofRule.SKOLEMIZE, ResAxiom.SKOLEMIZE); - ruleMapping.put(Z3ProofRule.MODUS_PONENS_OEQ, ResAxiom.MODUS_PONENS_OEQ); - ruleMapping.put(Z3ProofRule.TH_LEMMA, ResAxiom.TH_LEMMA); - ruleMapping.put(Z3ProofRule.HYPER_RESOLVE, ResAxiom.HYPER_RESOLVE); - } - - */ - - /* - public static ResAxiom mapRule(Z3ProofRule z3Rule) { - return ruleMapping.getOrDefault(z3Rule, ResAxiom.OPERATION); - } - */ static ResolutionProofDag convertToResolutionProofDag(Z3ProofNode[] z3ProofNodes) { ResolutionProofDag dag = new ResolutionProofDag(); @@ -115,7 +80,7 @@ static ResolutionProofDag convertToResolutionProofDag(Z3ProofNode[] z3ProofNodes return dag; } - private static class EquivalenceExtractor implements BooleanFormulaVisitor { + private static class ExtractorVisitor implements BooleanFormulaVisitor { private final List equivalenceOperands = new ArrayList<>(); public List getEquivalenceOperands() { @@ -187,11 +152,18 @@ public TraversalProcess visitAtom( } public List extractEquivalenceOperands(BooleanFormula formula) { - EquivalenceExtractor extractor = new EquivalenceExtractor(); + ExtractorVisitor extractor = new ExtractorVisitor(); bfm.visitRecursively(formula, extractor); return extractor.getEquivalenceOperands(); } + /** + * Converts a {@link Z3ProofNode} into either a {@link ResolutionProofNode} or + * a {@link SourceProofNode}, depending on its rule. + * + * @param node the {@link Z3ProofNode} to convert + * @return the resulting {@link ProofNode} + */ ProofNode handleNode(Z3ProofNode node) { Z3ProofRule rule = (Z3ProofRule) node.getRule(); From 34c9a7e1fcd714a8faae80561203d73d77882d24 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sun, 23 Mar 2025 11:46:51 +0100 Subject: [PATCH 027/132] `ProofFactory` no longer public --- src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java index 09188ef70a..51123ff600 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java @@ -15,12 +15,12 @@ import org.sosy_lab.java_smt.SourceProofNode; import org.sosy_lab.java_smt.api.Formula; -public class ProofFactory { - public static ProofNode createSourceNode(ResAxiom rule, Formula formula) { + class ProofFactory { + static ProofNode createSourceNode(ResAxiom rule, Formula formula) { return new SourceProofNode(rule, formula); } - public static ProofNode createResolutionNode(Formula formula, Formula pivot) { + static ProofNode createResolutionNode(Formula formula, Formula pivot) { return new ResolutionProofNode(formula, pivot); } } From 5aeb6446b8a7071da02776f35efb9c3815ced093 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sun, 23 Mar 2025 11:49:20 +0100 Subject: [PATCH 028/132] CVC5: fixed some proofs test issues --- src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java index 02ddca50f6..ca3754acb4 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java @@ -21,6 +21,7 @@ import io.github.cvc5.Term; import io.github.cvc5.TermManager; import java.util.Set; +import org.junit.After; import org.junit.AssumptionViolatedException; import org.junit.Before; import org.junit.BeforeClass; @@ -85,6 +86,12 @@ public void setUpSolver() throws Exception { bmgr = (CVC5BooleanFormulaManager) mgr.getBooleanFormulaManager(); } + @After + public void freeEnvironment() { + solver.deletePointer(); + tm.deletePointer(); + } + private static Solver createEnvironment() throws CVC5ApiException { Solver newSolver = new Solver(tm); From f7c568228c1df866bbde35fdaa9496825486a58f Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sun, 23 Mar 2025 15:12:17 +0100 Subject: [PATCH 029/132] CVC5: `getProof` handles the case where no proof is available --- .../java_smt/solvers/cvc5/CVC5AbstractProver.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java index ef87b21d6e..39b8e62c48 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java @@ -87,7 +87,6 @@ protected void setSolverOptions( } if (pOptions.contains(ProverOptions.GENERATE_PROOFS)) { pSolver.setOption("produce-proofs", "true"); - System.out.println("proofs enabled"); } pSolver.setOption("produce-assertions", "true"); pSolver.setOption("dump-models", "true"); @@ -243,10 +242,15 @@ public Optional> unsatCoreOverAssumptions( @Override public ProofNode getProof() { - Proof proof = solver.getProof()[0]; + + Proof[] proofs = solver.getProof(); + if (proofs == null || proofs.length == 0) { + throw new IllegalStateException("No proof available"); + } + CVC5ProofProcessor pp = new CVC5ProofProcessor(creator, this); try { - return pp.fromCVC5Proof(proof); + return pp.fromCVC5Proof(proofs[0]); } catch (CVC5ApiException pE) { throw new RuntimeException(pE); } From 4b35856495890aa00ed24cc16f5ebc7529f3f98c Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 24 Mar 2025 09:48:57 +0100 Subject: [PATCH 030/132] Refactoring some of the proof related classes --- .../java_smt/api/proofs/ProofFactory.java | 51 +++++++++++- .../java_smt/api/proofs/ProofFrame.java | 43 ++++++++++ .../solvers/mathsat5/Mathsat5NativeApi.java | 18 ---- .../solvers/mathsat5/Mathsat5ProofNode.java | 83 ++++++++++++++++++- 4 files changed, 175 insertions(+), 20 deletions(-) create mode 100644 src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java index 51123ff600..948e167f4e 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java @@ -10,12 +10,61 @@ package org.sosy_lab.java_smt.api.proofs; + import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.ResolutionProofNode; import org.sosy_lab.java_smt.SourceProofNode; import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.ProverEnvironment; +import org.sosy_lab.java_smt.basicimpl.FormulaCreator; +import org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5ProofNode; + +class ProofFactory { + + private final FormulaCreator formulaCreator; + private final ProverEnvironment prover; + private final Solvers solver; + + enum Solvers { + OPENSMT, + MATHSAT5, + SMTINTERPOL, + Z3, + PRINCESS, + BOOLECTOR, + CVC4, + CVC5, + YICES2, + BITWUZLA + } + + ProofFactory( + FormulaCreator pCreator, ProverEnvironment pProver, + ProofFactory.Solvers pSolver) { + formulaCreator = pCreator; + prover = pProver; + solver = pSolver; + } + + ProofNode createProofNode(T proof) { + return createProofNode0(proof); + } + + ProofNode createProofNode0(T proof) { + switch (solver) { + case MATHSAT5: + return Mathsat5ProofNode.fromMsatProof(prover, (long) proof); + case CVC5: + return null; + default: + throw new UnsupportedOperationException("Unsupported solver: " + solver); + } + } + + static ProofNode createRresoluteNode() { + return null; + } - class ProofFactory { static ProofNode createSourceNode(ResAxiom rule, Formula formula) { return new SourceProofNode(rule, formula); } diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java b/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java new file mode 100644 index 0000000000..2c8a5ec7d3 --- /dev/null +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java @@ -0,0 +1,43 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.api.proofs; + +public class ProofFrame { + final T proof; + int numArgs; + boolean visited; + + protected ProofFrame(T proof) { + this.proof = proof; + this.visited = false; + } + + public T getProof() { + return proof; + } + + public int getNumArgs() { + return numArgs; + } + + public boolean getVisited() { + return visited; + } + + public void setVisited(boolean visited) { + this.visited = visited; + } + + public void setNumArgs(int numArgs) { + this.numArgs = numArgs; + } + +} diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApi.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApi.java index 682204574a..f0862ddaf8 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApi.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApi.java @@ -806,24 +806,6 @@ private static native int msat_all_sat( public static native long[] msat_get_unsat_core(long e); - public static native long msat_get_proof_manager(long env); - - public static native void msat_destroy_proof_manager(long proofManager); - - public static native long msat_get_proof(long proofManager); - - public static native long msat_proof_id(long proof); - - public static native boolean msat_proof_is_term(long proof); - - public static native long msat_proof_get_term(long proof); - - public static native String msat_proof_get_name(long proof); - - public static native int msat_proof_get_arity(long proof); - - public static native long msat_proof_get_child(long proof, long index); - /* * Special functions */ diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java index 866789c571..06682d05b5 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java @@ -10,17 +10,98 @@ package org.sosy_lab.java_smt.solvers.mathsat5; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_get_arity; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_get_child; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_get_name; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_get_term; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_is_term; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.Nullable; import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.ProverEnvironment; +import org.sosy_lab.java_smt.api.proofs.ProofFrame; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; +import org.sosy_lab.java_smt.basicimpl.FormulaCreator; + public class Mathsat5ProofNode extends AbstractProofNode { - protected Mathsat5ProofNode(ProofRule rule, Formula formula) { + public Mathsat5ProofNode(ProofRule rule, Formula formula) { super(rule, formula); } + protected static class MsatProofFrame extends ProofFrame { + public MsatProofFrame(Long proof) { + super(proof); + } + } + + static public Mathsat5ProofNode fromMsatProof(ProverEnvironment pProver, long rootProof) { + final Mathsat5SolverContext context = ((Mathsat5TheoremProver) pProver).context; + final long curEnv = ((Mathsat5TheoremProver) pProver).curEnv; + final Mathsat5FormulaCreator formulaCreator = ((Mathsat5TheoremProver) pProver).creator; + + { + Deque stack = new ArrayDeque<>(); + Map computed = new HashMap<>(); + + stack.push(new MsatProofFrame(rootProof)); + + while (!stack.isEmpty()) { + MsatProofFrame frame = stack.peek(); + + if (!frame.getVisited()) { + frame.setNumArgs(msat_proof_get_arity(frame.getProof())); + frame.setVisited(true); + // Push children first so that the leaves are processed first. + for (int i = 0; i < frame.getNumArgs(); i++) { + long child = msat_proof_get_child(frame.getProof(), i); + if (!computed.containsKey(child)) { + stack.push(new MsatProofFrame(child)); + } + } + } else { + // Process the node after all its children have been processed. This should help to + // recreate the formula for the node correctly. + stack.pop(); + + // Generate the formula and proof rule. + Formula formula = generateFormula(frame.getProof(), (Mathsat5TheoremProver) pProver); + Mathsat5ProofRule proofRule = new Mathsat5ProofRule(msat_proof_get_name(frame.getProof())); + Mathsat5ProofNode node = new Mathsat5ProofNode(proofRule, formula); + + // Retrieve computed child nodes and attach them. + for (int i = 0; i < frame.getNumArgs(); i++) { + long child = msat_proof_get_child(frame.getProof(), i); + Mathsat5ProofNode childNode = computed.get(child); + if (childNode != null) { + node.addChild(childNode); + } + } + computed.put(frame.getProof(), node); + } + } + return computed.get(rootProof); + } + } + + @Nullable + private static Formula generateFormula(long proof, Mathsat5TheoremProver prover){ + Mathsat5FormulaCreator formulaCreator = prover.creator; + Formula formula = null; + if (msat_proof_is_term(proof)) { + long proofTerm = msat_proof_get_term(proof); + formula = formulaCreator.encapsulate(formulaCreator.getFormulaType(proofTerm), proofTerm); + } + return formula; + } + public String asString() { return asString(0); } From 7dce94854d78c24e4c8166d674ca99bce27d6ea3 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 24 Mar 2025 11:59:42 +0100 Subject: [PATCH 031/132] Proofs: Refactoring to have fewer classes and repeated code. --- src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java | 2 +- src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java | 2 +- .../java_smt/solvers/mathsat5/Mathsat5TheoremProver.java | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java index 948e167f4e..a85da5cbbc 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java @@ -19,7 +19,7 @@ import org.sosy_lab.java_smt.basicimpl.FormulaCreator; import org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5ProofNode; -class ProofFactory { +public class ProofFactory { private final FormulaCreator formulaCreator; private final ProverEnvironment prover; diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java b/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java index 2c8a5ec7d3..50012f64cb 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java @@ -10,7 +10,7 @@ package org.sosy_lab.java_smt.api.proofs; -public class ProofFrame { +public abstract class ProofFrame { final T proof; int numArgs; boolean visited; diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java index 21d692561e..604ade74df 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java @@ -23,6 +23,7 @@ import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.ProofFactory; class Mathsat5TheoremProver extends Mathsat5AbstractProver implements ProverEnvironment { @@ -52,6 +53,7 @@ protected Void addConstraintImpl(BooleanFormula constraint) throws InterruptedEx public ProofNode getProof() { ProofNode pn; long pm = msat_get_proof_manager(curEnv); + //ProofFactory proofFactory = new ProofFactory(); Mathsat5ProofProcessor pp = new Mathsat5ProofProcessor(context, curEnv, creator, this); pn = pp.fromMsatProof(msat_get_proof(pm)); msat_destroy_proof_manager(pm); From 4af588c930f234c94fe24adb2a676898d25328e8 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 24 Mar 2025 12:00:29 +0100 Subject: [PATCH 032/132] Extended documentation regarding proofs format --- src/org/sosy_lab/java_smt/ResProofRule.java | 6 +- .../sosy_lab/java_smt/ResolutionProofDag.java | 64 +++---------------- .../z3/Z3ToResoluteProofConverter.java | 10 ++- 3 files changed, 23 insertions(+), 57 deletions(-) diff --git a/src/org/sosy_lab/java_smt/ResProofRule.java b/src/org/sosy_lab/java_smt/ResProofRule.java index a2603b22e4..e15298c6af 100644 --- a/src/org/sosy_lab/java_smt/ResProofRule.java +++ b/src/org/sosy_lab/java_smt/ResProofRule.java @@ -13,7 +13,11 @@ import org.sosy_lab.java_smt.api.proofs.ProofRule; /** - * A proof rule in the proof DAG of the internal proof format of JavaSMT. + * A proof rule in the proof DAG of the proof format RESOLUTE used by SMTInterpol. + * See: ... + * + * The conversion from other formats to RESOLUTE appears to be simple and as such, it is a good + * candidate for a common proof format. * * @author Gabriel Carpio */ diff --git a/src/org/sosy_lab/java_smt/ResolutionProofDag.java b/src/org/sosy_lab/java_smt/ResolutionProofDag.java index 177e531be4..0074743e08 100644 --- a/src/org/sosy_lab/java_smt/ResolutionProofDag.java +++ b/src/org/sosy_lab/java_smt/ResolutionProofDag.java @@ -12,61 +12,15 @@ import org.sosy_lab.java_smt.basicimpl.AbstractProofDag; +/** + * This class represents a resolution proof DAG. Its nodes might be of the type + * {@link SourceProofNode} or {@link ResolutionProofNode}. It is used to represent proofs based on + * the RESOLUTE proof format from SMTInterpol. + * + * @see ResProofRule + */ @SuppressWarnings("all") public class ResolutionProofDag extends AbstractProofDag { - - /* - public ResolutionProofDAG() { - super(); - } - - - public static ResolutionProofDAG fromTerm( - Term proof, FormulaManager pManager, - Map pAnnotatedTerms) { - - // Use our new ProofTermParser to convert the proof term to a ResolutionProofDAG - return ProofTermParser.convert(proof, pManager, pAnnotatedTerms); - } - - private static void traverseTerm(Term term, ResolutionProofDAG dag, ProofNode parentClause) { - if (term instanceof AnnotatedTerm) { - AnnotatedTerm annotatedTerm = (AnnotatedTerm) term; - for (Annotation annotation : annotatedTerm.getAnnotations()) { - /* - if (annotation.getKey().equals(ProofConstants.ANNOTKEY_PROVES)) { - //ProofNode clause = annotation.getValue().toString(); - if (parentClause != null) { - dag.addEdge(parentClause, clause); - } else { - dag.addNode(clause); - } - for (Term subTerm : annotatedTerm.getSubterms()) { - traverseTerm(subTerm, dag, clause); - } - } - - - } - } - } - - - - @Override - public void addNode(ProofNode node) { - super.addNode(node); - } - - @Override - public ProofNode getNode(int nodeId) { - return super.getNode(nodeId); - } - - @Override - public void addEdge(int parentNodeId, int childNodeId) { - super.addEdge(parentNodeId, childNodeId); - } - - */ + //Work in progress. The functionality of producing just nodes should be provided first. + //The idea is to provide extended functionality (by providng a set of edges for example). } diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java index 022b021674..c0ffe1ba02 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java @@ -62,7 +62,12 @@ public class Z3ToResoluteProofConverter { private static final Map ruleMapping = new HashMap<>(); - + /** + * This method converts a set of Z3ProofNodes into a {@link ResolutionProofDag}. + * + * @param z3ProofNodes + * @return {@link ResolutionProofDag} + */ static ResolutionProofDag convertToResolutionProofDag(Z3ProofNode[] z3ProofNodes) { ResolutionProofDag dag = new ResolutionProofDag(); @@ -80,6 +85,7 @@ static ResolutionProofDag convertToResolutionProofDag(Z3ProofNode[] z3ProofNodes return dag; } + //This should help extract parts of a formula to better transform proof rules. private static class ExtractorVisitor implements BooleanFormulaVisitor { private final List equivalenceOperands = new ArrayList<>(); @@ -299,6 +305,7 @@ ProofNode handleNode(Z3ProofNode node) { } } + ProofNode handleTrue(Z3ProofNode node) { BooleanFormula formula = (BooleanFormula) node.getFormula(); SourceProofNode pn = new SourceProofNode(ResAxiom.TRUE_POSITIVE, formula); @@ -537,6 +544,7 @@ ProofNode handleDefault(Z3ProofNode node) { return null; } + //This is for debugging purposes. void printProof(ProofNode node, int indentLevel) { String indent = " ".repeat(indentLevel); From 1440715f07a6512cac95a84251cf629de041c456 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 24 Mar 2025 12:01:56 +0100 Subject: [PATCH 033/132] Checkstyle --- src/org/sosy_lab/java_smt/ResProofRule.java | 6 ++-- .../sosy_lab/java_smt/ResolutionProofDag.java | 10 +++--- .../java_smt/api/proofs/ProofFactory.java | 4 +-- .../java_smt/api/proofs/ProofFrame.java | 31 +++++++++--------- .../solvers/cvc5/CVC5AbstractProver.java | 2 +- .../java_smt/solvers/cvc5/CVC5ProofsTest.java | 11 +++---- .../solvers/mathsat5/Mathsat5ProofNode.java | 25 +++++++-------- .../mathsat5/Mathsat5TheoremProver.java | 3 +- .../z3/Z3ToResoluteProofConverter.java | 32 ++++++++----------- 9 files changed, 57 insertions(+), 67 deletions(-) diff --git a/src/org/sosy_lab/java_smt/ResProofRule.java b/src/org/sosy_lab/java_smt/ResProofRule.java index e15298c6af..07b0e6004e 100644 --- a/src/org/sosy_lab/java_smt/ResProofRule.java +++ b/src/org/sosy_lab/java_smt/ResProofRule.java @@ -13,10 +13,10 @@ import org.sosy_lab.java_smt.api.proofs.ProofRule; /** - * A proof rule in the proof DAG of the proof format RESOLUTE used by SMTInterpol. - * See: ... + * A proof rule in the proof DAG of the proof format RESOLUTE used by SMTInterpol. See: ... * - * The conversion from other formats to RESOLUTE appears to be simple and as such, it is a good + *

The conversion from other formats to RESOLUTE appears to be simple and as such, it is a good * candidate for a common proof format. * * @author Gabriel Carpio diff --git a/src/org/sosy_lab/java_smt/ResolutionProofDag.java b/src/org/sosy_lab/java_smt/ResolutionProofDag.java index 0074743e08..8ae0e46f21 100644 --- a/src/org/sosy_lab/java_smt/ResolutionProofDag.java +++ b/src/org/sosy_lab/java_smt/ResolutionProofDag.java @@ -13,14 +13,14 @@ import org.sosy_lab.java_smt.basicimpl.AbstractProofDag; /** - * This class represents a resolution proof DAG. Its nodes might be of the type - * {@link SourceProofNode} or {@link ResolutionProofNode}. It is used to represent proofs based on - * the RESOLUTE proof format from SMTInterpol. + * This class represents a resolution proof DAG. Its nodes might be of the type {@link + * SourceProofNode} or {@link ResolutionProofNode}. It is used to represent proofs based on the + * RESOLUTE proof format from SMTInterpol. * * @see ResProofRule */ @SuppressWarnings("all") public class ResolutionProofDag extends AbstractProofDag { - //Work in progress. The functionality of producing just nodes should be provided first. - //The idea is to provide extended functionality (by providng a set of edges for example). + // Work in progress. The functionality of producing just nodes should be provided first. + // The idea is to provide extended functionality (by providng a set of edges for example). } diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java index a85da5cbbc..bbdd423b83 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java @@ -10,7 +10,6 @@ package org.sosy_lab.java_smt.api.proofs; - import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.ResolutionProofNode; import org.sosy_lab.java_smt.SourceProofNode; @@ -39,7 +38,8 @@ enum Solvers { } ProofFactory( - FormulaCreator pCreator, ProverEnvironment pProver, + FormulaCreator pCreator, + ProverEnvironment pProver, ProofFactory.Solvers pSolver) { formulaCreator = pCreator; prover = pProver; diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java b/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java index 50012f64cb..0720c52e9e 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java @@ -15,29 +15,28 @@ public abstract class ProofFrame { int numArgs; boolean visited; - protected ProofFrame(T proof) { + protected ProofFrame(T proof) { this.proof = proof; this.visited = false; } - public T getProof() { - return proof; - } + public T getProof() { + return proof; + } - public int getNumArgs() { + public int getNumArgs() { return numArgs; - } - - public boolean getVisited() { - return visited; - } + } - public void setVisited(boolean visited) { - this.visited = visited; - } + public boolean getVisited() { + return visited; + } - public void setNumArgs(int numArgs) { - this.numArgs = numArgs; - } + public void setVisited(boolean visited) { + this.visited = visited; + } + public void setNumArgs(int numArgs) { + this.numArgs = numArgs; + } } diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java index 39b8e62c48..34a0853b2e 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java @@ -86,7 +86,7 @@ protected void setSolverOptions( pSolver.setOption("produce-unsat-cores", "true"); } if (pOptions.contains(ProverOptions.GENERATE_PROOFS)) { - pSolver.setOption("produce-proofs", "true"); + pSolver.setOption("produce-proofs", "true"); } pSolver.setOption("produce-assertions", "true"); pSolver.setOption("dump-models", "true"); diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java index ca3754acb4..99bee76103 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java @@ -20,7 +20,6 @@ import io.github.cvc5.Sort; import io.github.cvc5.Term; import io.github.cvc5.TermManager; -import java.util.Set; import org.junit.After; import org.junit.AssumptionViolatedException; import org.junit.Before; @@ -40,7 +39,6 @@ import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.AbstractNumeralFormulaManager.NonLinearArithmetic; - @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) public class CVC5ProofsTest { @@ -127,7 +125,6 @@ public void getProofTest() { } catch (SolverException | InterruptedException pE) { throw new RuntimeException(pE); } - } private void processProof(Proof proof, int depth, int childNumber) throws CVC5ApiException { @@ -160,8 +157,8 @@ public void proofTest() throws CVC5ApiException { // (assert q1) // (assert (not q2)) Sort booleanSort = tm.getBooleanSort(); - Term q1 = solver.declareFun("q1", new Sort[]{}, booleanSort); - Term q2 = solver.declareFun("q2", new Sort[]{}, booleanSort); + Term q1 = solver.declareFun("q1", new Sort[] {}, booleanSort); + Term q2 = solver.declareFun("q2", new Sort[] {}, booleanSort); solver.assertFormula(tm.mkTerm(Kind.OR, (tm.mkTerm(Kind.NOT, q1)), q2)); solver.assertFormula(q1); @@ -187,8 +184,8 @@ public void cvc5ProofToStringTest() { // (assert q1) // (assert (not q2)) Sort booleanSort = tm.getBooleanSort(); - Term q1 = solver.declareFun("q1", new Sort[]{}, booleanSort); - Term q2 = solver.declareFun("q2", new Sort[]{}, booleanSort); + Term q1 = solver.declareFun("q1", new Sort[] {}, booleanSort); + Term q2 = solver.declareFun("q2", new Sort[] {}, booleanSort); solver.assertFormula(tm.mkTerm(Kind.OR, (tm.mkTerm(Kind.NOT, q1)), q2)); solver.assertFormula(q1); diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java index 06682d05b5..94a16679e5 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java @@ -27,8 +27,6 @@ import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; -import org.sosy_lab.java_smt.basicimpl.FormulaCreator; - public class Mathsat5ProofNode extends AbstractProofNode { @@ -42,7 +40,7 @@ public MsatProofFrame(Long proof) { } } - static public Mathsat5ProofNode fromMsatProof(ProverEnvironment pProver, long rootProof) { + public static Mathsat5ProofNode fromMsatProof(ProverEnvironment pProver, long rootProof) { final Mathsat5SolverContext context = ((Mathsat5TheoremProver) pProver).context; final long curEnv = ((Mathsat5TheoremProver) pProver).curEnv; final Mathsat5FormulaCreator formulaCreator = ((Mathsat5TheoremProver) pProver).creator; @@ -73,7 +71,8 @@ static public Mathsat5ProofNode fromMsatProof(ProverEnvironment pProver, long ro // Generate the formula and proof rule. Formula formula = generateFormula(frame.getProof(), (Mathsat5TheoremProver) pProver); - Mathsat5ProofRule proofRule = new Mathsat5ProofRule(msat_proof_get_name(frame.getProof())); + Mathsat5ProofRule proofRule = + new Mathsat5ProofRule(msat_proof_get_name(frame.getProof())); Mathsat5ProofNode node = new Mathsat5ProofNode(proofRule, formula); // Retrieve computed child nodes and attach them. @@ -91,16 +90,16 @@ static public Mathsat5ProofNode fromMsatProof(ProverEnvironment pProver, long ro } } - @Nullable - private static Formula generateFormula(long proof, Mathsat5TheoremProver prover){ - Mathsat5FormulaCreator formulaCreator = prover.creator; - Formula formula = null; - if (msat_proof_is_term(proof)) { - long proofTerm = msat_proof_get_term(proof); - formula = formulaCreator.encapsulate(formulaCreator.getFormulaType(proofTerm), proofTerm); - } - return formula; + @Nullable + private static Formula generateFormula(long proof, Mathsat5TheoremProver prover) { + Mathsat5FormulaCreator formulaCreator = prover.creator; + Formula formula = null; + if (msat_proof_is_term(proof)) { + long proofTerm = msat_proof_get_term(proof); + formula = formulaCreator.encapsulate(formulaCreator.getFormulaType(proofTerm), proofTerm); } + return formula; + } public String asString() { return asString(0); diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java index 604ade74df..94da0fbcf1 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java @@ -23,7 +23,6 @@ import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.proofs.ProofNode; -import org.sosy_lab.java_smt.api.proofs.ProofFactory; class Mathsat5TheoremProver extends Mathsat5AbstractProver implements ProverEnvironment { @@ -53,7 +52,7 @@ protected Void addConstraintImpl(BooleanFormula constraint) throws InterruptedEx public ProofNode getProof() { ProofNode pn; long pm = msat_get_proof_manager(curEnv); - //ProofFactory proofFactory = new ProofFactory(); + // ProofFactory proofFactory = new ProofFactory(); Mathsat5ProofProcessor pp = new Mathsat5ProofProcessor(context, curEnv, creator, this); pn = pp.fromMsatProof(msat_get_proof(pm)); msat_destroy_proof_manager(pm); diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java index c0ffe1ba02..3cc0e794c0 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java @@ -32,22 +32,19 @@ /** * Converts a Z3 proof into a format based on the RESOLUTE proof format. - *

- * The RESOLUTE format is a low-level proof format used by SMTInterpol. It exclusively relies on - * the resolution rule, with multiple axioms defined to support various theories. These axioms - * serve as the leaf nodes in the proof DAG. - *

- * The strategy used is to transform each result from a Z3 proof into corresponding resolution - * proof nodes, aiming to maintain the formulas used as arguments for the Z3 proof rule as well - * as the result. Depending on the rule, the number of nodes may remain the same (e.g., for modus ponens) or increase - * (e.g., for transitivity star). For the transitivity star rule, the sub-proof grows - * approximately 2n-1 times, where n is the number of nodes in the - * sub-proof. - *

+ * + *

The RESOLUTE format is a low-level proof format used by SMTInterpol. It exclusively relies on + * the resolution rule, with multiple axioms defined to support various theories. These axioms serve + * as the leaf nodes in the proof DAG. The strategy used is to transform each result from a Z3 proof + * into corresponding resolution proof nodes, aiming to maintain the formulas used as arguments for + * the Z3 proof rule as well as the result. Depending on the rule, the number of nodes may remain + * the same (e.g., for modus ponens) or increase (e.g., for transitivity star). For the transitivity + * star rule, the sub-proof grows approximately 2n-1 times, where n is the + * number of nodes in the sub-proof. * * @see Z3ProofRule for the list of Z3 proof rules. * @see org.sosy_lab.java_smt.ResProofRule for the list of RESOLUTE axioms. - **/ + */ @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access", "ModifiedButNotUsed"}) public class Z3ToResoluteProofConverter { @@ -85,7 +82,7 @@ static ResolutionProofDag convertToResolutionProofDag(Z3ProofNode[] z3ProofNodes return dag; } - //This should help extract parts of a formula to better transform proof rules. + // This should help extract parts of a formula to better transform proof rules. private static class ExtractorVisitor implements BooleanFormulaVisitor { private final List equivalenceOperands = new ArrayList<>(); @@ -164,8 +161,8 @@ public List extractEquivalenceOperands(BooleanFormula formula) { } /** - * Converts a {@link Z3ProofNode} into either a {@link ResolutionProofNode} or - * a {@link SourceProofNode}, depending on its rule. + * Converts a {@link Z3ProofNode} into either a {@link ResolutionProofNode} or a {@link + * SourceProofNode}, depending on its rule. * * @param node the {@link Z3ProofNode} to convert * @return the resulting {@link ProofNode} @@ -305,7 +302,6 @@ ProofNode handleNode(Z3ProofNode node) { } } - ProofNode handleTrue(Z3ProofNode node) { BooleanFormula formula = (BooleanFormula) node.getFormula(); SourceProofNode pn = new SourceProofNode(ResAxiom.TRUE_POSITIVE, formula); @@ -544,7 +540,7 @@ ProofNode handleDefault(Z3ProofNode node) { return null; } - //This is for debugging purposes. + // This is for debugging purposes. void printProof(ProofNode node, int indentLevel) { String indent = " ".repeat(indentLevel); From c64814a04935e1174f5c31b30c1faeca95e4926f Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 24 Mar 2025 13:13:11 +0100 Subject: [PATCH 034/132] Documentation on the proof processing from Z3 --- src/org/sosy_lab/java_smt/solvers/z3/Z3ProofProcessor.java | 1 + src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java | 2 ++ .../java_smt/solvers/z3/Z3ToResoluteProofConverter.java | 4 ++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofProcessor.java index 2d19389d89..d007542836 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofProcessor.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofProcessor.java @@ -17,6 +17,7 @@ import java.util.Map; import org.sosy_lab.java_smt.api.Formula; +// This class uses java recursion and as such, Z3NonRecursiveProofProcessor.java is preferred @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) class Z3ProofProcessor { private final long z3context; diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java index 753d55bf6d..1f0cb38877 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java @@ -14,6 +14,8 @@ import org.sosy_lab.java_smt.api.proofs.ProofRule; // TODO correctly document the formula strings + +/** Proof rules for Z3. These can be found in the Z3 API source code in the file Z3_api.h */ public enum Z3ProofRule implements ProofRule { // Undefined proof object diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java index 3cc0e794c0..281031f6b8 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java @@ -46,8 +46,8 @@ * @see org.sosy_lab.java_smt.ResProofRule for the list of RESOLUTE axioms. */ @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access", "ModifiedButNotUsed"}) -public class Z3ToResoluteProofConverter { - +public class Z3ToResoluteProofConverter { // This class is inclompete and currently not used. The + // strategy for transforming proof rules should be proved first. private final Z3FormulaManager formulaManager; private final BooleanFormulaManager bfm; From c5ea9bb3656978051d0c58a13aea774cc78c9e3b Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 24 Mar 2025 13:14:00 +0100 Subject: [PATCH 035/132] Z3: Changed the way the proof rule that Z3 gives back is processed --- .../z3/Z3NonRecursiveProofProcessor.java | 117 ++++-------------- 1 file changed, 24 insertions(+), 93 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java index 646aa8e3ff..38deb32ebe 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java @@ -17,11 +17,20 @@ import java.util.Deque; import java.util.HashMap; import java.util.Map; +import org.sosy_lab.java_smt.ProofRuleRegistry; import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.proofs.ProofRule; /** * This class is used to process the proof generated by Z3 and store it as a ProofNode. It is a - * non-recursive implementation of the proof processor. + * non-(java-)recursive implementation of the proof processor.# + * + *

The resulting DAG from transforming the proof from the Z3 provided structures into a set of + * {@link Z3ProofNode} should enable an easier way to extract the information from the proofs. + * However, some information is lost from the original proof, as the Z3 provided proof makes uses of + * more general structures like AST, SortKind, DeclKind. E.g. the leafs in the {@link Z3ProofNode} + * contain the whole formula used for the first proof rules in the tree, while these are internal + * nodes in the Z3 proof and leafs are the operands use in innermost terms. */ @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) class Z3NonRecursiveProofProcessor { @@ -39,9 +48,10 @@ class Z3NonRecursiveProofProcessor { } Z3ProofNode fromASTIterative(long rootProof) { - + // proof ast to be processed wrapped inside a frame Deque stack = new ArrayDeque<>(); + // proof ast has been converted into ProofNode Map computed = new HashMap<>(); stack.push(new Frame(rootProof)); @@ -49,9 +59,12 @@ Z3ProofNode fromASTIterative(long rootProof) { while (!stack.isEmpty()) { Frame frame = stack.peek(); + // prevent processing the same proof ast multiple times if (!frame.visited) { Native.incRef(z3context, frame.proof); + + // The number of children of the proof node frame.numArgs = Native.getAppNumArgs(z3context, frame.proof); frame.visited = true; @@ -68,17 +81,21 @@ Z3ProofNode fromASTIterative(long rootProof) { int numArgs = frame.numArgs; Formula formula; + // needed for the sortKind long sort = Native.getSort(z3context, frame.proof); long sortKind = Native.getSortKind(z3context, sort); Z3_sort_kind sk = Z3_sort_kind.fromInt((int) sortKind); if (sk != Z3_sort_kind.Z3_UNKNOWN_SORT) { + // This should be a proof sort, this is not included in the enum class provided by the API formula = generateFormula(frame.proof); } else { + // Return the i-th argument of the given application. The formula resulting from + // applying the proof rule is the last argument of the proof node. long z3expr = Native.getAppArg(z3context, frame.proof, numArgs - 1); formula = generateFormula(z3expr); } int declKind = Native.getDeclKind(z3context, Native.getAppDecl(z3context, frame.proof)); - Z3ProofRule proofRule = getPRfromDK(declKind); + ProofRule proofRule = getPRfromDK(declKind); Z3ProofNode node = new Z3ProofNode(formula, proofRule); for (int i = 0; i < numArgs - 1; i++) { @@ -94,96 +111,10 @@ Z3ProofNode fromASTIterative(long rootProof) { return computed.get(rootProof); } - private Z3ProofRule getPRfromDK(int declKind) { - Z3_decl_kind dk = Z3_decl_kind.fromInt(declKind); - switch (dk) { - case Z3_OP_PR_UNDEF: - return Z3ProofRule.UNDEF; - case Z3_OP_PR_TRUE: - return Z3ProofRule.TRUE; - case Z3_OP_PR_ASSERTED: - return Z3ProofRule.ASSERTED; - case Z3_OP_PR_GOAL: - return Z3ProofRule.GOAL; - case Z3_OP_PR_MODUS_PONENS: - return Z3ProofRule.MODUS_PONENS; - case Z3_OP_PR_REFLEXIVITY: - return Z3ProofRule.REFLEXIVITY; - case Z3_OP_PR_SYMMETRY: - return Z3ProofRule.SYMMETRY; - case Z3_OP_PR_TRANSITIVITY: - return Z3ProofRule.TRANSITIVITY; - case Z3_OP_PR_TRANSITIVITY_STAR: - return Z3ProofRule.TRANSITIVITY_STAR; - case Z3_OP_PR_MONOTONICITY: - return Z3ProofRule.MONOTONICITY; - case Z3_OP_PR_QUANT_INTRO: - return Z3ProofRule.QUANT_INTRO; - case Z3_OP_PR_BIND: - return Z3ProofRule.BIND; - case Z3_OP_PR_DISTRIBUTIVITY: - return Z3ProofRule.DISTRIBUTIVITY; - case Z3_OP_PR_AND_ELIM: - return Z3ProofRule.AND_ELIM; - case Z3_OP_PR_NOT_OR_ELIM: - return Z3ProofRule.NOT_OR_ELIM; - case Z3_OP_PR_REWRITE: - return Z3ProofRule.REWRITE; - case Z3_OP_PR_REWRITE_STAR: - return Z3ProofRule.REWRITE_STAR; - case Z3_OP_PR_PULL_QUANT: - return Z3ProofRule.PULL_QUANT; - case Z3_OP_PR_PUSH_QUANT: - return Z3ProofRule.PUSH_QUANT; - case Z3_OP_PR_ELIM_UNUSED_VARS: - return Z3ProofRule.ELIM_UNUSED_VARS; - case Z3_OP_PR_DER: - return Z3ProofRule.DER; - case Z3_OP_PR_QUANT_INST: - return Z3ProofRule.QUANT_INST; - case Z3_OP_PR_HYPOTHESIS: - return Z3ProofRule.HYPOTHESIS; - case Z3_OP_PR_LEMMA: - return Z3ProofRule.LEMMA; - case Z3_OP_PR_UNIT_RESOLUTION: - return Z3ProofRule.UNIT_RESOLUTION; - case Z3_OP_PR_IFF_TRUE: - return Z3ProofRule.IFF_TRUE; - case Z3_OP_PR_IFF_FALSE: - return Z3ProofRule.IFF_FALSE; - case Z3_OP_PR_COMMUTATIVITY: - return Z3ProofRule.COMMUTATIVITY; - case Z3_OP_PR_DEF_AXIOM: - return Z3ProofRule.DEF_AXIOM; - case Z3_OP_PR_ASSUMPTION_ADD: - return Z3ProofRule.ASSUMPTION_ADD; - case Z3_OP_PR_LEMMA_ADD: - return Z3ProofRule.LEMMA_ADD; - case Z3_OP_PR_REDUNDANT_DEL: - return Z3ProofRule.REDUNDANT_DEL; - case Z3_OP_PR_CLAUSE_TRAIL: - return Z3ProofRule.CLAUSE_TRAIL; - case Z3_OP_PR_DEF_INTRO: - return Z3ProofRule.DEF_INTRO; - case Z3_OP_PR_APPLY_DEF: - return Z3ProofRule.APPLY_DEF; - case Z3_OP_PR_IFF_OEQ: - return Z3ProofRule.IFF_OEQ; - case Z3_OP_PR_NNF_POS: - return Z3ProofRule.NNF_POS; - case Z3_OP_PR_NNF_NEG: - return Z3ProofRule.NNF_NEG; - case Z3_OP_PR_SKOLEMIZE: - return Z3ProofRule.SKOLEMIZE; - case Z3_OP_PR_MODUS_PONENS_OEQ: - return Z3ProofRule.MODUS_PONENS_OEQ; - case Z3_OP_PR_TH_LEMMA: - return Z3ProofRule.TH_LEMMA; - case Z3_OP_PR_HYPER_RESOLVE: - return Z3ProofRule.HYPER_RESOLVE; - default: - return Z3ProofRule.OPERATION; - } + private ProofRule getPRfromDK(int declKind) { + String rawName = Z3_decl_kind.fromInt(declKind).name(); + String prName = rawName.replaceFirst("Z3_OP_PR_", ""); + return ProofRuleRegistry.fromName(Z3ProofRule.class, prName); } private Formula generateFormula(long proof) { From e2268bae13f7a64a4ae428a89765864720c3d70e Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 24 Mar 2025 19:37:59 +0100 Subject: [PATCH 036/132] `ResolutionProofNode` and `SourceProofNode` have been moved inside `ResolutionProofDag` --- .../sosy_lab/java_smt/ResolutionProofDag.java | 100 +++++++ .../java_smt/ResolutionProofNode.java | 42 --- .../sosy_lab/java_smt/SourceProofNode.java | 31 --- .../java_smt/api/proofs/ProofFactory.java | 4 +- .../solvers/smtinterpol/ProofTermParser.java | 2 +- .../SmtInterpolFormulaCreator.java | 7 +- .../smtinterpol/SmtInterpolProofNode.java | 261 ------------------ .../SmtInterpolProofNodeCreator.java | 83 ++++++ .../z3/Z3ToResoluteProofConverter.java | 4 +- 9 files changed, 189 insertions(+), 345 deletions(-) delete mode 100644 src/org/sosy_lab/java_smt/ResolutionProofNode.java delete mode 100644 src/org/sosy_lab/java_smt/SourceProofNode.java delete mode 100644 src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNode.java create mode 100644 src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java diff --git a/src/org/sosy_lab/java_smt/ResolutionProofDag.java b/src/org/sosy_lab/java_smt/ResolutionProofDag.java index 8ae0e46f21..43865f4b6b 100644 --- a/src/org/sosy_lab/java_smt/ResolutionProofDag.java +++ b/src/org/sosy_lab/java_smt/ResolutionProofDag.java @@ -10,7 +10,13 @@ package org.sosy_lab.java_smt; +import java.util.Objects; +import org.sosy_lab.java_smt.ResProofRule.ResAxiom; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.basicimpl.AbstractProofDag; +import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; /** * This class represents a resolution proof DAG. Its nodes might be of the type {@link @@ -23,4 +29,98 @@ public class ResolutionProofDag extends AbstractProofDag { // Work in progress. The functionality of producing just nodes should be provided first. // The idea is to provide extended functionality (by providng a set of edges for example). + + /* + public ResolutionProofDAG() { + super(); + } + + + public static ResolutionProofDAG fromTerm( + Term proof, FormulaManager pManager, + Map pAnnotatedTerms) { + + // Use our new ProofTermParser to convert the proof term to a ResolutionProofDAG + return ProofTermParser.convert(proof, pManager, pAnnotatedTerms); + } + + private static void traverseTerm(Term term, ResolutionProofDAG dag, ProofNode parentClause) { + if (term instanceof AnnotatedTerm) { + AnnotatedTerm annotatedTerm = (AnnotatedTerm) term; + for (Annotation annotation : annotatedTerm.getAnnotations()) { + /* + if (annotation.getKey().equals(ProofConstants.ANNOTKEY_PROVES)) { + //ProofNode clause = annotation.getValue().toString(); + if (parentClause != null) { + dag.addEdge(parentClause, clause); + } else { + dag.addNode(clause); + } + for (Term subTerm : annotatedTerm.getSubterms()) { + traverseTerm(subTerm, dag, clause); + } + } + + + } + } + } + + + + @Override + public void addNode(ProofNode node) { + super.addNode(node); + } + + @Override + public ProofNode getNode(int nodeId) { + return super.getNode(nodeId); + } + + @Override + public void addEdge(int parentNodeId, int childNodeId) { + super.addEdge(parentNodeId, childNodeId); + } + + */ + + public static class ResolutionProofNode extends AbstractProofNode implements ProofNode { + + private final Formula pivot; + + public ResolutionProofNode(Formula formula, Formula pivot) { + super(ResAxiom.RESOLUTION, Objects.requireNonNull(formula, "Formula must not be null")); + this.pivot = Objects.requireNonNull(pivot, "Pivot must not be null"); + } + + @Override + public boolean isSource() { + return false; + } + + public Formula getPivot() { + return pivot; + } + + @Override + public ProofRule getRule() { + return super.getRule(); + } + } + + public static class SourceProofNode extends AbstractProofNode implements ProofNode { + + public SourceProofNode(ResAxiom rule, Formula formula) { + super( + Objects.requireNonNull(rule, "Rule must not be null"), + Objects.requireNonNull(formula, "Formula must not be null")); + } + + @Override + public boolean isSource() { + return true; + } + } + } diff --git a/src/org/sosy_lab/java_smt/ResolutionProofNode.java b/src/org/sosy_lab/java_smt/ResolutionProofNode.java deleted file mode 100644 index 8b5111d107..0000000000 --- a/src/org/sosy_lab/java_smt/ResolutionProofNode.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of JavaSMT, - * an API wrapper for a collection of SMT solvers: - * https://github.com/sosy-lab/java-smt - * - * SPDX-FileCopyrightText: 2024 Dirk Beyer - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.sosy_lab.java_smt; - -import java.util.Objects; -import org.sosy_lab.java_smt.ResProofRule.ResAxiom; -import org.sosy_lab.java_smt.api.Formula; -import org.sosy_lab.java_smt.api.proofs.ProofNode; -import org.sosy_lab.java_smt.api.proofs.ProofRule; -import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; - -public class ResolutionProofNode extends AbstractProofNode implements ProofNode { - - private final Formula pivot; - - public ResolutionProofNode(Formula formula, Formula pivot) { - super(ResAxiom.RESOLUTION, Objects.requireNonNull(formula, "Formula must not be null")); - this.pivot = Objects.requireNonNull(pivot, "Pivot must not be null"); - } - - @Override - public boolean isSource() { - return false; - } - - public Formula getPivot() { - return pivot; - } - - @Override - public ProofRule getRule() { - return super.getRule(); - } -} diff --git a/src/org/sosy_lab/java_smt/SourceProofNode.java b/src/org/sosy_lab/java_smt/SourceProofNode.java deleted file mode 100644 index 06c6aa029d..0000000000 --- a/src/org/sosy_lab/java_smt/SourceProofNode.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of JavaSMT, - * an API wrapper for a collection of SMT solvers: - * https://github.com/sosy-lab/java-smt - * - * SPDX-FileCopyrightText: 2024 Dirk Beyer - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.sosy_lab.java_smt; - -import java.util.Objects; -import org.sosy_lab.java_smt.ResProofRule.ResAxiom; -import org.sosy_lab.java_smt.api.Formula; -import org.sosy_lab.java_smt.api.proofs.ProofNode; -import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; - -public class SourceProofNode extends AbstractProofNode implements ProofNode { - - public SourceProofNode(ResAxiom rule, Formula formula) { - super( - Objects.requireNonNull(rule, "Rule must not be null"), - Objects.requireNonNull(formula, "Formula must not be null")); - } - - @Override - public boolean isSource() { - return true; - } -} diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java index bbdd423b83..5d7f769d0f 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java @@ -11,8 +11,8 @@ package org.sosy_lab.java_smt.api.proofs; import org.sosy_lab.java_smt.ResProofRule.ResAxiom; -import org.sosy_lab.java_smt.ResolutionProofNode; -import org.sosy_lab.java_smt.SourceProofNode; +import org.sosy_lab.java_smt.ResolutionProofDag.ResolutionProofNode; +import org.sosy_lab.java_smt.ResolutionProofDag.SourceProofNode; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.basicimpl.FormulaCreator; diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java index 56088c74c6..f9e2deb705 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java @@ -165,7 +165,7 @@ private BooleanFormula getBooleanFormulaFromTerm(Term term) { } private ProofNode createSourceNode(ResAxiom rule, BooleanFormula formula) { - ProofNode node = new org.sosy_lab.java_smt.SourceProofNode(rule, formula); + ProofNode node = new org.sosy_lab.java_smt.ResolutionProofDag.SourceProofNode(rule, formula); proofDag.addNode(node); return node; } diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolFormulaCreator.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolFormulaCreator.java index 757b2a61ba..fe083eb844 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolFormulaCreator.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolFormulaCreator.java @@ -101,12 +101,7 @@ private FunctionSymbol declareFun(String fun, Sort[] paramSorts, Sort resultSort FunctionSymbol fsym = environment.getTheory().getFunction(fun, paramSorts); if (fsym == null) { - try { - environment.declareFun(fun, paramSorts, resultSort); - } catch (SMTLIBException e) { - // can fail, if function is already declared with a different sort - throw new IllegalArgumentException("Cannot declare function '" + fun + "'", e); - } + environment.declareFun(fun, paramSorts, resultSort); return environment.getTheory().getFunction(fun, paramSorts); } else { if (!fsym.getReturnSort().equals(resultSort)) { diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNode.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNode.java deleted file mode 100644 index a7560bb632..0000000000 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNode.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * This file is part of JavaSMT, - * an API wrapper for a collection of SMT solvers: - * https://github.com/sosy-lab/java-smt - * - * SPDX-FileCopyrightText: 2024 Dirk Beyer - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.sosy_lab.java_smt.solvers.smtinterpol; - -import de.uni_freiburg.informatik.ultimate.logic.AnnotatedTerm; -import de.uni_freiburg.informatik.ultimate.logic.Annotation; -import de.uni_freiburg.informatik.ultimate.logic.Term; -import de.uni_freiburg.informatik.ultimate.logic.Theory; -import de.uni_freiburg.informatik.ultimate.smtinterpol.dpll.Clause; -import de.uni_freiburg.informatik.ultimate.smtinterpol.dpll.IAnnotation; -import de.uni_freiburg.informatik.ultimate.smtinterpol.dpll.Literal; -import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.LeafNode; -import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.ProofNode; -import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.ProofRules; -import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.ResolutionNode; -import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.ResolutionNode.Antecedent; -import org.sosy_lab.java_smt.ResolutionProofDag; -import org.sosy_lab.java_smt.ResolutionProofNode; -import org.sosy_lab.java_smt.api.Formula; -import org.sosy_lab.java_smt.api.proofs.ProofRule; -import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; - -@SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) -class SmtInterpolProofNode extends AbstractProofNode { - static class ResolutionProofDAGBuilder { - private final SmtInterpolFormulaCreator creator; - private Theory theory; - - public ResolutionProofDAGBuilder(SmtInterpolFormulaCreator creator) { - this.creator = creator; - } - - /* - // Morris traversal that processes every node and returns the created ResolutionProofDAG. - public static ResolutionProofDAG buildDag(SmtInterpolProofNode root) { - SmtInterpolProofNode current = root; - // Morris Traversal: process each node in inorder without extra stack. - while (current != null) { - if (current.getLeft() == null) { - current.processNode(); - current = current.getRight(); - } else { - SmtInterpolProofNode predecessor = current.getLeft(); - while (predecessor.getRight() != null && predecessor.getRight() != current) { - predecessor = predecessor.getRight(); - } - if (predecessor.getRight() == null) { - predecessor.setRight(current); // create temporary thread - current = current.getLeft(); - } else { - predecessor.setRight(null); // remove the thread - current = current.getRight(); - } - } - } - // Create DAG from the processed tree. - ResolutionProofDAG dag = new ResolutionProofDAG(); - addDagEdges(root, dag); - return dag; - } - */ - - // Recursively adds nodes and edges from the tree to the dag. - private static void addDagEdges(SmtInterpolProofNode node, ResolutionProofDag dag) { - if (node == null) { - return; - } - dag.addNode(node.getTransformed()); - if (node.getLeft() != null) { - dag.addEdge(node.getTransformed().getId(), node.getLeft().getTransformed().getId()); - addDagEdges(node.getLeft(), dag); - } - if (node.getRight() != null) { - dag.addEdge(node.getTransformed().getId(), node.getRight().getTransformed().getId()); - addDagEdges(node.getRight(), dag); - } - } - - public void processResNode(SmtInterpolProofNode node) { - if (node.getLeft() == null && node.getRight() == null) { - throw new UnsupportedOperationException("Cannot process leaf node"); - } else { - ResolutionNode rn = (ResolutionNode) SmtInterpolProofNode.node; - Antecedent[] antecedents = rn.getAntecedents(); - Literal pivot = antecedents[0].mPivot; - node.transformed = - new ResolutionProofNode( - node.getFormula(), creator.encapsulateBoolean(pivot.getSMTFormula(theory))); - } - } - - /* - public void processSourceNode(SmtInterpolProofNode node) { - if (node.getLeft() == null && node.getRight() == null) { - node.transformed = new SourceProofNode(node.getFormula()); - } else { - throw new UnsupportedOperationException("Cannot process resolution node"); - } - } - */ - } - - private static ProofNode node; - private SmtInterpolProofNode left; - private SmtInterpolProofNode right; - private org.sosy_lab.java_smt.api.proofs.ProofNode transformed; - - protected SmtInterpolProofNode(ProofRule rule, Formula formula) { - super(rule, formula); - } - - /* - public static SmtInterpolProofNode create( - Clause pClause, Theory pTheory, - Map pAnnotatedTerms, SmtInterpolFormulaCreator pCreator) { - Term clsAsTerm = pClause.toTerm(pTheory); - boolean createFormula = true; - String termName = null; - ProofNode pn = pClause.getProof(); - SmtInterpolProofNode newNode; - String rule; - if (clsAsTerm instanceof AnnotatedTerm) { - termName = getTermName((AnnotatedTerm) clsAsTerm); - if (termName != null) { - createFormula = false; - } - } - - if (!pn.isLeaf()) { - rule = ProofRules.RES; - newNode = new SmtInterpolProofNode(rule, - createFormula ? pCreator.encapsulateBoolean(clsAsTerm) : pAnnotatedTerms.get(termName)); - newNode.setProofNode(pn); - ResolutionNode rn = (ResolutionNode) pn; - newNode.left = create(rn.getPrimary(), pTheory, pAnnotatedTerms, pCreator); - Antecedent[] antecedents = rn.getAntecedents(); - if (antecedents.length > 0) { - newNode.right = create(antecedents[0].mAntecedent, pTheory, pAnnotatedTerms, pCreator); - } - } else { - LeafNode ln = (LeafNode) pn; - Term res; - final IAnnotation annot = ln.getTheoryAnnotation(); - if (ln.getLeafKind() == -1) { - rule = "INPUT"; - } else if (ln.getLeafKind() >= 0) { - rule = "TAUTOLOGY"; - } - if (annot == null) { - assert ln.getLeafKind() == LeafNode.ASSUMPTION; - rule = ProofRules.ASSUME; - - } else if (annot instanceof EQAnnotation) { - rule = ProofRules.ORACLE; - - } else if (annot instanceof LAAnnotation) { - rule = - } else if (annot instanceof CCAnnotation) { - rule = - } else if (annot instanceof QuantAnnotation) { - rule = - } else if (annot instanceof SourceAnnotation) { - rule = - } - newNode = new SmtInterpolProofNode(rule, - createFormula ? pCreator.encapsulateBoolean(clsAsTerm) : pAnnotatedTerms.get(termName)); - newNode.setProofNode(pn); - } - - - return newNode; - } - */ - public org.sosy_lab.java_smt.api.proofs.ProofNode getTransformed() { - return transformed; - } - - public SmtInterpolProofNode getLeft() { - return left; - } - - public SmtInterpolProofNode getRight() { - return right; - } - - // Helper for assigning temporary thread pointers - public void setRight(SmtInterpolProofNode node) { - this.right = node; - } - - private void setProofNode(ProofNode pNode) { - node = pNode; - } - - private static String getTermName(AnnotatedTerm pTerm) { - for (Annotation annotation : pTerm.getAnnotations()) { - if (annotation.getKey().equals(":named")) { - return annotation.getValue().toString(); - } - } - return null; - } - - private static ProofNode getNode() { - return node; - } - - public static Term annotationMethod(Clause cls, ProofRules rule) { - ProofNode pn = cls.getProof(); - Term res = null; - final IAnnotation annot = ((LeafNode) pn).getTheoryAnnotation(); - if (annot != null) { - res = annot.toTerm(cls, rule); - } - return res; - } - - /* - - - - public static ResolutionProofDAG generateProofDAG(ProofNode node) { - ResolutionProofDAG dag = new ResolutionProofDAG(); - if (node == null) { - return dag; - } - if (node.isLeaf()) { - - } else { - ResolutionNode resNode = (ResolutionNode) node; - ResolutionNode.Antecedent[] antecedents = resNode.getAntecedents(); - if (antecedents != null) { - for (ResolutionNode.Antecedent antecedent : antecedents) { - traverse(antecedent.mAntecedent.getProof()); - } - } - } - } - - - private void predecessorSetRight(SmtInterpolProofNode predecessor, SmtInterpolProofNode thread) { - try { - Field rightField = BinaryProofNode.class.getDeclaredField("right"); - rightField.setAccessible(true); - rightField.set(predecessor, thread); - } catch (Exception e) { - throw new RuntimeException("Unable to set right field via reflection", e); - } - } - - */ - -} diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java new file mode 100644 index 0000000000..1ae9a71054 --- /dev/null +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java @@ -0,0 +1,83 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.solvers.smtinterpol; + +import io.github.cvc5.Proof; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; +import org.sosy_lab.java_smt.api.proofs.ProofRule; +import org.sosy_lab.java_smt.solvers.cvc5.CVC5ProofNode; +import org.sosy_lab.java_smt.solvers.cvc5.CVC5ProofRule; + +@SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) +class SmtInterpolProofNodeCreator { + private final SmtInterpolFormulaCreator creator; + private final SmtInterpolTheoremProver prover; + + SmtInterpolProofNodeCreator( + SmtInterpolFormulaCreator pCreator, + SmtInterpolTheoremProver pProver) { + creator = pCreator; + prover = pProver; + + } + /* + + ProofNode fromTerm(Term pTerm) { + + Deque stack = new ArrayDeque<>(); + + Map computed = new HashMap<>(); + + stack.push(new Frame(rootProof)); + + while (!stack.isEmpty()) { + Frame frame = stack.peek(); + + // Skip processing the frame if its rule is "SCOPE" + // This rule seems to just help the processing by CVC5 + if (!frame.visited && frame.proof.getRule().getValue() == 1) { + // Pop the SCOPE frame and push its children onto the stack + stack.pop(); + frame.numChildren = rootProof.getChildren().length; + frame.visited = true; + + for (int i = frame.numChildren-1; i >= 0; i--) { + Proof child = rootProof.getChildren()[i]; + if (!computed.containsKey(child)) { + stack.push(new Frame(child)); + } + } + } else { + + stack.pop(); + int numChildren = frame.numChildren; + + CVC5ProofRule proofRule = + ProofRule.fromName(CVC5ProofRule.class, frame.proof.getRule().toString()); + CVC5ProofNode pn = new CVC5ProofNode(proofRule, generateFormula(frame.proof)); + for (int i = 0; i < numChildren - 1; i++) { + Proof child = frame.proof.getChildren()[i]; + + if (computed.containsKey(child)) { + pn.addChild(computed.get(child)); + } + } + computed.put(frame.proof, pn); + } + } + return computed.get(rootProof); + } + + */ +} diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java index 281031f6b8..5ec1f65fc5 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java @@ -19,8 +19,8 @@ import java.util.Map; import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.ResolutionProofDag; -import org.sosy_lab.java_smt.ResolutionProofNode; -import org.sosy_lab.java_smt.SourceProofNode; +import org.sosy_lab.java_smt.ResolutionProofDag.ResolutionProofNode; +import org.sosy_lab.java_smt.ResolutionProofDag.SourceProofNode; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.BooleanFormulaManager; import org.sosy_lab.java_smt.api.Formula; From e0d116df129e8fd811b0585e05fef8e9a7424065 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Tue, 25 Mar 2025 20:41:25 +0100 Subject: [PATCH 037/132] `getProof` now checks if the state of the solver and throws an exception if proof generation is not enabled. The default method is now in `AbstractProver`instead of `BasicProverEnvironment` --- .../sosy_lab/java_smt/api/BasicProverEnvironment.java | 9 +-------- src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java | 9 +++++++++ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java b/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java index b446497397..2421aec1a2 100644 --- a/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java @@ -154,14 +154,7 @@ default ImmutableMap getStatistics() { * Get proof of unsatisfiability of the conjuction of the current satck of all formulas. Should * only be called after {@link #isUnsat()} returned true. */ - default ProofNode getProof() { - try { - throw new UnsupportedOperationException("Proof generation isn't enabled."); - } catch (UnsupportedOperationException e) { - System.out.println(e.getMessage()); - throw e; - } - } + ProofNode getProof(); /** * Closes the prover environment. The object should be discarded, and should not be used after diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java index baa7dc07d1..11435d2547 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java @@ -26,6 +26,7 @@ import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.Evaluator; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; +import org.sosy_lab.java_smt.api.proofs.ProofNode; public abstract class AbstractProver implements BasicProverEnvironment { @@ -164,4 +165,12 @@ public void close() { closeAllEvaluators(); closed = true; } + + @Override + public ProofNode getProof() { + checkState(!closed); + checkGenerateProofs(); + + return null; + } } From 23e79a8e155709ccde0038ed4e15858347d0628f Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Tue, 25 Mar 2025 20:43:31 +0100 Subject: [PATCH 038/132] Added documentation. --- src/org/sosy_lab/java_smt/ResProofRule.java | 6 +++-- .../sosy_lab/java_smt/ResolutionProofDag.java | 1 - .../java_smt/api/proofs/ProofDag.java | 23 +++++++++++++++++++ .../java_smt/api/proofs/ProofFactory.java | 7 ++++++ .../java_smt/api/proofs/ProofFrame.java | 15 ++++++++++-- .../solvers/mathsat5/Mathsat5ProofNode.java | 4 ++-- 6 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/org/sosy_lab/java_smt/ResProofRule.java b/src/org/sosy_lab/java_smt/ResProofRule.java index 07b0e6004e..65db377168 100644 --- a/src/org/sosy_lab/java_smt/ResProofRule.java +++ b/src/org/sosy_lab/java_smt/ResProofRule.java @@ -10,6 +10,7 @@ package org.sosy_lab.java_smt; +import org.checkerframework.checker.nullness.qual.Nullable; import org.sosy_lab.java_smt.api.proofs.ProofRule; /** @@ -28,6 +29,7 @@ public enum ResAxiom implements ProofRule { // Resolution Rule RESOLUTION("res", "(res t proof1 proof2)"), + // RUP("rup", null), ASSUME("assume", "(assume t)"), // Logical operators TRUE_POSITIVE("true+", "(+ true)"), @@ -109,9 +111,9 @@ public enum ResAxiom implements ProofRule { "(= (match t ((p1 x1) c1) ...) (ite ((_ is p1) t) (let (x1 (sel1 t)) c1) ...))"); private final String name; - private final String formula; + @Nullable private final String formula; - ResAxiom(String pName, String pFormula) { + ResAxiom(String pName, @Nullable String pFormula) { name = pName; formula = pFormula; } diff --git a/src/org/sosy_lab/java_smt/ResolutionProofDag.java b/src/org/sosy_lab/java_smt/ResolutionProofDag.java index 43865f4b6b..513183f85b 100644 --- a/src/org/sosy_lab/java_smt/ResolutionProofDag.java +++ b/src/org/sosy_lab/java_smt/ResolutionProofDag.java @@ -122,5 +122,4 @@ public boolean isSource() { return true; } } - } diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofDag.java b/src/org/sosy_lab/java_smt/api/proofs/ProofDag.java index 3dc326d891..c38ecd81a2 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofDag.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofDag.java @@ -13,13 +13,36 @@ import java.util.Collection; import org.sosy_lab.java_smt.api.proofs.visitors.ProofVisitor; +/** + * A DAG representing a proof. Each node in the DAG is a {@link ProofNode} and each edge is a + * directed edge from a parent node to a child node. + */ public interface ProofDag { + + /** + * Add a node to the DAG. + * + * @param node + */ void addNode(ProofNode node); + /** + * Get a node from the DAG. + * + * @param nodeId + * @return + */ ProofNode getNode(int nodeId); + /** + * Add an edge to the DAG. + * + * @param parentNodeId + * @param childNodeId + */ void addEdge(int parentNodeId, int childNodeId); + /** Get all nodes in the DAG. */ Collection getNodes(); void accept(ProofVisitor visitor); // To allow traversal of the entire DAG diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java index 5d7f769d0f..d55eb8e099 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java @@ -18,6 +18,13 @@ import org.sosy_lab.java_smt.basicimpl.FormulaCreator; import org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5ProofNode; +/** + * A factory for creating proof nodes. The methods of this class are to be used in the ProofNode + * implementations of each solver to be able to convert the proof object given back by the solver to + * a proof in JavaSMT. + * + * @param The type of the proof object. + */ public class ProofFactory { private final FormulaCreator formulaCreator; diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java b/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java index 0720c52e9e..d22846f3d3 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java @@ -10,6 +10,12 @@ package org.sosy_lab.java_smt.api.proofs; +/** + * Stores proof related information and gets stored in a stack when processing proofs. Each frame + * contains a proof object and the number of arguments it has. + * + * @param The type of the proof object. + */ public abstract class ProofFrame { final T proof; int numArgs; @@ -20,22 +26,27 @@ protected ProofFrame(T proof) { this.visited = false; } + /** Get the proof object. */ public T getProof() { return proof; } + /** Get the number of arguments the proof object has. */ public int getNumArgs() { return numArgs; } - public boolean getVisited() { + /** Check if the frame has been visited. */ + public boolean isVisited() { return visited; } - public void setVisited(boolean visited) { + /** Set the frame as visited. */ + public void setAsVisited(boolean visited) { this.visited = visited; } + /** Set the number of arguments the proof object has. */ public void setNumArgs(int numArgs) { this.numArgs = numArgs; } diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java index 94a16679e5..de034c7f91 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java @@ -54,9 +54,9 @@ public static Mathsat5ProofNode fromMsatProof(ProverEnvironment pProver, long ro while (!stack.isEmpty()) { MsatProofFrame frame = stack.peek(); - if (!frame.getVisited()) { + if (!frame.isVisited()) { frame.setNumArgs(msat_proof_get_arity(frame.getProof())); - frame.setVisited(true); + frame.setAsVisited(true); // Push children first so that the leaves are processed first. for (int i = 0; i < frame.getNumArgs(); i++) { long child = msat_proof_get_child(frame.getProof(), i); From 99f682e720f3f5a6c0c2ce89178883b370afaad3 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Tue, 25 Mar 2025 20:45:56 +0100 Subject: [PATCH 039/132] SMTInterpol: added basic traversal for retrieved proofs in `SmtInterpolProofNodeCreator` --- .../SmtInterpolProofNodeCreator.java | 126 ++++++++++++++---- 1 file changed, 99 insertions(+), 27 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java index 1ae9a71054..7b87c6942d 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java @@ -10,14 +10,20 @@ package org.sosy_lab.java_smt.solvers.smtinterpol; +import de.uni_freiburg.informatik.ultimate.logic.AnnotatedTerm; +import de.uni_freiburg.informatik.ultimate.logic.Annotation; +import de.uni_freiburg.informatik.ultimate.logic.Term; import io.github.cvc5.Proof; import java.util.ArrayDeque; import java.util.Deque; import java.util.HashMap; import java.util.Map; +import org.sosy_lab.java_smt.api.proofs.ProofFrame; +import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.api.proofs.ProofRule; -import org.sosy_lab.java_smt.solvers.cvc5.CVC5ProofNode; -import org.sosy_lab.java_smt.solvers.cvc5.CVC5ProofRule; + +// SMTInterpol gives back a Term (apparently) only of instance ApplicationTerm or AnnotatedTerm, +// so the other instances are not needed. @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) class SmtInterpolProofNodeCreator { @@ -25,59 +31,125 @@ class SmtInterpolProofNodeCreator { private final SmtInterpolTheoremProver prover; SmtInterpolProofNodeCreator( - SmtInterpolFormulaCreator pCreator, - SmtInterpolTheoremProver pProver) { + SmtInterpolFormulaCreator pCreator, SmtInterpolTheoremProver pProver) { creator = pCreator; prover = pProver; + } + private class SmtTermFrame extends ProofFrame { + public SmtTermFrame(Term term) { + super(term); + } } - /* - ProofNode fromTerm(Term pTerm) { + ProofNode fromTerm(Term rootProof) { - Deque stack = new ArrayDeque<>(); + Deque stack = new ArrayDeque<>(); - Map computed = new HashMap<>(); + Map computed = new HashMap<>(); - stack.push(new Frame(rootProof)); + stack.push(new SmtTermFrame(rootProof)); while (!stack.isEmpty()) { - Frame frame = stack.peek(); + SmtTermFrame frame = stack.peek(); // Skip processing the frame if its rule is "SCOPE" // This rule seems to just help the processing by CVC5 - if (!frame.visited && frame.proof.getRule().getValue() == 1) { + if (!frame.isVisited() && frame.getProof() == null) { // Pop the SCOPE frame and push its children onto the stack stack.pop(); - frame.numChildren = rootProof.getChildren().length; - frame.visited = true; - - for (int i = frame.numChildren-1; i >= 0; i--) { - Proof child = rootProof.getChildren()[i]; - if (!computed.containsKey(child)) { - stack.push(new Frame(child)); + // frame.setNumArgs(rootProof. + frame.setAsVisited(true); + // numChildren - 1 iterations + for (int i = 10 - 1; i >= 0; i--) { + // Proof child = rootProof.getChildren()[i]; + // !Computed.containsKey(child) + if (true) { + // stack.push(new Frame(child)); } } } else { stack.pop(); - int numChildren = frame.numChildren; + int numChildren = frame.getNumArgs(); - CVC5ProofRule proofRule = - ProofRule.fromName(CVC5ProofRule.class, frame.proof.getRule().toString()); - CVC5ProofNode pn = new CVC5ProofNode(proofRule, generateFormula(frame.proof)); + // ProofRule proofRule = + // new source node or resolution node for (int i = 0; i < numChildren - 1; i++) { - Proof child = frame.proof.getChildren()[i]; + // Proof child = frame.getProof().getChildren()[i]; - if (computed.containsKey(child)) { - pn.addChild(computed.get(child)); + // if (computed.containsKey(child)) { + if (true) { + // pn.addChild(computed.get(child)); } } - computed.put(frame.proof, pn); + // computed.put(frame.proof, pn); } } return computed.get(rootProof); } - */ + private class ProvitionalProofNode { + private Term pivot; + private ProofRule proofRule; + private Term formula; + private int numChildren; + + public ProvitionalProofNode() {} + + public void setFormula(Term pFormula) { + formula = pFormula; + } + + public void setPivot(Term pPivot) { + pivot = pPivot; + } + + public void setProofRule(ProofRule pProofRule) { + proofRule = pProofRule; + } + + public void setNumChildren(int pNumChildren) { + numChildren = pNumChildren; + } + + public Term getFormula() { + return formula; + } + + public Term getPivot() { + return pivot; + } + + public ProofRule getProofRule() { + return proofRule; + } + + public int getNumChildren() { + return numChildren; + } + + void processAnnotated(AnnotatedTerm term) { + for (Annotation annotation : term.getAnnotations()) { + String key = annotation.getKey().substring(1); + if (annotation.getKey().equals("proves")) { + this.setFormula((Term) annotation.getValue()); + } + + switch (annotation.getKey()) { + case ":proves": + this.setFormula((Term) annotation.getValue()); + break; + case ":rup": + this.setFormula((Term) annotation.getValue()); + break; + case ":input": + this.setFormula((Term) annotation.getValue()); + break; + default: + break; + } + } + } + } } From f0d19ac5bff87445e192292336e6ce6395ace101 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 28 Mar 2025 17:38:32 +0100 Subject: [PATCH 040/132] Documentation --- .../java_smt/basicimpl/AbstractProofNode.java | 18 ++++-------------- .../java_smt/solvers/cvc5/CVC5ProofsTest.java | 8 +++++++- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java index ea1b2f8feb..abc880bc2a 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java @@ -42,7 +42,7 @@ public List getChildren() { return Collections.unmodifiableList(children); } - @Override +@Override public void addChild(ProofNode child) { children.add(child); } @@ -52,30 +52,20 @@ public ProofRule getRule() { } @Override - public boolean isSource() { - return false; - } - - @Override - public boolean isSink() { + public boolean isLeaf() { return children.isEmpty(); } - @Override - public void accept(ProofVisitor visitor) { - visitor.visitNode(this); - } - @Override public int getId() { return id; } - public void setRule(ProofRule rule) { + void setRule(ProofRule rule) { this.rule = rule; } - public void setFormula(Formula pFormula) { + void setFormula(Formula pFormula) { formula = pFormula; } } diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java index 99bee76103..bc08925794 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java @@ -109,7 +109,13 @@ private static Solver createEnvironment() throws CVC5ApiException { @Test public void getProofTest() { - // example from the 2022 RESOLUTE paper + //(declare-fun q1 () Bool) + //(declare-fun q2 () Bool) + //(assert (or (not q1) q2)) + //(assert q1) + //(assert (not q2)) + //(check-sat) + //(get-proof) BooleanFormula q1 = bmgr.makeVariable("q1"); BooleanFormula q2 = bmgr.makeVariable("q2"); From 3debfe29a05bdad74912d4448e547dc61eca3685 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 28 Mar 2025 17:39:42 +0100 Subject: [PATCH 041/132] `getProof` implementation was missing in some `ProverEnvironment` inheritors --- .../BasicProverWithAssumptionsWrapper.java | 6 ++++++ .../debugging/DebuggingBasicProverEnvironment.java | 6 ++++++ .../delegate/logging/LoggingBasicProverEnvironment.java | 8 ++++++++ .../statistics/StatisticsBasicProverEnvironment.java | 6 ++++++ .../synchronize/SynchronizedBasicProverEnvironment.java | 6 ++++++ .../SynchronizedBasicProverEnvironmentWithContext.java | 6 ++++++ 6 files changed, 38 insertions(+) diff --git a/src/org/sosy_lab/java_smt/basicimpl/withAssumptionsWrapper/BasicProverWithAssumptionsWrapper.java b/src/org/sosy_lab/java_smt/basicimpl/withAssumptionsWrapper/BasicProverWithAssumptionsWrapper.java index f2bf7435fe..f5c99bc5dc 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/withAssumptionsWrapper/BasicProverWithAssumptionsWrapper.java +++ b/src/org/sosy_lab/java_smt/basicimpl/withAssumptionsWrapper/BasicProverWithAssumptionsWrapper.java @@ -18,6 +18,7 @@ import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.Model; import org.sosy_lab.java_smt.api.SolverException; +import org.sosy_lab.java_smt.api.proofs.ProofNode; public class BasicProverWithAssumptionsWrapper> implements BasicProverEnvironment { @@ -128,4 +129,9 @@ public R allSat(AllSatCallback pCallback, List pImportant clearAssumptions(); return delegate.allSat(pCallback, pImportant); } + + @Override + public ProofNode getProof() { + return delegate.getProof(); + } } diff --git a/src/org/sosy_lab/java_smt/delegate/debugging/DebuggingBasicProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/debugging/DebuggingBasicProverEnvironment.java index c548d30384..21b4c44798 100644 --- a/src/org/sosy_lab/java_smt/delegate/debugging/DebuggingBasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/delegate/debugging/DebuggingBasicProverEnvironment.java @@ -18,6 +18,7 @@ import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.Model; import org.sosy_lab.java_smt.api.SolverException; +import org.sosy_lab.java_smt.api.proofs.ProofNode; class DebuggingBasicProverEnvironment implements BasicProverEnvironment { private final BasicProverEnvironment delegate; @@ -93,6 +94,11 @@ public Optional> unsatCoreOverAssumptions( return delegate.unsatCoreOverAssumptions(assumptions); } + @Override + public ProofNode getProof() { + return delegate.getProof(); + } + @Override public void close() { debugging.assertThreadLocal(); diff --git a/src/org/sosy_lab/java_smt/delegate/logging/LoggingBasicProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/logging/LoggingBasicProverEnvironment.java index 2f194c6125..c8b79cfe60 100644 --- a/src/org/sosy_lab/java_smt/delegate/logging/LoggingBasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/delegate/logging/LoggingBasicProverEnvironment.java @@ -24,6 +24,7 @@ import org.sosy_lab.java_smt.api.Model; import org.sosy_lab.java_smt.api.Model.ValueAssignment; import org.sosy_lab.java_smt.api.SolverException; +import org.sosy_lab.java_smt.api.proofs.ProofNode; /** Wraps a basic prover environment with a logging object. */ class LoggingBasicProverEnvironment implements BasicProverEnvironment { @@ -120,6 +121,13 @@ public ImmutableMap getStatistics() { return wrapped.getStatistics(); } + @Override + public ProofNode getProof() { + ProofNode p = wrapped.getProof(); + logger.log(Level.FINE, "proof", p); + return p; + } + @Override public void close() { wrapped.close(); diff --git a/src/org/sosy_lab/java_smt/delegate/statistics/StatisticsBasicProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/statistics/StatisticsBasicProverEnvironment.java index 49106d6324..433624b01a 100644 --- a/src/org/sosy_lab/java_smt/delegate/statistics/StatisticsBasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/delegate/statistics/StatisticsBasicProverEnvironment.java @@ -18,6 +18,7 @@ import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.Model; import org.sosy_lab.java_smt.api.SolverException; +import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.delegate.statistics.TimerPool.TimerWrapper; class StatisticsBasicProverEnvironment implements BasicProverEnvironment { @@ -99,6 +100,11 @@ public Optional> unsatCoreOverAssumptions( return delegate.unsatCoreOverAssumptions(pAssumptions); } + @Override + public ProofNode getProof() { + return delegate.getProof(); + } + @Override public void close() { delegate.close(); diff --git a/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedBasicProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedBasicProverEnvironment.java index f0401c6db2..fcb58d7b90 100644 --- a/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedBasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedBasicProverEnvironment.java @@ -20,6 +20,7 @@ import org.sosy_lab.java_smt.api.Model; import org.sosy_lab.java_smt.api.SolverContext; import org.sosy_lab.java_smt.api.SolverException; +import org.sosy_lab.java_smt.api.proofs.ProofNode; class SynchronizedBasicProverEnvironment implements BasicProverEnvironment { @@ -104,6 +105,11 @@ public ImmutableMap getStatistics() { } } + @Override + public ProofNode getProof() { + return delegate.getProof(); + } + @Override public void close() { synchronized (sync) { diff --git a/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedBasicProverEnvironmentWithContext.java b/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedBasicProverEnvironmentWithContext.java index 43922ccc25..bd7d04162f 100644 --- a/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedBasicProverEnvironmentWithContext.java +++ b/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedBasicProverEnvironmentWithContext.java @@ -22,6 +22,7 @@ import org.sosy_lab.java_smt.api.Model; import org.sosy_lab.java_smt.api.SolverContext; import org.sosy_lab.java_smt.api.SolverException; +import org.sosy_lab.java_smt.api.proofs.ProofNode; class SynchronizedBasicProverEnvironmentWithContext implements BasicProverEnvironment { @@ -121,6 +122,11 @@ public ImmutableMap getStatistics() { } } + @Override + public ProofNode getProof() { + return delegate.getProof(); + } + @Override public void close() { synchronized (sync) { From 85f8e1111c8d48a554861a191c8d3a9323b123ef Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 28 Mar 2025 17:40:28 +0100 Subject: [PATCH 042/132] Z3: added some tests for proofs --- .../java_smt/solvers/z3/Z3ProofsTest.java | 215 ++---------------- 1 file changed, 24 insertions(+), 191 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java index 415c0914e2..6e5fda6696 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java @@ -33,9 +33,11 @@ public class Z3ProofsTest { private Z3SolverContext context; private Z3FormulaManager mgr; private Z3BooleanFormulaManager bmgr; + private ProverEnvironment q1q2prover; @Before - public void setUpSolver() throws Exception { + public void setUpSolverContext() throws Exception { + //Z3 requires to enable proof generation in the configuration of the context Configuration config = Configuration.builder().setOption("solver.z3.requireProofs", "true").build(); LogManager logger = BasicLogManager.create(config); @@ -56,214 +58,45 @@ public void setUpSolver() throws Exception { bmgr = (Z3BooleanFormulaManager) mgr.getBooleanFormulaManager(); } - @After - public void closeSolver() { - if (context != null) { - context.close(); - } - } - - @Test - public void getProofTest() throws InterruptedException { + @Before + public void setUpQ1Q2Prover() throws InterruptedException { // example from the 2022 RESOLUTE paper BooleanFormula q1 = bmgr.makeVariable("q1"); BooleanFormula q2 = bmgr.makeVariable("q2"); - ProverEnvironment prover = context.newProverEnvironment0(Set.of()); - // Z3TheoremProver prover = - // (Z3TheoremProver) context.newProverEnvironment0(Set.of(ProverOptions - // .GENERATE_UNSAT_CORE)); - try { - System.out.println("proofs enabled: " + context.getGenerateProofs()); - prover.addConstraint(bmgr.or(bmgr.not(q1), q2)); - prover.addConstraint(q1); - prover.addConstraint(bmgr.not(q2)); - assertTrue(prover.isUnsat()); - - ProofNode proof = prover.getProof(); - assertThat(proof).isNotNull(); - } catch (SolverException pE) { - throw new RuntimeException(pE); - } - } - - @Test - public void printProofTest() throws InterruptedException { - // example from the 2022 RESOLUTE paper - BooleanFormula q1 = bmgr.makeVariable("q1"); - BooleanFormula q2 = bmgr.makeVariable("q2"); + q1q2prover = context.newProverEnvironment0(Set.of()); - ProverEnvironment prover = context.newProverEnvironment0(Set.of()); - // Z3TheoremProver prover = - // (Z3TheoremProver) context.newProverEnvironment0(Set.of(ProverOptions - // .GENERATE_UNSAT_CORE)); try { - System.out.println("proofs enabled: " + context.getGenerateProofs()); - prover.addConstraint(bmgr.or(bmgr.not(q1), q2)); - prover.addConstraint(q1); - prover.addConstraint(bmgr.not(q2)); - assertTrue(prover.isUnsat()); + q1q2prover.addConstraint(bmgr.or(bmgr.not(q1), q2)); + q1q2prover.addConstraint(q1); + q1q2prover.addConstraint(bmgr.not(q2)); + assertTrue(q1q2prover.isUnsat()); - ProofNode proof = prover.getProof(); - assertThat(proof).isNotNull(); - - System.out.println(((Z3ProofNode) proof).asString()); } catch (SolverException pE) { throw new RuntimeException(pE); } } - @Test - public void internalPrintProcessedProofTest() throws SolverException, InterruptedException { - // example from the 2022 RESOLUTE paper - BooleanFormula q1 = bmgr.makeVariable("q1"); - BooleanFormula q2 = bmgr.makeVariable("q2"); - - Z3TheoremProver prover = (Z3TheoremProver) context.newProverEnvironment0(Set.of()); - // Z3TheoremProver prover = - // (Z3TheoremProver) context.newProverEnvironment0(Set.of(ProverOptions - // .GENERATE_UNSAT_CORE)); - try { - System.out.println("proofs enabled: " + context.getGenerateProofs()); - prover.addConstraint(bmgr.or(bmgr.not(q1), q2)); - prover.addConstraint(q1); - prover.addConstraint(bmgr.not(q2)); - assertTrue(prover.isUnsat()); - - long proof = prover.getZ3Proof(); - Z3ProofProcessor parser = - new Z3ProofProcessor( - mgr.getEnvironment(), - prover.getZ3solver(), - (Z3FormulaCreator) mgr.getFormulaCreator(), - prover); - Z3ProofNode root = parser.fromAST(proof); - - System.out.println(root.asString()); - - } finally { - prover.close(); - } - } - - @Test - public void nonRecursivePrintParsedProofTest() throws SolverException, InterruptedException { - // example from the 2022 RESOLUTE paper - BooleanFormula q1 = bmgr.makeVariable("q1"); - BooleanFormula q2 = bmgr.makeVariable("q2"); - - Z3TheoremProver prover = (Z3TheoremProver) context.newProverEnvironment0(Set.of()); - // Z3TheoremProver prover = - // (Z3TheoremProver) context.newProverEnvironment0(Set.of(ProverOptions - // .GENERATE_UNSAT_CORE)); - try { - System.out.println("proofs enabled: " + context.getGenerateProofs()); - prover.addConstraint(bmgr.or(bmgr.not(q1), q2)); - prover.addConstraint(q1); - prover.addConstraint(bmgr.not(q2)); - assertTrue(prover.isUnsat()); - - long proof = prover.getZ3Proof(); - Z3NonRecursiveProofProcessor parser = - new Z3NonRecursiveProofProcessor( - mgr.getEnvironment(), - prover.getZ3solver(), - (Z3FormulaCreator) mgr.getFormulaCreator(), - prover); - Z3ProofNode root = parser.fromASTIterative(proof); - - System.out.println(root.asString()); - - } finally { - prover.close(); + @After + public void closeSolver() { + if (context != null) { + context.close(); } } @Test - public void compareRecursiveAndNonRecursiveOutputsTest() - throws SolverException, InterruptedException { - // example from the 2022 RESOLUTE paper - BooleanFormula q1 = bmgr.makeVariable("q1"); - BooleanFormula q2 = bmgr.makeVariable("q2"); - - Z3TheoremProver prover = (Z3TheoremProver) context.newProverEnvironment0(Set.of()); - // Z3TheoremProver prover = - // (Z3TheoremProver) context.newProverEnvironment0(Set.of(ProverOptions - // .GENERATE_UNSAT_CORE)); - try { - System.out.println("proofs enabled: " + context.getGenerateProofs()); - prover.addConstraint(bmgr.or(bmgr.not(q1), q2)); - prover.addConstraint(q1); - prover.addConstraint(bmgr.not(q2)); - assertTrue(prover.isUnsat()); - - long proof = prover.getZ3Proof(); - - Z3ProofProcessor parser = - new Z3ProofProcessor( - mgr.getEnvironment(), - prover.getZ3solver(), - (Z3FormulaCreator) mgr.getFormulaCreator(), - prover); - Z3ProofNode root = parser.fromAST(proof); - - Z3NonRecursiveProofProcessor nrParser = - new Z3NonRecursiveProofProcessor( - mgr.getEnvironment(), - prover.getZ3solver(), - (Z3FormulaCreator) mgr.getFormulaCreator(), - prover); - Z3ProofNode nRroot = nrParser.fromASTIterative(proof); - - assertEquals(root.asString(), nRroot.asString()); - - } finally { - prover.close(); - } - } - - public static Context createContextWithRawPointer(long m_ctx) { - try { - Constructor constructor = Context.class.getDeclaredConstructor(long.class); - constructor.setAccessible(true); // allow access even if non‑public - return constructor.newInstance(m_ctx); - } catch (Exception e) { - throw new RuntimeException("Failed to create Context instance", e); - } + public void getProofTest() throws InterruptedException { + ProofNode proof = q1q2prover.getProof(); + assertThat(proof).isNotNull(); } @Test - public void printZ3ProofAstTest() { - HashMap cfg = new HashMap<>(); - cfg.put("proof", "true"); - Context ctx = new Context(cfg); - try { - // Create boolean variables - BoolExpr q1 = ctx.mkBoolConst("q1"); - BoolExpr q2 = ctx.mkBoolConst("q2"); - - // Create solver - Solver solver = ctx.mkSolver(); - - // Assert (or (not q1) q2) - solver.add(ctx.mkOr(ctx.mkNot(q1), q2)); - - // Assert q1 - solver.add(q1); - - // Assert (not q2) - solver.add(ctx.mkNot(q2)); + public void getChildrenTest() { + ProofNode proof = q1q2prover.getProof(); + assertThat(proof).isNotNull(); + assertThat(proof.getChildren()).isNotEmpty(); + assertThat(proof.getChildren().get(0)).isNotNull(); - Status status = solver.check(); - - System.out.println("Unsat: " + (status == Status.UNSATISFIABLE)); - - Expr proof = solver.getProof(); - System.out.println("proof: " + proof); - System.out.println(Version.getFullVersion()); - } finally { - ctx.close(); - } } @Test @@ -279,12 +112,12 @@ public void Z3handleTransitivityTest() { pn.addChild(new Z3ProofNode(equiv1, Z3ProofRule.ASSERTED)); pn.addChild(new Z3ProofNode(equiv2, Z3ProofRule.ASSERTED)); - System.out.println(pn.asString()); + Z3ToResoluteProofConverter pc = new Z3ToResoluteProofConverter(mgr); ProofNode res = pc.handleTransitivity(pn); - pc.printProof(res, 0); + assertThat(res).isNotNull(); } } From 44e6ce8eaf5679a7748a71e130c542e2bc4c2a34 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 28 Mar 2025 17:41:03 +0100 Subject: [PATCH 043/132] Refactoring of some methods and classes, name changes and modifiers. --- .../sosy_lab/java_smt/ResolutionProofDag.java | 15 +++----------- .../java_smt/api/proofs/ProofFactory.java | 4 ++-- .../java_smt/api/proofs/ProofNode.java | 7 +------ .../solvers/smtinterpol/ProofTermParser.java | 3 ++- .../z3/Z3ToResoluteProofConverter.java | 20 +++++++++---------- 5 files changed, 18 insertions(+), 31 deletions(-) diff --git a/src/org/sosy_lab/java_smt/ResolutionProofDag.java b/src/org/sosy_lab/java_smt/ResolutionProofDag.java index 513183f85b..d6eee43f18 100644 --- a/src/org/sosy_lab/java_smt/ResolutionProofDag.java +++ b/src/org/sosy_lab/java_smt/ResolutionProofDag.java @@ -20,7 +20,7 @@ /** * This class represents a resolution proof DAG. Its nodes might be of the type {@link - * SourceProofNode} or {@link ResolutionProofNode}. It is used to represent proofs based on the + * AxiomProofNode} or {@link ResolutionProofNode}. It is used to represent proofs based on the * RESOLUTE proof format from SMTInterpol. * * @see ResProofRule @@ -94,11 +94,6 @@ public ResolutionProofNode(Formula formula, Formula pivot) { this.pivot = Objects.requireNonNull(pivot, "Pivot must not be null"); } - @Override - public boolean isSource() { - return false; - } - public Formula getPivot() { return pivot; } @@ -109,17 +104,13 @@ public ProofRule getRule() { } } - public static class SourceProofNode extends AbstractProofNode implements ProofNode { + public static class AxiomProofNode extends AbstractProofNode implements ProofNode { - public SourceProofNode(ResAxiom rule, Formula formula) { + public AxiomProofNode(ResAxiom rule, Formula formula) { super( Objects.requireNonNull(rule, "Rule must not be null"), Objects.requireNonNull(formula, "Formula must not be null")); } - @Override - public boolean isSource() { - return true; - } } } diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java index d55eb8e099..1edfab4998 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java @@ -12,7 +12,7 @@ import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.ResolutionProofDag.ResolutionProofNode; -import org.sosy_lab.java_smt.ResolutionProofDag.SourceProofNode; +import org.sosy_lab.java_smt.ResolutionProofDag.AxiomProofNode; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.basicimpl.FormulaCreator; @@ -73,7 +73,7 @@ static ProofNode createRresoluteNode() { } static ProofNode createSourceNode(ResAxiom rule, Formula formula) { - return new SourceProofNode(rule, formula); + return new AxiomProofNode(rule, formula); } static ProofNode createResolutionNode(Formula formula, Formula pivot) { diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java b/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java index 218e672f29..fdbb36cf9b 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java @@ -12,7 +12,6 @@ import java.util.List; import org.sosy_lab.java_smt.api.Formula; -import org.sosy_lab.java_smt.api.proofs.visitors.ProofVisitor; /** * A proof node in the proof DAG of a proof. @@ -26,11 +25,7 @@ public interface ProofNode { void addChild(ProofNode child); - boolean isSource(); - - boolean isSink(); - - void accept(ProofVisitor visitor); + boolean isLeaf(); /** * Get the formula of the proof node. diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java index f9e2deb705..2f5877c2b1 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java @@ -10,6 +10,7 @@ import java.util.Map; import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.ResolutionProofDag; +import org.sosy_lab.java_smt.ResolutionProofDag.AxiomProofNode; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.FormulaManager; import org.sosy_lab.java_smt.api.proofs.ProofNode; @@ -165,7 +166,7 @@ private BooleanFormula getBooleanFormulaFromTerm(Term term) { } private ProofNode createSourceNode(ResAxiom rule, BooleanFormula formula) { - ProofNode node = new org.sosy_lab.java_smt.ResolutionProofDag.SourceProofNode(rule, formula); + ProofNode node = new AxiomProofNode(rule, formula); proofDag.addNode(node); return node; } diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java index 5ec1f65fc5..3c08700471 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java @@ -20,7 +20,7 @@ import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.ResolutionProofDag; import org.sosy_lab.java_smt.ResolutionProofDag.ResolutionProofNode; -import org.sosy_lab.java_smt.ResolutionProofDag.SourceProofNode; +import org.sosy_lab.java_smt.ResolutionProofDag.AxiomProofNode; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.BooleanFormulaManager; import org.sosy_lab.java_smt.api.Formula; @@ -162,7 +162,7 @@ public List extractEquivalenceOperands(BooleanFormula formula) { /** * Converts a {@link Z3ProofNode} into either a {@link ResolutionProofNode} or a {@link - * SourceProofNode}, depending on its rule. + * AxiomProofNode}, depending on its rule. * * @param node the {@link Z3ProofNode} to convert * @return the resulting {@link ProofNode} @@ -304,13 +304,13 @@ ProofNode handleNode(Z3ProofNode node) { ProofNode handleTrue(Z3ProofNode node) { BooleanFormula formula = (BooleanFormula) node.getFormula(); - SourceProofNode pn = new SourceProofNode(ResAxiom.TRUE_POSITIVE, formula); + AxiomProofNode pn = new AxiomProofNode(ResAxiom.TRUE_POSITIVE, formula); return pn; } ProofNode handleAsserted(Z3ProofNode node) { BooleanFormula formula = (BooleanFormula) node.getFormula(); - SourceProofNode pn = new SourceProofNode(ResAxiom.ASSUME, formula); + AxiomProofNode pn = new AxiomProofNode(ResAxiom.ASSUME, formula); return pn; } @@ -325,7 +325,7 @@ ProofNode handleModusPonens(Z3ProofNode node) { ProofNode handleReflexivity(Z3ProofNode node) { BooleanFormula formula = (BooleanFormula) node.getFormula(); - SourceProofNode pn = new SourceProofNode(ResAxiom.REFLEXIVITY, formula); + AxiomProofNode pn = new AxiomProofNode(ResAxiom.REFLEXIVITY, formula); return pn; } @@ -335,7 +335,7 @@ ProofNode handleSymmetry(Z3ProofNode node) { BooleanFormula snFormula = bfm.or(bfm.not(pivot), formula); ResolutionProofNode pn = new ResolutionProofNode(formula, pivot); - SourceProofNode sn = new SourceProofNode(ResAxiom.SYMMETRY, snFormula); + AxiomProofNode sn = new AxiomProofNode(ResAxiom.SYMMETRY, snFormula); pn.addChild(sn); pn.addChild(handleNode((Z3ProofNode) node.getChildren().get(0))); return pn; @@ -355,7 +355,7 @@ ProofNode handleTransitivity(Z3ProofNode node) { BooleanFormula transRes = formula; BooleanFormula transClause = bfm.or(bfm.not(t1), bfm.not(t2), formula); - SourceProofNode pn = new SourceProofNode(ResAxiom.TRANSITIVITY, transClause); + AxiomProofNode pn = new AxiomProofNode(ResAxiom.TRANSITIVITY, transClause); ResolutionProofNode transResNode = new ResolutionProofNode(transRes, t2); ResolutionProofNode trnAnte1 = new ResolutionProofNode(t2, t2); @@ -390,7 +390,7 @@ ProofNode handleTransitivityStar(Z3ProofNode node) { formulas.add((BooleanFormula) node.getFormula()); BooleanFormula transitivityFormula = bfm.or(formulas); - SourceProofNode sn = new SourceProofNode(ResAxiom.TRANSITIVITY, transitivityFormula); + AxiomProofNode sn = new AxiomProofNode(ResAxiom.TRANSITIVITY, transitivityFormula); for (int i = 0; i < formulas.size() - 2; i++) { // ResolutionProofNode pn1 = new ResolutionProofNode(transitivityFormula., @@ -544,8 +544,8 @@ ProofNode handleDefault(Z3ProofNode node) { void printProof(ProofNode node, int indentLevel) { String indent = " ".repeat(indentLevel); - if (node instanceof SourceProofNode) { - SourceProofNode sourceNode = (SourceProofNode) node; + if (node instanceof AxiomProofNode) { + AxiomProofNode sourceNode = (AxiomProofNode) node; System.out.println(indent + "Formula: " + sourceNode.getFormula()); System.out.println(indent + "Rule: " + sourceNode.getRule()); System.out.println(indent + "No. Children: " + sourceNode.getChildren().size()); From f7da3932d922fbcbb27b143239b77f7d5fc2f74a Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 28 Mar 2025 20:37:55 +0100 Subject: [PATCH 044/132] CVC5: fixed unending loop in `getProof`. Fixed `Map`s in `ProofRuleResgistry` being empty --- .../sosy_lab/java_smt/ProofRuleRegistry.java | 24 +++++++++++++-- .../java_smt/basicimpl/AbstractProofNode.java | 1 + .../solvers/cvc5/CVC5ProofProcessor.java | 30 ++++++++++++------- .../java_smt/solvers/cvc5/CVC5ProofRule.java | 12 ++------ 4 files changed, 43 insertions(+), 24 deletions(-) diff --git a/src/org/sosy_lab/java_smt/ProofRuleRegistry.java b/src/org/sosy_lab/java_smt/ProofRuleRegistry.java index a598689f0d..0e0f050306 100644 --- a/src/org/sosy_lab/java_smt/ProofRuleRegistry.java +++ b/src/org/sosy_lab/java_smt/ProofRuleRegistry.java @@ -12,18 +12,36 @@ import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.sosy_lab.java_smt.api.proofs.ProofRule; +import org.sosy_lab.java_smt.solvers.cvc5.CVC5ProofRule; +import org.sosy_lab.java_smt.solvers.z3.Z3ProofRule; +/** + * Registry for proof rules. This class is used to register and retrieve proof rules by their name. + * It checks for the solver that called to retrieve the according rule. + */ public class ProofRuleRegistry { // Key: ProofRule class, Value: (Key: Name, Value: ProofRule) private static final Map, Map> RULES = - new HashMap<>(); + new ConcurrentHashMap<>(); - public static void register(Class clazz, ProofRule rule) { + private static void register(Class clazz, ProofRule rule) { RULES.computeIfAbsent(clazz, k -> new HashMap<>()).put(rule.getName(), rule); } public static ProofRule fromName(Class clazz, String name) { - return RULES.getOrDefault(clazz, new HashMap<>()).get(name); + return RULES.getOrDefault(clazz, new HashMap<>()).get(name.toLowerCase()); + } + + static { + + for (CVC5ProofRule rule : CVC5ProofRule.values()) { + ProofRuleRegistry.register(CVC5ProofRule.class, rule); + } + + for (Z3ProofRule rule : Z3ProofRule.values()) { + ProofRuleRegistry.register(Z3ProofRule.class, rule); + } } } diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java index abc880bc2a..5673f7b131 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java @@ -47,6 +47,7 @@ public void addChild(ProofNode child) { children.add(child); } + @Override public ProofRule getRule() { return rule; } diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java index 337d72d351..b2c0627bf2 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java @@ -18,13 +18,14 @@ import java.util.HashMap; import java.util.Map; import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.proofs.ProofRule; public class CVC5ProofProcessor { private final CVC5FormulaCreator formulaCreator; - private final CVC5AbstractProver prover; + private final ProverEnvironment prover; - CVC5ProofProcessor(CVC5FormulaCreator creator, CVC5AbstractProver pProver) { + CVC5ProofProcessor(CVC5FormulaCreator creator, ProverEnvironment pProver) { formulaCreator = creator; prover = pProver; } @@ -40,27 +41,34 @@ CVC5ProofNode fromCVC5Proof(Proof rootProof) throws CVC5ApiException { while (!stack.isEmpty()) { Frame frame = stack.peek(); - // Skip processing the frame if its rule is "SCOPE" - // This rule seems to just help the processing by CVC5 - if (!frame.visited && frame.proof.getRule().getValue() == 1) { - // Pop the SCOPE frame and push its children onto the stack - stack.pop(); - frame.numChildren = rootProof.getChildren().length; + + if (!frame.visited) { + + frame.numChildren = frame.proof.getChildren().length; frame.visited = true; - for (int i = frame.numChildren; i >= 0; i--) { - Proof child = rootProof.getChildren()[i]; + for (int i = frame.numChildren-1; i >= 0; i--) { + Proof child = frame.proof.getChildren()[i]; if (!computed.containsKey(child)) { stack.push(new Frame(child)); } } } else { + if (frame.proof.getRule().getValue() == 1) { + // Skip processing the frame if its rule is "SCOPE" + // This rule seems to just help the processing by CVC5 + System.out.println("Skipping SCOPE"); + stack.pop(); + continue; + } + + stack.pop(); int numChildren = frame.numChildren; CVC5ProofRule proofRule = - ProofRule.fromName(CVC5ProofRule.class, frame.proof.getRule().toString()); + ProofRule.fromName(CVC5ProofRule.class, frame.proof.getRule().toString().toLowerCase()); CVC5ProofNode pn = new CVC5ProofNode(proofRule, generateFormula(frame.proof)); for (int i = 0; i < numChildren - 1; i++) { Proof child = frame.proof.getChildren()[i]; diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofRule.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofRule.java index d49aa0b223..5eb403571d 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofRule.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofRule.java @@ -181,21 +181,13 @@ public enum CVC5ProofRule implements ProofRule { formula = pFormula; } - private static final Map NAME_TO_RULE_MAP = new HashMap<>(); - - static { - for (CVC5ProofRule rule : values()) { - ProofRuleRegistry.register(CVC5ProofRule.class, rule); - } - } - @Override public String getName() { - return ""; + return name; } @Override public String getFormula() { - return ""; + return formula; } } From dc6d5b3391be3d975d783c2e7b5582f7a914bccb Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 28 Mar 2025 20:39:26 +0100 Subject: [PATCH 045/132] Z3: Added tests for proof methods, fixed rule not properly created when creating `Z3ProofNode` --- .../sosy_lab/java_smt/api/proofs/ProofNode.java | 2 ++ .../java_smt/solvers/z3/Z3ProofProcessor.java | 9 --------- .../sosy_lab/java_smt/solvers/z3/Z3ProofRule.java | 6 ------ .../java_smt/solvers/z3/Z3ProofsTest.java | 15 +++++++++++++++ .../java_smt/solvers/z3/Z3TheoremProver.java | 2 +- 5 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java b/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java index fdbb36cf9b..8eb324fa2e 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java @@ -40,4 +40,6 @@ public interface ProofNode { * @return The id of the proof node. */ int getId(); + + ProofRule getRule(); } diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofProcessor.java index d007542836..f42140c6a1 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofProcessor.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofProcessor.java @@ -166,15 +166,6 @@ private Z3ProofRule getPRfromDK(int declKind) { } } - // @Nullable - // private Formula getFromStoredConstraints(long proof) { - // String varName = Native.astToString(z3context, proof); - // if (prover.getStoredConstraints().peek().containsKey(varName)) { - // return prover.getStoredConstraints().peek().get(varName); - // } else { - // return null; - // } - // } private Formula generateFormula(long proof) { Formula formula = null; diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java index 1f0cb38877..98b6280f19 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java @@ -98,12 +98,6 @@ public enum Z3ProofRule implements ProofRule { this.formula = formula; } - static { - for (Z3ProofRule rule : values()) { - ProofRuleRegistry.register(Z3ProofRule.class, rule); - } - } - @Override public String getName() { return name; diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java index 6e5fda6696..1812169ec1 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java @@ -96,7 +96,22 @@ public void getChildrenTest() { assertThat(proof).isNotNull(); assertThat(proof.getChildren()).isNotEmpty(); assertThat(proof.getChildren().get(0)).isNotNull(); + } + @Test + public void getProofRuleTest() { + ProofNode proof = q1q2prover.getProof(); + assertThat(proof).isNotNull(); + assertThat(proof.getRule()).isNotNull(); + assertThat(proof.getRule()).isEqualTo(Z3ProofRule.UNIT_RESOLUTION); + } + + @Test + public void getFormulaTest() { + ProofNode proof = q1q2prover.getProof(); + assertThat(proof).isNotNull(); + assertThat(proof.getFormula()).isNotNull(); + assertThat(proof.getFormula()).isEqualTo(bmgr.makeFalse()); } @Test diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java index 662da97d58..8ff8e3b995 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java @@ -150,7 +150,7 @@ protected long getZ3Model() { @Override public ProofNode getProof() { long proofAst = Native.solverGetProof(z3context, z3solver); - return new Z3ProofProcessor(z3context, z3solver, creator, this).fromAST(proofAst); + return new Z3NonRecursiveProofProcessor(z3context, z3solver, creator, this).fromASTIterative(proofAst); } // This method is used to get the Z3 proof as a long for testing exclusively From 12e4ccb1896ca5d9fa65dec295e58239c3109f1d Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 28 Mar 2025 20:46:42 +0100 Subject: [PATCH 046/132] CVC5: Corrected incorrect cast at `getProof` --- src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java index 34a0853b2e..514a6fde15 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java @@ -35,6 +35,7 @@ import org.sosy_lab.java_smt.api.Evaluator; import org.sosy_lab.java_smt.api.FormulaManager; import org.sosy_lab.java_smt.api.Model.ValueAssignment; +import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; import org.sosy_lab.java_smt.api.proofs.ProofNode; @@ -248,7 +249,7 @@ public ProofNode getProof() { throw new IllegalStateException("No proof available"); } - CVC5ProofProcessor pp = new CVC5ProofProcessor(creator, this); + CVC5ProofProcessor pp = new CVC5ProofProcessor(creator, (ProverEnvironment) this); try { return pp.fromCVC5Proof(proofs[0]); } catch (CVC5ApiException pE) { From 9bc37ca5a5b4db42523fc2ab840d0f716591dd6a Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sat, 29 Mar 2025 17:59:35 +0100 Subject: [PATCH 047/132] CVC5: proof dag now gets completely generated. --- .../java_smt/solvers/cvc5/CVC5ProofNode.java | 20 ++++++ .../solvers/cvc5/CVC5ProofProcessor.java | 65 ++++++++++--------- 2 files changed, 53 insertions(+), 32 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java index 6d3ad5945b..f4f18d3eb5 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java @@ -11,6 +11,7 @@ package org.sosy_lab.java_smt.solvers.cvc5; import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; @@ -20,4 +21,23 @@ public CVC5ProofNode(ProofRule pProofRule, Formula formula) { super(pProofRule, formula); } + + String asString(int indentLevel) { + StringBuilder proof = new StringBuilder(); + String indent = " ".repeat(indentLevel); + + proof.append(indent).append("Formula: ").append(getFormula().toString()).append("\n"); + proof.append(indent).append("Rule: ").append(getRule().getName()).append("\n"); + proof.append(indent).append("No. Children: ").append(getChildren().size()).append("\n"); + proof.append(indent).append("ID: ").append(getId()).append("\n"); + proof.append(indent).append("leaf: ").append(isLeaf()).append("\n"); + + int i = 0; + for (ProofNode child : getChildren()) { + proof.append(indent).append("Child ").append(++i).append(":\n"); + proof.append(((CVC5ProofNode) child).asString(indentLevel + 1)); + } + + return proof.toString(); + } } diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java index b2c0627bf2..23ea706fab 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java @@ -19,9 +19,16 @@ import java.util.Map; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.ProverEnvironment; +import org.sosy_lab.java_smt.api.proofs.ProofFrame; import org.sosy_lab.java_smt.api.proofs.ProofRule; public class CVC5ProofProcessor { + + private class CVC5Frame extends ProofFrame { + CVC5Frame(Proof proof) { + super(proof); + } + } private final CVC5FormulaCreator formulaCreator; private final ProverEnvironment prover; @@ -30,57 +37,57 @@ public class CVC5ProofProcessor { prover = pProver; } - CVC5ProofNode fromCVC5Proof(Proof rootProof) throws CVC5ApiException { + CVC5ProofNode fromCVC5Proof(Proof pProof) throws CVC5ApiException { - Deque stack = new ArrayDeque<>(); + boolean skippedScope = false; + + Deque stack = new ArrayDeque<>(); Map computed = new HashMap<>(); - stack.push(new Frame(rootProof)); + stack.push(new CVC5Frame(pProof)); while (!stack.isEmpty()) { - Frame frame = stack.peek(); + CVC5Frame frame = stack.peek(); - if (!frame.visited) { + if (!frame.isVisited()) { - frame.numChildren = frame.proof.getChildren().length; - frame.visited = true; + frame.setNumArgs(frame.getProof().getChildren().length); + frame.setAsVisited(true); - for (int i = frame.numChildren-1; i >= 0; i--) { - Proof child = frame.proof.getChildren()[i]; + for (int i = frame.getNumArgs()-1; i >= 0; i--) { + Proof child = frame.getProof().getChildren()[i]; if (!computed.containsKey(child)) { - stack.push(new Frame(child)); + stack.push(new CVC5Frame(child)); } } } else { + stack.pop(); + int numChildren = frame.getNumArgs(); - if (frame.proof.getRule().getValue() == 1) { + if (frame.getProof().getRule().getValue() == 1 && !skippedScope) { // Skip processing the frame if its rule is "SCOPE" // This rule seems to just help the processing by CVC5 - System.out.println("Skipping SCOPE"); - stack.pop(); + pProof = changeRoot(frame.getProof()); + skippedScope = true; continue; } - - stack.pop(); - int numChildren = frame.numChildren; - CVC5ProofRule proofRule = - ProofRule.fromName(CVC5ProofRule.class, frame.proof.getRule().toString().toLowerCase()); - CVC5ProofNode pn = new CVC5ProofNode(proofRule, generateFormula(frame.proof)); - for (int i = 0; i < numChildren - 1; i++) { - Proof child = frame.proof.getChildren()[i]; + ProofRule.fromName(CVC5ProofRule.class, frame.getProof().getRule().toString().toLowerCase()); + CVC5ProofNode pn = new CVC5ProofNode(proofRule, generateFormula(frame.getProof())); + for (int i = 0; i < numChildren; i++) { + Proof child = frame.getProof().getChildren()[i]; if (computed.containsKey(child)) { pn.addChild(computed.get(child)); } } - computed.put(frame.proof, pn); + computed.put(frame.getProof(), pn); } } - return computed.get(rootProof); + return computed.get(pProof); } private Formula generateFormula(Proof proof) { @@ -92,14 +99,8 @@ private Formula generateFormula(Proof proof) { return formula; } - private static class Frame { - final Proof proof; - int numChildren; - boolean visited; - - Frame(Proof pProof) { - proof = pProof; - visited = false; - } + private Proof changeRoot(Proof root) { + return root.getChildren()[0]; } + } From 78e5431b6e5f3511fb0c0ae8fddabda2f3a0ada2 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sat, 29 Mar 2025 18:00:21 +0100 Subject: [PATCH 048/132] Fixed incorrect generation of IDs for `AbstractProofNode` inheritors' instances --- src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java index 5673f7b131..6ffbb49ee5 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java @@ -22,7 +22,7 @@ public abstract class AbstractProofNode implements ProofNode { private final List children; private ProofRule rule; private Formula formula; - private final UniqueIdGenerator idGenerator = new UniqueIdGenerator(); + private static final UniqueIdGenerator idGenerator = new UniqueIdGenerator(); private final int id; protected AbstractProofNode(ProofRule rule, Formula formula) { From 961704885dbc69f8c229bdaf0ea7f8a4b1b97b7c Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sat, 29 Mar 2025 18:53:28 +0100 Subject: [PATCH 049/132] Documentation --- .../sosy_lab/java_smt/ResolutionProofDag.java | 55 ------------------- .../java_smt/solvers/cvc5/CVC5ProofsTest.java | 2 + .../java_smt/solvers/z3/Z3ProofsTest.java | 37 ++++++++----- 3 files changed, 25 insertions(+), 69 deletions(-) diff --git a/src/org/sosy_lab/java_smt/ResolutionProofDag.java b/src/org/sosy_lab/java_smt/ResolutionProofDag.java index d6eee43f18..f8c6bc15f0 100644 --- a/src/org/sosy_lab/java_smt/ResolutionProofDag.java +++ b/src/org/sosy_lab/java_smt/ResolutionProofDag.java @@ -30,61 +30,6 @@ public class ResolutionProofDag extends AbstractProofDag { // Work in progress. The functionality of producing just nodes should be provided first. // The idea is to provide extended functionality (by providng a set of edges for example). - /* - public ResolutionProofDAG() { - super(); - } - - - public static ResolutionProofDAG fromTerm( - Term proof, FormulaManager pManager, - Map pAnnotatedTerms) { - - // Use our new ProofTermParser to convert the proof term to a ResolutionProofDAG - return ProofTermParser.convert(proof, pManager, pAnnotatedTerms); - } - - private static void traverseTerm(Term term, ResolutionProofDAG dag, ProofNode parentClause) { - if (term instanceof AnnotatedTerm) { - AnnotatedTerm annotatedTerm = (AnnotatedTerm) term; - for (Annotation annotation : annotatedTerm.getAnnotations()) { - /* - if (annotation.getKey().equals(ProofConstants.ANNOTKEY_PROVES)) { - //ProofNode clause = annotation.getValue().toString(); - if (parentClause != null) { - dag.addEdge(parentClause, clause); - } else { - dag.addNode(clause); - } - for (Term subTerm : annotatedTerm.getSubterms()) { - traverseTerm(subTerm, dag, clause); - } - } - - - } - } - } - - - - @Override - public void addNode(ProofNode node) { - super.addNode(node); - } - - @Override - public ProofNode getNode(int nodeId) { - return super.getNode(nodeId); - } - - @Override - public void addEdge(int parentNodeId, int childNodeId) { - super.addEdge(parentNodeId, childNodeId); - } - - */ - public static class ResolutionProofNode extends AbstractProofNode implements ProofNode { private final Formula pivot; diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java index bc08925794..df12edb620 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java @@ -116,6 +116,8 @@ public void getProofTest() { //(assert (not q2)) //(check-sat) //(get-proof) + //This problem is from the paper found in https://ultimate.informatik.uni-freiburg.de/smtinterpol/proofs.html + BooleanFormula q1 = bmgr.makeVariable("q1"); BooleanFormula q2 = bmgr.makeVariable("q2"); diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java index 1812169ec1..3d03255f4f 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java @@ -19,9 +19,11 @@ import org.sosy_lab.common.configuration.Configuration; import org.sosy_lab.common.log.BasicLogManager; import org.sosy_lab.common.log.LogManager; +import org.sosy_lab.java_smt.SolverContextFactory; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.FloatingPointRoundingMode; import org.sosy_lab.java_smt.api.ProverEnvironment; +import org.sosy_lab.java_smt.api.SolverContext; import org.sosy_lab.java_smt.api.SolverException; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.AbstractNumeralFormulaManager.NonLinearArithmetic; @@ -30,7 +32,7 @@ @Ignore("prevent this class being executed as testcase by ant") public class Z3ProofsTest { - private Z3SolverContext context; + private SolverContext context; private Z3FormulaManager mgr; private Z3BooleanFormulaManager bmgr; private ProverEnvironment q1q2prover; @@ -43,28 +45,28 @@ public void setUpSolverContext() throws Exception { LogManager logger = BasicLogManager.create(config); ShutdownManager shutdown = ShutdownManager.create(); - // Create new context with SMTInterpol - context = - Z3SolverContext.create( - logger, - config, - shutdown.getNotifier(), - null, // no logfile - 42, // random seed value - FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN, - NonLinearArithmetic.USE, - NativeLibraries::loadLibrary); + context = SolverContextFactory.createSolverContext( + config, logger, shutdown.getNotifier(), SolverContextFactory.Solvers.Z3); + + mgr = (Z3FormulaManager) context.getFormulaManager(); bmgr = (Z3BooleanFormulaManager) mgr.getBooleanFormulaManager(); } @Before public void setUpQ1Q2Prover() throws InterruptedException { - // example from the 2022 RESOLUTE paper + //(declare-fun q1 () Bool) + //(declare-fun q2 () Bool) + //(assert (or (not q1) q2)) + //(assert q1) + //(assert (not q2)) + //(check-sat) + //(get-proof) + //This problem is from the paper found in https://ultimate.informatik.uni-freiburg.de/smtinterpol/proofs.html BooleanFormula q1 = bmgr.makeVariable("q1"); BooleanFormula q2 = bmgr.makeVariable("q2"); - q1q2prover = context.newProverEnvironment0(Set.of()); + q1q2prover = context.newProverEnvironment(); try { q1q2prover.addConstraint(bmgr.or(bmgr.not(q1), q2)); @@ -114,6 +116,13 @@ public void getFormulaTest() { assertThat(proof.getFormula()).isEqualTo(bmgr.makeFalse()); } + @Test + public void getProofTermTest() throws SolverException, InterruptedException { + ProofNode proof = q1q2prover.getProof(); + + System.out.println(((Z3ProofNode) proof).asString()); + } + @Test public void Z3handleTransitivityTest() { BooleanFormula f1 = bmgr.makeVariable("f1"); From 95ee7556d1fb85ea025418a5b007b8beccb4e33f Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sat, 29 Mar 2025 22:14:12 +0100 Subject: [PATCH 050/132] `AbstractProofNode` now is an internal class of `AbstractProofDag` --- .../java_smt/basicimpl/AbstractProofDag.java | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java index 657628dab7..b1aaf4668d 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java @@ -10,11 +10,20 @@ package org.sosy_lab.java_smt.basicimpl; +import static com.google.common.base.Preconditions.checkState; + +import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; +import org.sosy_lab.common.UniqueIdGenerator; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.proofs.ProofDag; import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.api.proofs.visitors.ProofVisitor; /** @@ -54,4 +63,58 @@ public Collection getNodes() { public void accept(ProofVisitor visitor) { visitor.visitDAG(this); } + + public abstract static class AbstractProofNode implements ProofNode { + private final List children; + private ProofRule rule; + private Formula formula; + private static final UniqueIdGenerator idGenerator = new UniqueIdGenerator(); + private final int id; + + protected AbstractProofNode(ProofRule rule, Formula formula) { + this.rule = rule; + this.formula = formula; + children = new ArrayList<>(); + id = idGenerator.getFreshId(); + } + + @Override + public Formula getFormula() { + return formula; + } + + @Override + public List getChildren() { + return Collections.unmodifiableList(children); + } + + @Override + public void addChild(ProofNode child) { + children.add(child); + } + + @Override + public ProofRule getRule() { + return rule; + } + + @Override + public boolean isLeaf() { + return children.isEmpty(); + } + + @Override + public int getId() { + return id; + } + + void setRule(ProofRule rule) { + this.rule = rule; + } + + void setFormula(Formula pFormula) { + formula = pFormula; + } + + } } From 036a563bc9aa029bf6ccefa3eab8cc1e20b2e734 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sat, 29 Mar 2025 22:15:40 +0100 Subject: [PATCH 051/132] `getProof` no longer overridden in `AbstractProver`. default method again in interface `BasicProverEnvironment` --- .../java_smt/basicimpl/AbstractProofNode.java | 72 ------------------- .../java_smt/basicimpl/AbstractProver.java | 9 +-- 2 files changed, 2 insertions(+), 79 deletions(-) delete mode 100644 src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java deleted file mode 100644 index 6ffbb49ee5..0000000000 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofNode.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * This file is part of JavaSMT, - * an API wrapper for a collection of SMT solvers: - * https://github.com/sosy-lab/java-smt - * - * SPDX-FileCopyrightText: 2024 Dirk Beyer - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.sosy_lab.java_smt.basicimpl; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import org.sosy_lab.common.UniqueIdGenerator; -import org.sosy_lab.java_smt.api.Formula; -import org.sosy_lab.java_smt.api.proofs.ProofNode; -import org.sosy_lab.java_smt.api.proofs.ProofRule; -import org.sosy_lab.java_smt.api.proofs.visitors.ProofVisitor; - -public abstract class AbstractProofNode implements ProofNode { - private final List children; - private ProofRule rule; - private Formula formula; - private static final UniqueIdGenerator idGenerator = new UniqueIdGenerator(); - private final int id; - - protected AbstractProofNode(ProofRule rule, Formula formula) { - this.rule = rule; - this.formula = formula; - children = new ArrayList<>(); - id = idGenerator.getFreshId(); - } - - @Override - public Formula getFormula() { - return formula; - } - - @Override - public List getChildren() { - return Collections.unmodifiableList(children); - } - -@Override - public void addChild(ProofNode child) { - children.add(child); - } - - @Override - public ProofRule getRule() { - return rule; - } - - @Override - public boolean isLeaf() { - return children.isEmpty(); - } - - @Override - public int getId() { - return id; - } - - void setRule(ProofRule rule) { - this.rule = rule; - } - - void setFormula(Formula pFormula) { - formula = pFormula; - } -} diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java index 11435d2547..214c62abe9 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java @@ -25,7 +25,9 @@ import org.sosy_lab.java_smt.api.BasicProverEnvironment; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.Evaluator; +import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; +import org.sosy_lab.java_smt.api.SolverException; import org.sosy_lab.java_smt.api.proofs.ProofNode; public abstract class AbstractProver implements BasicProverEnvironment { @@ -166,11 +168,4 @@ public void close() { closed = true; } - @Override - public ProofNode getProof() { - checkState(!closed); - checkGenerateProofs(); - - return null; - } } From fd2230a514ee1fadb1d5c1d57280e13a96137e6c Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sat, 29 Mar 2025 22:15:47 +0100 Subject: [PATCH 052/132] `getProof` no longer overridden in `AbstractProver`. default method again in interface `BasicProverEnvironment` --- src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java b/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java index 2421aec1a2..2bc252f172 100644 --- a/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java @@ -154,7 +154,9 @@ default ImmutableMap getStatistics() { * Get proof of unsatisfiability of the conjuction of the current satck of all formulas. Should * only be called after {@link #isUnsat()} returned true. */ - ProofNode getProof(); + default ProofNode getProof() throws SolverException, InterruptedException { + throw new UnsupportedOperationException("Proof generation is not available for the current solver."); + } /** * Closes the prover environment. The object should be discarded, and should not be used after From 7fcd878b19fa94563a006291af9e0844e387fbf7 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sat, 29 Mar 2025 22:17:19 +0100 Subject: [PATCH 053/132] Mathsat5: `getProof` now checks if the state is closed and the stack evaluates to `unsat` --- .../BasicProverWithAssumptionsWrapper.java | 2 +- .../DebuggingBasicProverEnvironment.java | 2 +- .../LoggingBasicProverEnvironment.java | 2 +- .../java_smt/solvers/cvc5/CVC5ProofNode.java | 2 +- .../solvers/mathsat5/Mathsat5ProofNode.java | 13 ++- .../mathsat5/Mathsat5ProofProcessor.java | 106 ------------------ .../mathsat5/Mathsat5TheoremProver.java | 33 +++++- 7 files changed, 40 insertions(+), 120 deletions(-) delete mode 100644 src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofProcessor.java diff --git a/src/org/sosy_lab/java_smt/basicimpl/withAssumptionsWrapper/BasicProverWithAssumptionsWrapper.java b/src/org/sosy_lab/java_smt/basicimpl/withAssumptionsWrapper/BasicProverWithAssumptionsWrapper.java index f5c99bc5dc..0cb2e64571 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/withAssumptionsWrapper/BasicProverWithAssumptionsWrapper.java +++ b/src/org/sosy_lab/java_smt/basicimpl/withAssumptionsWrapper/BasicProverWithAssumptionsWrapper.java @@ -131,7 +131,7 @@ public R allSat(AllSatCallback pCallback, List pImportant } @Override - public ProofNode getProof() { + public ProofNode getProof() throws SolverException, InterruptedException { return delegate.getProof(); } } diff --git a/src/org/sosy_lab/java_smt/delegate/debugging/DebuggingBasicProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/debugging/DebuggingBasicProverEnvironment.java index 21b4c44798..e4ae1227bd 100644 --- a/src/org/sosy_lab/java_smt/delegate/debugging/DebuggingBasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/delegate/debugging/DebuggingBasicProverEnvironment.java @@ -95,7 +95,7 @@ public Optional> unsatCoreOverAssumptions( } @Override - public ProofNode getProof() { + public ProofNode getProof() throws SolverException, InterruptedException { return delegate.getProof(); } diff --git a/src/org/sosy_lab/java_smt/delegate/logging/LoggingBasicProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/logging/LoggingBasicProverEnvironment.java index c8b79cfe60..3dd36f5e2a 100644 --- a/src/org/sosy_lab/java_smt/delegate/logging/LoggingBasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/delegate/logging/LoggingBasicProverEnvironment.java @@ -122,7 +122,7 @@ public ImmutableMap getStatistics() { } @Override - public ProofNode getProof() { + public ProofNode getProof() throws SolverException, InterruptedException { ProofNode p = wrapped.getProof(); logger.log(Level.FINE, "proof", p); return p; diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java index f4f18d3eb5..75d35854d5 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java @@ -13,7 +13,7 @@ import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.api.proofs.ProofRule; -import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; +import org.sosy_lab.java_smt.basicimpl.AbstractProofDag.AbstractProofNode; public class CVC5ProofNode extends AbstractProofNode { diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java index de034c7f91..19c7dadaf3 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java @@ -26,16 +26,17 @@ import org.sosy_lab.java_smt.api.proofs.ProofFrame; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.api.proofs.ProofRule; -import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; +import org.sosy_lab.java_smt.basicimpl.AbstractProofDag.AbstractProofNode; -public class Mathsat5ProofNode extends AbstractProofNode { + public class Mathsat5ProofNode extends AbstractProofNode { - public Mathsat5ProofNode(ProofRule rule, Formula formula) { + protected Mathsat5ProofNode(ProofRule rule, Formula formula) { super(rule, formula); } - protected static class MsatProofFrame extends ProofFrame { - public MsatProofFrame(Long proof) { + + protected static class MsatProofFrame extends ProofFrame { + MsatProofFrame(Long proof) { super(proof); } } @@ -101,7 +102,7 @@ private static Formula generateFormula(long proof, Mathsat5TheoremProver prover) return formula; } - public String asString() { + String asString() { return asString(0); } diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofProcessor.java deleted file mode 100644 index a11e97f96c..0000000000 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofProcessor.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * This file is part of JavaSMT, - * an API wrapper for a collection of SMT solvers: - * https://github.com/sosy-lab/java-smt - * - * SPDX-FileCopyrightText: 2024 Dirk Beyer - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.sosy_lab.java_smt.solvers.mathsat5; - -import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_get_arity; -import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_get_child; -import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_get_name; -import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_get_term; -import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_is_term; - -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.HashMap; -import java.util.Map; -import javax.annotation.Nullable; -import org.sosy_lab.java_smt.api.Formula; - -public class Mathsat5ProofProcessor { - private final Mathsat5SolverContext context; - private final long curEnv; - private final Mathsat5FormulaCreator formulaCreator; - private final Mathsat5TheoremProver theoremProver; - - Mathsat5ProofProcessor( - Mathsat5SolverContext ctx, - long pCurEnv, - Mathsat5FormulaCreator creator, - Mathsat5TheoremProver prover) { - context = ctx; - curEnv = pCurEnv; - formulaCreator = creator; - theoremProver = prover; - } - - public Mathsat5ProofNode fromMsatProof(long rootProof) { - Deque stack = new ArrayDeque<>(); - Map computed = new HashMap<>(); - - stack.push(new Frame(rootProof)); - - while (!stack.isEmpty()) { - Frame frame = stack.peek(); - - if (!frame.visited) { - frame.numArgs = msat_proof_get_arity(frame.proof); - frame.visited = true; - // Push children first so that the leaves are processed first. - for (int i = 0; i < frame.numArgs; i++) { - long child = msat_proof_get_child(frame.proof, i); - if (!computed.containsKey(child)) { - stack.push(new Frame(child)); - } - } - } else { - // Process the node after all its children have been processed. This should help to - // recreate the formula for the node correctly. - stack.pop(); - - // Generate the formula and proof rule. - Formula formula = generateFormula(frame.proof); - Mathsat5ProofRule proofRule = new Mathsat5ProofRule(msat_proof_get_name(frame.proof)); - Mathsat5ProofNode node = new Mathsat5ProofNode(proofRule, formula); - - // Retrieve computed child nodes and attach them. - for (int i = 0; i < frame.numArgs; i++) { - long child = msat_proof_get_child(frame.proof, i); - Mathsat5ProofNode childNode = computed.get(child); - if (childNode != null) { - node.addChild(childNode); - } - } - computed.put(frame.proof, node); - } - } - return computed.get(rootProof); - } - - @Nullable - private Formula generateFormula(long proof) { - Formula formula = null; - if (msat_proof_is_term(proof)) { - long proofTerm = msat_proof_get_term(proof); - formula = formulaCreator.encapsulate(formulaCreator.getFormulaType(proofTerm), proofTerm); - } - return formula; - } - - private static class Frame { - final long proof; - int numArgs; - boolean visited; - - Frame(long proof) { - this.proof = proof; - this.visited = false; - } - } -} diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java index 94da0fbcf1..916c2b2ba1 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java @@ -22,7 +22,10 @@ import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; +import org.sosy_lab.java_smt.api.SolverException; import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.basicimpl.ProofFactory; + class Mathsat5TheoremProver extends Mathsat5AbstractProver implements ProverEnvironment { @@ -49,13 +52,35 @@ protected Void addConstraintImpl(BooleanFormula constraint) throws InterruptedEx } @Override - public ProofNode getProof() { + public ProofNode getProof() throws SolverException, InterruptedException { + Preconditions.checkState(!closed); + Preconditions.checkState(this.isUnsat()); + + ProofNode pn; long pm = msat_get_proof_manager(curEnv); - // ProofFactory proofFactory = new ProofFactory(); - Mathsat5ProofProcessor pp = new Mathsat5ProofProcessor(context, curEnv, creator, this); - pn = pp.fromMsatProof(msat_get_proof(pm)); + long proof = msat_get_proof(pm); + pn = Mathsat5ProofNode.fromMsatProof(this, proof); msat_destroy_proof_manager(pm); + return pn; + + + + //return getProof0(); } + + protected ProofNode getProof0() { + var proofFactory = new ProofFactory(this.creator, this, "MATHSAT5") { + public ProofNode createProofWrapper(long pProof) { + return this.createProofNode(pProof); + } + }; + long pm = msat_get_proof_manager(curEnv); + long proof = msat_get_proof(pm); + ProofNode pn = proofFactory.createProofWrapper(proof); + msat_destroy_proof_manager(pm); + return pn; + } + } From 4dbc7eca7c654b34cfb5263ec0da08c2467cbedf Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sat, 29 Mar 2025 22:19:38 +0100 Subject: [PATCH 054/132] Mathsat5: `getProof` now checks if the state is closed and the stack evaluates to `unsat`. --- .../sosy_lab/java_smt/ResolutionProofDag.java | 1 - .../proofs => basicimpl}/ProofFactory.java | 28 +-- .../StatisticsBasicProverEnvironment.java | 2 +- .../SynchronizedBasicProverEnvironment.java | 2 +- ...izedBasicProverEnvironmentWithContext.java | 2 +- .../z3/Z3NonRecursiveProofProcessor.java | 13 +- .../java_smt/solvers/z3/Z3ProofDag.java | 35 +++- .../java_smt/solvers/z3/Z3ProofNode.java | 34 ---- .../java_smt/solvers/z3/Z3ProofProcessor.java | 178 ------------------ .../java_smt/solvers/z3/Z3ProofsTest.java | 25 +-- .../z3/Z3ToResoluteProofConverter.java | 100 +++++----- .../test/SolverThreadLocalityTest.java | 4 +- 12 files changed, 119 insertions(+), 305 deletions(-) rename src/org/sosy_lab/java_smt/{api/proofs => basicimpl}/ProofFactory.java (73%) delete mode 100644 src/org/sosy_lab/java_smt/solvers/z3/Z3ProofNode.java delete mode 100644 src/org/sosy_lab/java_smt/solvers/z3/Z3ProofProcessor.java diff --git a/src/org/sosy_lab/java_smt/ResolutionProofDag.java b/src/org/sosy_lab/java_smt/ResolutionProofDag.java index f8c6bc15f0..f5cfa07162 100644 --- a/src/org/sosy_lab/java_smt/ResolutionProofDag.java +++ b/src/org/sosy_lab/java_smt/ResolutionProofDag.java @@ -16,7 +16,6 @@ import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.basicimpl.AbstractProofDag; -import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; /** * This class represents a resolution proof DAG. Its nodes might be of the type {@link diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java b/src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java similarity index 73% rename from src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java rename to src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java index 1edfab4998..9babee6522 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java +++ b/src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java @@ -8,15 +8,18 @@ * SPDX-License-Identifier: Apache-2.0 */ -package org.sosy_lab.java_smt.api.proofs; +package org.sosy_lab.java_smt.basicimpl; +import io.github.cvc5.Proof; import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.ResolutionProofDag.ResolutionProofNode; import org.sosy_lab.java_smt.ResolutionProofDag.AxiomProofNode; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.ProverEnvironment; -import org.sosy_lab.java_smt.basicimpl.FormulaCreator; +import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5ProofNode; +import org.sosy_lab.java_smt.solvers.z3.Z3ProofDag; /** * A factory for creating proof nodes. The methods of this class are to be used in the ProofNode @@ -44,20 +47,21 @@ enum Solvers { BITWUZLA } - ProofFactory( + protected ProofFactory( FormulaCreator pCreator, ProverEnvironment pProver, - ProofFactory.Solvers pSolver) { + String pSolver) { formulaCreator = pCreator; prover = pProver; - solver = pSolver; + solver = Solvers.valueOf(pSolver); } - ProofNode createProofNode(T proof) { - return createProofNode0(proof); + protected ProofNode createProofNode(T proof) { + return createProofNode0(proof); } - ProofNode createProofNode0(T proof) { + protected ProofNode createProofNode0(T proof) { + switch (solver) { case MATHSAT5: return Mathsat5ProofNode.fromMsatProof(prover, (long) proof); @@ -66,17 +70,15 @@ ProofNode createProofNode0(T proof) { default: throw new UnsupportedOperationException("Unsupported solver: " + solver); } - } - static ProofNode createRresoluteNode() { - return null; + } - static ProofNode createSourceNode(ResAxiom rule, Formula formula) { + protected static ProofNode createSourceNode(ResAxiom rule, Formula formula) { return new AxiomProofNode(rule, formula); } - static ProofNode createResolutionNode(Formula formula, Formula pivot) { + protected static ProofNode createResolutionNode(Formula formula, Formula pivot) { return new ResolutionProofNode(formula, pivot); } } diff --git a/src/org/sosy_lab/java_smt/delegate/statistics/StatisticsBasicProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/statistics/StatisticsBasicProverEnvironment.java index 433624b01a..70b6ccf74d 100644 --- a/src/org/sosy_lab/java_smt/delegate/statistics/StatisticsBasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/delegate/statistics/StatisticsBasicProverEnvironment.java @@ -101,7 +101,7 @@ public Optional> unsatCoreOverAssumptions( } @Override - public ProofNode getProof() { + public ProofNode getProof() throws SolverException, InterruptedException { return delegate.getProof(); } diff --git a/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedBasicProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedBasicProverEnvironment.java index fcb58d7b90..b258c71b36 100644 --- a/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedBasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedBasicProverEnvironment.java @@ -106,7 +106,7 @@ public ImmutableMap getStatistics() { } @Override - public ProofNode getProof() { + public ProofNode getProof() throws SolverException, InterruptedException { return delegate.getProof(); } diff --git a/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedBasicProverEnvironmentWithContext.java b/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedBasicProverEnvironmentWithContext.java index bd7d04162f..364e37af49 100644 --- a/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedBasicProverEnvironmentWithContext.java +++ b/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedBasicProverEnvironmentWithContext.java @@ -123,7 +123,7 @@ public ImmutableMap getStatistics() { } @Override - public ProofNode getProof() { + public ProofNode getProof() throws SolverException, InterruptedException { return delegate.getProof(); } diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java index 38deb32ebe..5aee1d15b2 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java @@ -26,9 +26,9 @@ * non-(java-)recursive implementation of the proof processor.# * *

The resulting DAG from transforming the proof from the Z3 provided structures into a set of - * {@link Z3ProofNode} should enable an easier way to extract the information from the proofs. + * {@link Z3ProofDag.Z3ProofNode} should enable an easier way to extract the information from the proofs. * However, some information is lost from the original proof, as the Z3 provided proof makes uses of - * more general structures like AST, SortKind, DeclKind. E.g. the leafs in the {@link Z3ProofNode} + * more general structures like AST, SortKind, DeclKind. E.g. the leafs in the {@link Z3ProofDag.Z3ProofNode} * contain the whole formula used for the first proof rules in the tree, while these are internal * nodes in the Z3 proof and leafs are the operands use in innermost terms. */ @@ -47,12 +47,12 @@ class Z3NonRecursiveProofProcessor { prover = pProver; } - Z3ProofNode fromASTIterative(long rootProof) { + Z3ProofDag.Z3ProofNode fromASTIterative(long rootProof) { // proof ast to be processed wrapped inside a frame Deque stack = new ArrayDeque<>(); // proof ast has been converted into ProofNode - Map computed = new HashMap<>(); + Map computed = new HashMap<>(); stack.push(new Frame(rootProof)); @@ -96,7 +96,7 @@ Z3ProofNode fromASTIterative(long rootProof) { } int declKind = Native.getDeclKind(z3context, Native.getAppDecl(z3context, frame.proof)); ProofRule proofRule = getPRfromDK(declKind); - Z3ProofNode node = new Z3ProofNode(formula, proofRule); + Z3ProofDag.Z3ProofNode node = new Z3ProofDag.Z3ProofNode(formula, proofRule); for (int i = 0; i < numArgs - 1; i++) { long arg = Native.getAppArg(z3context, frame.proof, i); @@ -114,7 +114,8 @@ Z3ProofNode fromASTIterative(long rootProof) { private ProofRule getPRfromDK(int declKind) { String rawName = Z3_decl_kind.fromInt(declKind).name(); String prName = rawName.replaceFirst("Z3_OP_PR_", ""); - return ProofRuleRegistry.fromName(Z3ProofRule.class, prName); + return ProofRule.fromName(Z3ProofRule.class, prName); + //return ProofRuleRegistry.fromName(Z3ProofRule.class, prName); } private Formula generateFormula(long proof) { diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDag.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDag.java index e008ce8c92..06cbe773d0 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDag.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDag.java @@ -10,6 +10,39 @@ package org.sosy_lab.java_smt.solvers.z3; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.basicimpl.AbstractProofDag; -public class Z3ProofDag extends AbstractProofDag {} +public class Z3ProofDag extends AbstractProofDag { + public static class Z3ProofNode extends AbstractProofNode { + + Z3ProofNode(Formula pFormula, ProofRule pProofRule) { + super(pProofRule, pFormula); + } + + String asString() { + return asString(0); + } + + private String asString(int indentLevel) { + StringBuilder proof = new StringBuilder(); + String indent = " ".repeat(indentLevel); + + proof.append(indent).append("Formula: ").append(getFormula().toString()).append("\n"); + proof.append(indent).append("Rule: ").append(getRule().getName()).append("\n"); + proof.append(indent).append("No. Children: ").append(getChildren().size()).append("\n"); + proof.append(indent).append("ID: ").append(getId()).append("\n"); + proof.append(indent).append("leaf: ").append(isLeaf()).append("\n"); + + int i = 0; + for (ProofNode child : getChildren()) { + proof.append(indent).append("Child ").append(++i).append(":\n"); + proof.append(((Z3ProofNode) child).asString(indentLevel + 1)); + } + + return proof.toString(); + } + } +} diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofNode.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofNode.java deleted file mode 100644 index 26fda40dfd..0000000000 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofNode.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.sosy_lab.java_smt.solvers.z3; - -import org.sosy_lab.java_smt.api.Formula; -import org.sosy_lab.java_smt.api.proofs.ProofNode; -import org.sosy_lab.java_smt.api.proofs.ProofRule; -import org.sosy_lab.java_smt.basicimpl.AbstractProofNode; - -class Z3ProofNode extends AbstractProofNode { - - Z3ProofNode(Formula pFormula, ProofRule pProofRule) { - super(pProofRule, pFormula); - } - - String asString() { - return asString(0); - } - - private String asString(int indentLevel) { - StringBuilder proof = new StringBuilder(); - String indent = " ".repeat(indentLevel); - - proof.append(indent).append("Formula: ").append(getFormula().toString()).append("\n"); - proof.append(indent).append("Rule: ").append(getRule().getName()).append("\n"); - proof.append(indent).append("No. Children: ").append(getChildren().size()).append("\n"); - - int i = 0; - for (ProofNode child : getChildren()) { - proof.append(indent).append("Child ").append(++i).append(":\n"); - proof.append(((Z3ProofNode) child).asString(indentLevel + 1)); - } - - return proof.toString(); - } -} diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofProcessor.java deleted file mode 100644 index f42140c6a1..0000000000 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofProcessor.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * This file is part of JavaSMT, - * an API wrapper for a collection of SMT solvers: - * https://github.com/sosy-lab/java-smt - * - * SPDX-FileCopyrightText: 2024 Dirk Beyer - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.sosy_lab.java_smt.solvers.z3; - -import com.microsoft.z3.Native; -import com.microsoft.z3.enumerations.Z3_decl_kind; -import com.microsoft.z3.enumerations.Z3_sort_kind; -import java.util.HashMap; -import java.util.Map; -import org.sosy_lab.java_smt.api.Formula; - -// This class uses java recursion and as such, Z3NonRecursiveProofProcessor.java is preferred -@SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) -class Z3ProofProcessor { - private final long z3context; - private final long z3solver; - private final Z3FormulaCreator formulaCreator; - private final Z3AbstractProver prover; - private final Map parsed = new HashMap<>(); - - Z3ProofProcessor(long ctx, long solver, Z3FormulaCreator creator, Z3AbstractProver pProver) { - z3context = ctx; - z3solver = solver; - formulaCreator = creator; - prover = pProver; - } - - Z3ProofNode fromAST(long proof) { - if (parsed.containsKey(proof)) { - return parsed.get(proof); - } - - Native.incRef(z3context, proof); - long sort = Native.getSort(z3context, proof); - long sortKind = Native.getSortKind(z3context, sort); - int declKind = Native.getDeclKind(z3context, Native.getAppDecl(z3context, proof)); - int numArgs = Native.getAppNumArgs(z3context, proof); - Z3_sort_kind sort_kind = Z3_sort_kind.fromInt((int) sortKind); - Formula formula; - Z3ProofRule proofRule; - - if (sort_kind != Z3_sort_kind.Z3_UNKNOWN_SORT) { - formula = generateFormula(proof); - } else { - - long z3expr = Native.getAppArg(z3context, proof, numArgs - 1); - formula = generateFormula(z3expr); - } - proofRule = getPRfromDK(declKind); - Z3ProofNode proofNode = new Z3ProofNode(formula, proofRule); - parsed.put(proof, proofNode); - - for (int i = 0; i < numArgs - 1; i++) { - long arg = Native.getAppArg(z3context, proof, i); - proofNode.addChild(fromAST(arg)); - } - Native.decRef(z3context, proof); - return proofNode; - } - - private Z3ProofRule getPRfromDK(int declKind) { - Z3_decl_kind dk = Z3_decl_kind.fromInt(declKind); - switch (dk) { - case Z3_OP_PR_UNDEF: - return Z3ProofRule.UNDEF; - - case Z3_OP_PR_TRUE: - return Z3ProofRule.TRUE; - - case Z3_OP_PR_ASSERTED: - return Z3ProofRule.ASSERTED; - - case Z3_OP_PR_GOAL: - return Z3ProofRule.GOAL; - - case Z3_OP_PR_MODUS_PONENS: - return Z3ProofRule.MODUS_PONENS; - - case Z3_OP_PR_REFLEXIVITY: - return Z3ProofRule.REFLEXIVITY; - - case Z3_OP_PR_SYMMETRY: - return Z3ProofRule.SYMMETRY; - - case Z3_OP_PR_TRANSITIVITY: - return Z3ProofRule.TRANSITIVITY; - - case Z3_OP_PR_TRANSITIVITY_STAR: - return Z3ProofRule.TRANSITIVITY_STAR; - case Z3_OP_PR_MONOTONICITY: - return Z3ProofRule.MONOTONICITY; - case Z3_OP_PR_QUANT_INTRO: - return Z3ProofRule.QUANT_INTRO; - case Z3_OP_PR_BIND: - return Z3ProofRule.BIND; - case Z3_OP_PR_DISTRIBUTIVITY: - return Z3ProofRule.DISTRIBUTIVITY; - case Z3_OP_PR_AND_ELIM: - return Z3ProofRule.AND_ELIM; - case Z3_OP_PR_NOT_OR_ELIM: - return Z3ProofRule.NOT_OR_ELIM; - case Z3_OP_PR_REWRITE: - return Z3ProofRule.REWRITE; - case Z3_OP_PR_REWRITE_STAR: - return Z3ProofRule.REWRITE_STAR; - case Z3_OP_PR_PULL_QUANT: - return Z3ProofRule.PULL_QUANT; - case Z3_OP_PR_PUSH_QUANT: - return Z3ProofRule.PUSH_QUANT; - case Z3_OP_PR_ELIM_UNUSED_VARS: - return Z3ProofRule.ELIM_UNUSED_VARS; - case Z3_OP_PR_DER: - return Z3ProofRule.DER; - case Z3_OP_PR_QUANT_INST: - return Z3ProofRule.QUANT_INST; - case Z3_OP_PR_HYPOTHESIS: - return Z3ProofRule.HYPOTHESIS; - case Z3_OP_PR_LEMMA: - return Z3ProofRule.LEMMA; - case Z3_OP_PR_UNIT_RESOLUTION: - return Z3ProofRule.UNIT_RESOLUTION; - case Z3_OP_PR_IFF_TRUE: - return Z3ProofRule.IFF_TRUE; - case Z3_OP_PR_IFF_FALSE: - return Z3ProofRule.IFF_FALSE; - case Z3_OP_PR_COMMUTATIVITY: - return Z3ProofRule.COMMUTATIVITY; - case Z3_OP_PR_DEF_AXIOM: - return Z3ProofRule.DEF_AXIOM; - case Z3_OP_PR_ASSUMPTION_ADD: - return Z3ProofRule.ASSUMPTION_ADD; - case Z3_OP_PR_LEMMA_ADD: - return Z3ProofRule.LEMMA_ADD; - case Z3_OP_PR_REDUNDANT_DEL: - return Z3ProofRule.REDUNDANT_DEL; - case Z3_OP_PR_CLAUSE_TRAIL: - return Z3ProofRule.CLAUSE_TRAIL; - case Z3_OP_PR_DEF_INTRO: - return Z3ProofRule.DEF_INTRO; - case Z3_OP_PR_APPLY_DEF: - return Z3ProofRule.APPLY_DEF; - case Z3_OP_PR_IFF_OEQ: - return Z3ProofRule.IFF_OEQ; - case Z3_OP_PR_NNF_POS: - return Z3ProofRule.NNF_POS; - case Z3_OP_PR_NNF_NEG: - return Z3ProofRule.NNF_NEG; - case Z3_OP_PR_SKOLEMIZE: - return Z3ProofRule.SKOLEMIZE; - case Z3_OP_PR_MODUS_PONENS_OEQ: - return Z3ProofRule.MODUS_PONENS_OEQ; - case Z3_OP_PR_TH_LEMMA: - return Z3ProofRule.TH_LEMMA; - case Z3_OP_PR_HYPER_RESOLVE: - return Z3ProofRule.HYPER_RESOLVE; - default: - return Z3ProofRule.OPERATION; - } - } - - - private Formula generateFormula(long proof) { - Formula formula = null; - // Formula formula = getFromStoredConstraints(proof); - if (formula == null) { - formula = formulaCreator.encapsulate(formulaCreator.getFormulaType(proof), proof); - } - return formula; - } -} diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java index 3d03255f4f..73063e1e15 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java @@ -4,29 +4,20 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import com.microsoft.z3.*; -import com.microsoft.z3.Context; -import com.microsoft.z3.Solver; -import java.lang.reflect.Constructor; -import java.util.HashMap; -import java.util.Set; import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; -import org.sosy_lab.common.NativeLibraries; import org.sosy_lab.common.ShutdownManager; import org.sosy_lab.common.configuration.Configuration; import org.sosy_lab.common.log.BasicLogManager; import org.sosy_lab.common.log.LogManager; import org.sosy_lab.java_smt.SolverContextFactory; import org.sosy_lab.java_smt.api.BooleanFormula; -import org.sosy_lab.java_smt.api.FloatingPointRoundingMode; import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.SolverContext; import org.sosy_lab.java_smt.api.SolverException; import org.sosy_lab.java_smt.api.proofs.ProofNode; -import org.sosy_lab.java_smt.basicimpl.AbstractNumeralFormulaManager.NonLinearArithmetic; @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) @Ignore("prevent this class being executed as testcase by ant") @@ -87,13 +78,13 @@ public void closeSolver() { } @Test - public void getProofTest() throws InterruptedException { + public void getProofTest() throws InterruptedException, SolverException { ProofNode proof = q1q2prover.getProof(); assertThat(proof).isNotNull(); } @Test - public void getChildrenTest() { + public void getChildrenTest() throws SolverException, InterruptedException { ProofNode proof = q1q2prover.getProof(); assertThat(proof).isNotNull(); assertThat(proof.getChildren()).isNotEmpty(); @@ -101,7 +92,7 @@ public void getChildrenTest() { } @Test - public void getProofRuleTest() { + public void getProofRuleTest() throws SolverException, InterruptedException { ProofNode proof = q1q2prover.getProof(); assertThat(proof).isNotNull(); assertThat(proof.getRule()).isNotNull(); @@ -109,7 +100,7 @@ public void getProofRuleTest() { } @Test - public void getFormulaTest() { + public void getFormulaTest() throws SolverException, InterruptedException { ProofNode proof = q1q2prover.getProof(); assertThat(proof).isNotNull(); assertThat(proof.getFormula()).isNotNull(); @@ -120,7 +111,7 @@ public void getFormulaTest() { public void getProofTermTest() throws SolverException, InterruptedException { ProofNode proof = q1q2prover.getProof(); - System.out.println(((Z3ProofNode) proof).asString()); + System.out.println(((Z3ProofDag.Z3ProofNode) proof).asString()); } @Test @@ -132,9 +123,9 @@ public void Z3handleTransitivityTest() { BooleanFormula equiv2 = bmgr.equivalence(f2, f3); BooleanFormula equiv3 = bmgr.equivalence(f1, f3); - Z3ProofNode pn = new Z3ProofNode(equiv3, Z3ProofRule.TRANSITIVITY); - pn.addChild(new Z3ProofNode(equiv1, Z3ProofRule.ASSERTED)); - pn.addChild(new Z3ProofNode(equiv2, Z3ProofRule.ASSERTED)); + Z3ProofDag.Z3ProofNode pn = new Z3ProofDag.Z3ProofNode(equiv3, Z3ProofRule.TRANSITIVITY); + pn.addChild(new Z3ProofDag.Z3ProofNode(equiv1, Z3ProofRule.ASSERTED)); + pn.addChild(new Z3ProofDag.Z3ProofNode(equiv2, Z3ProofRule.ASSERTED)); diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java index 3c08700471..4e7c8a7531 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java @@ -65,10 +65,10 @@ public class Z3ToResoluteProofConverter { // This class is inclompete and curren * @param z3ProofNodes * @return {@link ResolutionProofDag} */ - static ResolutionProofDag convertToResolutionProofDag(Z3ProofNode[] z3ProofNodes) { + static ResolutionProofDag convertToResolutionProofDag(Z3ProofDag.Z3ProofNode[] z3ProofNodes) { ResolutionProofDag dag = new ResolutionProofDag(); - for (Z3ProofNode z3Node : z3ProofNodes) { + for (Z3ProofDag.Z3ProofNode z3Node : z3ProofNodes) { if (z3Node.getRule() == MODUS_PONENS) { } else { @@ -161,13 +161,13 @@ public List extractEquivalenceOperands(BooleanFormula formula) { } /** - * Converts a {@link Z3ProofNode} into either a {@link ResolutionProofNode} or a {@link + * Converts a {@link Z3ProofDag.Z3ProofNode} into either a {@link ResolutionProofNode} or a {@link * AxiomProofNode}, depending on its rule. * - * @param node the {@link Z3ProofNode} to convert + * @param node the {@link Z3ProofDag.Z3ProofNode} to convert * @return the resulting {@link ProofNode} */ - ProofNode handleNode(Z3ProofNode node) { + ProofNode handleNode(Z3ProofDag.Z3ProofNode node) { Z3ProofRule rule = (Z3ProofRule) node.getRule(); switch (rule) { @@ -302,34 +302,34 @@ ProofNode handleNode(Z3ProofNode node) { } } - ProofNode handleTrue(Z3ProofNode node) { + ProofNode handleTrue(Z3ProofDag.Z3ProofNode node) { BooleanFormula formula = (BooleanFormula) node.getFormula(); AxiomProofNode pn = new AxiomProofNode(ResAxiom.TRUE_POSITIVE, formula); return pn; } - ProofNode handleAsserted(Z3ProofNode node) { + ProofNode handleAsserted(Z3ProofDag.Z3ProofNode node) { BooleanFormula formula = (BooleanFormula) node.getFormula(); AxiomProofNode pn = new AxiomProofNode(ResAxiom.ASSUME, formula); return pn; } - ProofNode handleModusPonens(Z3ProofNode node) { + ProofNode handleModusPonens(Z3ProofDag.Z3ProofNode node) { BooleanFormula formula = (BooleanFormula) node.getFormula(); BooleanFormula pivot = (BooleanFormula) node.getChildren().get(0).getFormula(); ResolutionProofNode pn = new ResolutionProofNode(formula, pivot); - ProofNode c1 = handleNode((Z3ProofNode) node.getChildren().get(0)); - ProofNode c2 = handleNode((Z3ProofNode) node.getChildren().get(1)); + ProofNode c1 = handleNode((Z3ProofDag.Z3ProofNode) node.getChildren().get(0)); + ProofNode c2 = handleNode((Z3ProofDag.Z3ProofNode) node.getChildren().get(1)); return pn; } - ProofNode handleReflexivity(Z3ProofNode node) { + ProofNode handleReflexivity(Z3ProofDag.Z3ProofNode node) { BooleanFormula formula = (BooleanFormula) node.getFormula(); AxiomProofNode pn = new AxiomProofNode(ResAxiom.REFLEXIVITY, formula); return pn; } - ProofNode handleSymmetry(Z3ProofNode node) { + ProofNode handleSymmetry(Z3ProofDag.Z3ProofNode node) { BooleanFormula formula = (BooleanFormula) node.getFormula(); BooleanFormula pivot = (BooleanFormula) node.getChildren().get(0).getFormula(); BooleanFormula snFormula = bfm.or(bfm.not(pivot), formula); @@ -337,11 +337,11 @@ ProofNode handleSymmetry(Z3ProofNode node) { ResolutionProofNode pn = new ResolutionProofNode(formula, pivot); AxiomProofNode sn = new AxiomProofNode(ResAxiom.SYMMETRY, snFormula); pn.addChild(sn); - pn.addChild(handleNode((Z3ProofNode) node.getChildren().get(0))); + pn.addChild(handleNode((Z3ProofDag.Z3ProofNode) node.getChildren().get(0))); return pn; } - ProofNode handleTransitivity(Z3ProofNode node) { + ProofNode handleTransitivity(Z3ProofDag.Z3ProofNode node) { BooleanFormula t1 = (BooleanFormula) node.getChildren().get(0).getFormula(); BooleanFormula t2 = (BooleanFormula) node.getChildren().get(1).getFormula(); @@ -371,7 +371,7 @@ ProofNode handleTransitivity(Z3ProofNode node) { return transResNode; } - ProofNode handleTransitivityStar(Z3ProofNode node) { + ProofNode handleTransitivityStar(Z3ProofDag.Z3ProofNode node) { BooleanFormula resPivot = null; Collection formulas = new ArrayList<>(); List> formulaList = new ArrayList<>(); @@ -400,143 +400,143 @@ ProofNode handleTransitivityStar(Z3ProofNode node) { return resNode; } - ProofNode handleMonotonicity(Z3ProofNode node) { + ProofNode handleMonotonicity(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleQuantIntro(Z3ProofNode node) { + ProofNode handleQuantIntro(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleBind(Z3ProofNode node) { + ProofNode handleBind(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleDistributivity(Z3ProofNode node) { + ProofNode handleDistributivity(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleAndElim(Z3ProofNode node) { + ProofNode handleAndElim(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleNotOrElim(Z3ProofNode node) { + ProofNode handleNotOrElim(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleRewrite(Z3ProofNode node) { + ProofNode handleRewrite(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleRewriteStar(Z3ProofNode node) { + ProofNode handleRewriteStar(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handlePullQuant(Z3ProofNode node) { + ProofNode handlePullQuant(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleElimUnusedVars(Z3ProofNode node) { + ProofNode handleElimUnusedVars(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handlePushQuant(Z3ProofNode node) { + ProofNode handlePushQuant(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleDer(Z3ProofNode node) { + ProofNode handleDer(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleQuantInst(Z3ProofNode node) { + ProofNode handleQuantInst(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleHypothesis(Z3ProofNode node) { + ProofNode handleHypothesis(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleLemma(Z3ProofNode node) { + ProofNode handleLemma(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleUnitResolution(Z3ProofNode node) { + ProofNode handleUnitResolution(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleIffTrue(Z3ProofNode node) { + ProofNode handleIffTrue(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleIffFalse(Z3ProofNode node) { + ProofNode handleIffFalse(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleCommutativity(Z3ProofNode node) { + ProofNode handleCommutativity(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleDefAxiom(Z3ProofNode node) { + ProofNode handleDefAxiom(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleAssumptionAdd(Z3ProofNode node) { + ProofNode handleAssumptionAdd(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleLemmaAdd(Z3ProofNode node) { + ProofNode handleLemmaAdd(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleRedundantDel(Z3ProofNode node) { + ProofNode handleRedundantDel(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleClauseTrail(Z3ProofNode node) { + ProofNode handleClauseTrail(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleDefIntro(Z3ProofNode node) { + ProofNode handleDefIntro(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleApplyDef(Z3ProofNode node) { + ProofNode handleApplyDef(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleIffOeq(Z3ProofNode node) { + ProofNode handleIffOeq(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleNnfPos(Z3ProofNode node) { + ProofNode handleNnfPos(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleNnfNeg(Z3ProofNode node) { + ProofNode handleNnfNeg(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleSkolemize(Z3ProofNode node) { + ProofNode handleSkolemize(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleModusPonensOeq(Z3ProofNode node) { + ProofNode handleModusPonensOeq(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleThLemma(Z3ProofNode node) { + ProofNode handleThLemma(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleHyperResolve(Z3ProofNode node) { + ProofNode handleHyperResolve(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleOperation(Z3ProofNode node) { + ProofNode handleOperation(Z3ProofDag.Z3ProofNode node) { return null; } - ProofNode handleDefault(Z3ProofNode node) { + ProofNode handleDefault(Z3ProofDag.Z3ProofNode node) { return null; } diff --git a/src/org/sosy_lab/java_smt/test/SolverThreadLocalityTest.java b/src/org/sosy_lab/java_smt/test/SolverThreadLocalityTest.java index 654788f28c..5e37b89ad4 100644 --- a/src/org/sosy_lab/java_smt/test/SolverThreadLocalityTest.java +++ b/src/org/sosy_lab/java_smt/test/SolverThreadLocalityTest.java @@ -161,7 +161,7 @@ public void nonLocalProverTest() throws InterruptedException, ExecutionException // (Solver.java:1455) // at org.sosy_lab.java_smt.solvers.cvc5.CVC5AbstractProver.addConstraintImpl // (CVC5AbstractProver.java:114) - // at org.sosy_lab.java_smt.basicimpl.AbstractProver.addConstraint + // at org.sosy_lab.java_smt.basicimpl.AbstractProofDag.AbstractProver.addConstraint // (AbstractProver.java:108) // at .. prover.push(formula); @@ -283,7 +283,7 @@ public void nonLocalInterpolationTest() throws InterruptedException, Executi // You tried to use push() on an CVC5 assertion stack illegally. // at org.sosy_lab.java_smt.solvers.cvc5.CVC5AbstractProver.pushImpl // (CVC5AbstractProver.java:89) - // at org.sosy_lab.java_smt.basicimpl.AbstractProver.push + // at org.sosy_lab.java_smt.basicimpl.AbstractProofDag.AbstractProver.push // (AbstractProver.java:88) // at .. prover.push(f2); From 2aa8f25713dcd7939c3286a29980b17943d465ad Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sat, 29 Mar 2025 22:21:31 +0100 Subject: [PATCH 055/132] Checkstyle --- .../sosy_lab/java_smt/ProofRuleRegistry.java | 1 - .../sosy_lab/java_smt/ResolutionProofDag.java | 1 - .../java_smt/api/BasicProverEnvironment.java | 7 ++-- .../java_smt/basicimpl/AbstractProofDag.java | 5 +-- .../java_smt/basicimpl/AbstractProver.java | 4 --- .../java_smt/basicimpl/ProofFactory.java | 13 ++----- .../java_smt/solvers/cvc5/CVC5ProofNode.java | 2 +- .../solvers/cvc5/CVC5ProofProcessor.java | 10 +++--- .../java_smt/solvers/cvc5/CVC5ProofRule.java | 3 -- .../java_smt/solvers/cvc5/CVC5ProofsTest.java | 17 ++++----- .../solvers/mathsat5/Mathsat5ProofNode.java | 11 +++--- .../mathsat5/Mathsat5TheoremProver.java | 34 ++++++++---------- .../z3/Z3NonRecursiveProofProcessor.java | 13 ++++--- .../java_smt/solvers/z3/Z3ProofDag.java | 4 +-- .../java_smt/solvers/z3/Z3ProofRule.java | 1 - .../java_smt/solvers/z3/Z3ProofsTest.java | 36 +++++++++---------- .../java_smt/solvers/z3/Z3TheoremProver.java | 3 +- .../z3/Z3ToResoluteProofConverter.java | 2 +- .../test/SolverThreadLocalityTest.java | 3 +- 19 files changed, 73 insertions(+), 97 deletions(-) diff --git a/src/org/sosy_lab/java_smt/ProofRuleRegistry.java b/src/org/sosy_lab/java_smt/ProofRuleRegistry.java index 0e0f050306..4cd19080d4 100644 --- a/src/org/sosy_lab/java_smt/ProofRuleRegistry.java +++ b/src/org/sosy_lab/java_smt/ProofRuleRegistry.java @@ -35,7 +35,6 @@ public static ProofRule fromName(Class clazz, String name) } static { - for (CVC5ProofRule rule : CVC5ProofRule.values()) { ProofRuleRegistry.register(CVC5ProofRule.class, rule); } diff --git a/src/org/sosy_lab/java_smt/ResolutionProofDag.java b/src/org/sosy_lab/java_smt/ResolutionProofDag.java index f5cfa07162..b11597a794 100644 --- a/src/org/sosy_lab/java_smt/ResolutionProofDag.java +++ b/src/org/sosy_lab/java_smt/ResolutionProofDag.java @@ -55,6 +55,5 @@ public AxiomProofNode(ResAxiom rule, Formula formula) { Objects.requireNonNull(rule, "Rule must not be null"), Objects.requireNonNull(formula, "Formula must not be null")); } - } } diff --git a/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java b/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java index 2bc252f172..a2915f40fd 100644 --- a/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java @@ -154,9 +154,10 @@ default ImmutableMap getStatistics() { * Get proof of unsatisfiability of the conjuction of the current satck of all formulas. Should * only be called after {@link #isUnsat()} returned true. */ - default ProofNode getProof() throws SolverException, InterruptedException { - throw new UnsupportedOperationException("Proof generation is not available for the current solver."); - } + default ProofNode getProof() throws SolverException, InterruptedException { + throw new UnsupportedOperationException( + "Proof generation is not available for the current solver."); + } /** * Closes the prover environment. The object should be discarded, and should not be used after diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java index b1aaf4668d..8a444b54c2 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java @@ -10,7 +10,6 @@ package org.sosy_lab.java_smt.basicimpl; -import static com.google.common.base.Preconditions.checkState; import java.util.ArrayList; import java.util.Collection; @@ -20,7 +19,6 @@ import java.util.Map; import org.sosy_lab.common.UniqueIdGenerator; import org.sosy_lab.java_smt.api.Formula; -import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.proofs.ProofDag; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.api.proofs.ProofRule; @@ -88,7 +86,7 @@ public List getChildren() { return Collections.unmodifiableList(children); } - @Override + @Override public void addChild(ProofNode child) { children.add(child); } @@ -115,6 +113,5 @@ void setRule(ProofRule rule) { void setFormula(Formula pFormula) { formula = pFormula; } - } } diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java index 214c62abe9..baa7dc07d1 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java @@ -25,10 +25,7 @@ import org.sosy_lab.java_smt.api.BasicProverEnvironment; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.Evaluator; -import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; -import org.sosy_lab.java_smt.api.SolverException; -import org.sosy_lab.java_smt.api.proofs.ProofNode; public abstract class AbstractProver implements BasicProverEnvironment { @@ -167,5 +164,4 @@ public void close() { closeAllEvaluators(); closed = true; } - } diff --git a/src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java b/src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java index 9babee6522..f939ccc7d9 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java +++ b/src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java @@ -10,16 +10,13 @@ package org.sosy_lab.java_smt.basicimpl; -import io.github.cvc5.Proof; import org.sosy_lab.java_smt.ResProofRule.ResAxiom; -import org.sosy_lab.java_smt.ResolutionProofDag.ResolutionProofNode; import org.sosy_lab.java_smt.ResolutionProofDag.AxiomProofNode; +import org.sosy_lab.java_smt.ResolutionProofDag.ResolutionProofNode; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.proofs.ProofNode; -import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5ProofNode; -import org.sosy_lab.java_smt.solvers.z3.Z3ProofDag; /** * A factory for creating proof nodes. The methods of this class are to be used in the ProofNode @@ -48,16 +45,14 @@ enum Solvers { } protected ProofFactory( - FormulaCreator pCreator, - ProverEnvironment pProver, - String pSolver) { + FormulaCreator pCreator, ProverEnvironment pProver, String pSolver) { formulaCreator = pCreator; prover = pProver; solver = Solvers.valueOf(pSolver); } protected ProofNode createProofNode(T proof) { - return createProofNode0(proof); + return createProofNode0(proof); } protected ProofNode createProofNode0(T proof) { @@ -70,8 +65,6 @@ protected ProofNode createProofNode0(T proof) { default: throw new UnsupportedOperationException("Unsupported solver: " + solver); } - - } protected static ProofNode createSourceNode(ResAxiom rule, Formula formula) { diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java index 75d35854d5..c3d0510406 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java @@ -22,7 +22,7 @@ public CVC5ProofNode(ProofRule pProofRule, Formula formula) { super(pProofRule, formula); } - String asString(int indentLevel) { + String asString(int indentLevel) { StringBuilder proof = new StringBuilder(); String indent = " ".repeat(indentLevel); diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java index 23ea706fab..04af15e26b 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java @@ -25,10 +25,11 @@ public class CVC5ProofProcessor { private class CVC5Frame extends ProofFrame { - CVC5Frame(Proof proof) { + CVC5Frame(Proof proof) { super(proof); } } + private final CVC5FormulaCreator formulaCreator; private final ProverEnvironment prover; @@ -50,13 +51,12 @@ CVC5ProofNode fromCVC5Proof(Proof pProof) throws CVC5ApiException { while (!stack.isEmpty()) { CVC5Frame frame = stack.peek(); - if (!frame.isVisited()) { frame.setNumArgs(frame.getProof().getChildren().length); frame.setAsVisited(true); - for (int i = frame.getNumArgs()-1; i >= 0; i--) { + for (int i = frame.getNumArgs() - 1; i >= 0; i--) { Proof child = frame.getProof().getChildren()[i]; if (!computed.containsKey(child)) { stack.push(new CVC5Frame(child)); @@ -75,7 +75,8 @@ CVC5ProofNode fromCVC5Proof(Proof pProof) throws CVC5ApiException { } CVC5ProofRule proofRule = - ProofRule.fromName(CVC5ProofRule.class, frame.getProof().getRule().toString().toLowerCase()); + ProofRule.fromName( + CVC5ProofRule.class, frame.getProof().getRule().toString().toLowerCase()); CVC5ProofNode pn = new CVC5ProofNode(proofRule, generateFormula(frame.getProof())); for (int i = 0; i < numChildren; i++) { Proof child = frame.getProof().getChildren()[i]; @@ -102,5 +103,4 @@ private Formula generateFormula(Proof proof) { private Proof changeRoot(Proof root) { return root.getChildren()[0]; } - } diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofRule.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofRule.java index 5eb403571d..33730cfead 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofRule.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofRule.java @@ -10,9 +10,6 @@ package org.sosy_lab.java_smt.solvers.cvc5; -import java.util.HashMap; -import java.util.Map; -import org.sosy_lab.java_smt.ProofRuleRegistry; import org.sosy_lab.java_smt.api.proofs.ProofRule; // TODO: Properly include the formulas for the proof rules. diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java index df12edb620..6d01e742eb 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java @@ -109,14 +109,15 @@ private static Solver createEnvironment() throws CVC5ApiException { @Test public void getProofTest() { - //(declare-fun q1 () Bool) - //(declare-fun q2 () Bool) - //(assert (or (not q1) q2)) - //(assert q1) - //(assert (not q2)) - //(check-sat) - //(get-proof) - //This problem is from the paper found in https://ultimate.informatik.uni-freiburg.de/smtinterpol/proofs.html + // (declare-fun q1 () Bool) + // (declare-fun q2 () Bool) + // (assert (or (not q1) q2)) + // (assert q1) + // (assert (not q2)) + // (check-sat) + // (get-proof) + // This problem is from the paper found in + // https://ultimate.informatik.uni-freiburg.de/smtinterpol/proofs.html BooleanFormula q1 = bmgr.makeVariable("q1"); BooleanFormula q2 = bmgr.makeVariable("q2"); diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java index 19c7dadaf3..27b7b36573 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java @@ -28,15 +28,14 @@ import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.basicimpl.AbstractProofDag.AbstractProofNode; - public class Mathsat5ProofNode extends AbstractProofNode { +public class Mathsat5ProofNode extends AbstractProofNode { - protected Mathsat5ProofNode(ProofRule rule, Formula formula) { + protected Mathsat5ProofNode(ProofRule rule, Formula formula) { super(rule, formula); } - - protected static class MsatProofFrame extends ProofFrame { - MsatProofFrame(Long proof) { + protected static class MsatProofFrame extends ProofFrame { + MsatProofFrame(Long proof) { super(proof); } } @@ -102,7 +101,7 @@ private static Formula generateFormula(long proof, Mathsat5TheoremProver prover) return formula; } - String asString() { + String asString() { return asString(0); } diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java index 916c2b2ba1..e57b16d41c 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java @@ -26,7 +26,6 @@ import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.ProofFactory; - class Mathsat5TheoremProver extends Mathsat5AbstractProver implements ProverEnvironment { Mathsat5TheoremProver( @@ -53,9 +52,8 @@ protected Void addConstraintImpl(BooleanFormula constraint) throws InterruptedEx @Override public ProofNode getProof() throws SolverException, InterruptedException { - Preconditions.checkState(!closed); - Preconditions.checkState(this.isUnsat()); - + Preconditions.checkState(!closed); + Preconditions.checkState(this.isUnsat()); ProofNode pn; long pm = msat_get_proof_manager(curEnv); @@ -65,22 +63,20 @@ public ProofNode getProof() throws SolverException, InterruptedException { return pn; - - - //return getProof0(); + // return getProof0(); } protected ProofNode getProof0() { - var proofFactory = new ProofFactory(this.creator, this, "MATHSAT5") { - public ProofNode createProofWrapper(long pProof) { - return this.createProofNode(pProof); - } - }; - long pm = msat_get_proof_manager(curEnv); - long proof = msat_get_proof(pm); - ProofNode pn = proofFactory.createProofWrapper(proof); - msat_destroy_proof_manager(pm); - return pn; - } - + var proofFactory = + new ProofFactory(this.creator, this, "MATHSAT5") { + public ProofNode createProofWrapper(long pProof) { + return this.createProofNode(pProof); + } + }; + long pm = msat_get_proof_manager(curEnv); + long proof = msat_get_proof(pm); + ProofNode pn = proofFactory.createProofWrapper(proof); + msat_destroy_proof_manager(pm); + return pn; + } } diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java index 5aee1d15b2..1a9181b006 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java @@ -17,7 +17,6 @@ import java.util.Deque; import java.util.HashMap; import java.util.Map; -import org.sosy_lab.java_smt.ProofRuleRegistry; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.ProofRule; @@ -26,11 +25,11 @@ * non-(java-)recursive implementation of the proof processor.# * *

The resulting DAG from transforming the proof from the Z3 provided structures into a set of - * {@link Z3ProofDag.Z3ProofNode} should enable an easier way to extract the information from the proofs. - * However, some information is lost from the original proof, as the Z3 provided proof makes uses of - * more general structures like AST, SortKind, DeclKind. E.g. the leafs in the {@link Z3ProofDag.Z3ProofNode} - * contain the whole formula used for the first proof rules in the tree, while these are internal - * nodes in the Z3 proof and leafs are the operands use in innermost terms. + * {@link Z3ProofDag.Z3ProofNode} should enable an easier way to extract the information from the + * proofs. However, some information is lost from the original proof, as the Z3 provided proof makes + * uses of more general structures like AST, SortKind, DeclKind. E.g. the leafs in the {@link + * Z3ProofDag.Z3ProofNode} contain the whole formula used for the first proof rules in the tree, + * while these are internal nodes in the Z3 proof and leafs are the operands use in innermost terms. */ @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) class Z3NonRecursiveProofProcessor { @@ -115,7 +114,7 @@ private ProofRule getPRfromDK(int declKind) { String rawName = Z3_decl_kind.fromInt(declKind).name(); String prName = rawName.replaceFirst("Z3_OP_PR_", ""); return ProofRule.fromName(Z3ProofRule.class, prName); - //return ProofRuleRegistry.fromName(Z3ProofRule.class, prName); + // return ProofRuleRegistry.fromName(Z3ProofRule.class, prName); } private Formula generateFormula(long proof) { diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDag.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDag.java index 06cbe773d0..635f44b2ff 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDag.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDag.java @@ -33,8 +33,8 @@ private String asString(int indentLevel) { proof.append(indent).append("Formula: ").append(getFormula().toString()).append("\n"); proof.append(indent).append("Rule: ").append(getRule().getName()).append("\n"); proof.append(indent).append("No. Children: ").append(getChildren().size()).append("\n"); - proof.append(indent).append("ID: ").append(getId()).append("\n"); - proof.append(indent).append("leaf: ").append(isLeaf()).append("\n"); + proof.append(indent).append("ID: ").append(getId()).append("\n"); + proof.append(indent).append("leaf: ").append(isLeaf()).append("\n"); int i = 0; for (ProofNode child : getChildren()) { diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java index 98b6280f19..6d9f301006 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java @@ -10,7 +10,6 @@ package org.sosy_lab.java_smt.solvers.z3; -import org.sosy_lab.java_smt.ProofRuleRegistry; import org.sosy_lab.java_smt.api.proofs.ProofRule; // TODO correctly document the formula strings diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java index 73063e1e15..3f08ec5904 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java @@ -1,7 +1,6 @@ package org.sosy_lab.java_smt.solvers.z3; import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import org.junit.After; @@ -30,15 +29,15 @@ public class Z3ProofsTest { @Before public void setUpSolverContext() throws Exception { - //Z3 requires to enable proof generation in the configuration of the context + // Z3 requires to enable proof generation in the configuration of the context Configuration config = Configuration.builder().setOption("solver.z3.requireProofs", "true").build(); LogManager logger = BasicLogManager.create(config); ShutdownManager shutdown = ShutdownManager.create(); - context = SolverContextFactory.createSolverContext( - config, logger, shutdown.getNotifier(), SolverContextFactory.Solvers.Z3); - + context = + SolverContextFactory.createSolverContext( + config, logger, shutdown.getNotifier(), SolverContextFactory.Solvers.Z3); mgr = (Z3FormulaManager) context.getFormulaManager(); bmgr = (Z3BooleanFormulaManager) mgr.getBooleanFormulaManager(); @@ -46,14 +45,15 @@ public void setUpSolverContext() throws Exception { @Before public void setUpQ1Q2Prover() throws InterruptedException { - //(declare-fun q1 () Bool) - //(declare-fun q2 () Bool) - //(assert (or (not q1) q2)) - //(assert q1) - //(assert (not q2)) - //(check-sat) - //(get-proof) - //This problem is from the paper found in https://ultimate.informatik.uni-freiburg.de/smtinterpol/proofs.html + // (declare-fun q1 () Bool) + // (declare-fun q2 () Bool) + // (assert (or (not q1) q2)) + // (assert q1) + // (assert (not q2)) + // (check-sat) + // (get-proof) + // This problem is from the paper found in + // https://ultimate.informatik.uni-freiburg.de/smtinterpol/proofs.html BooleanFormula q1 = bmgr.makeVariable("q1"); BooleanFormula q2 = bmgr.makeVariable("q2"); @@ -108,11 +108,11 @@ public void getFormulaTest() throws SolverException, InterruptedException { } @Test - public void getProofTermTest() throws SolverException, InterruptedException { - ProofNode proof = q1q2prover.getProof(); + public void getProofTermTest() throws SolverException, InterruptedException { + ProofNode proof = q1q2prover.getProof(); System.out.println(((Z3ProofDag.Z3ProofNode) proof).asString()); - } + } @Test public void Z3handleTransitivityTest() { @@ -127,12 +127,10 @@ public void Z3handleTransitivityTest() { pn.addChild(new Z3ProofDag.Z3ProofNode(equiv1, Z3ProofRule.ASSERTED)); pn.addChild(new Z3ProofDag.Z3ProofNode(equiv2, Z3ProofRule.ASSERTED)); - - Z3ToResoluteProofConverter pc = new Z3ToResoluteProofConverter(mgr); ProofNode res = pc.handleTransitivity(pn); - assertThat(res).isNotNull(); + assertThat(res).isNotNull(); } } diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java index 8ff8e3b995..a3fa8a0432 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java @@ -150,7 +150,8 @@ protected long getZ3Model() { @Override public ProofNode getProof() { long proofAst = Native.solverGetProof(z3context, z3solver); - return new Z3NonRecursiveProofProcessor(z3context, z3solver, creator, this).fromASTIterative(proofAst); + return new Z3NonRecursiveProofProcessor(z3context, z3solver, creator, this) + .fromASTIterative(proofAst); } // This method is used to get the Z3 proof as a long for testing exclusively diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java index 4e7c8a7531..5d89a743cd 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java @@ -19,8 +19,8 @@ import java.util.Map; import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.ResolutionProofDag; -import org.sosy_lab.java_smt.ResolutionProofDag.ResolutionProofNode; import org.sosy_lab.java_smt.ResolutionProofDag.AxiomProofNode; +import org.sosy_lab.java_smt.ResolutionProofDag.ResolutionProofNode; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.BooleanFormulaManager; import org.sosy_lab.java_smt.api.Formula; diff --git a/src/org/sosy_lab/java_smt/test/SolverThreadLocalityTest.java b/src/org/sosy_lab/java_smt/test/SolverThreadLocalityTest.java index 5e37b89ad4..3dd9e3f594 100644 --- a/src/org/sosy_lab/java_smt/test/SolverThreadLocalityTest.java +++ b/src/org/sosy_lab/java_smt/test/SolverThreadLocalityTest.java @@ -161,7 +161,8 @@ public void nonLocalProverTest() throws InterruptedException, ExecutionException // (Solver.java:1455) // at org.sosy_lab.java_smt.solvers.cvc5.CVC5AbstractProver.addConstraintImpl // (CVC5AbstractProver.java:114) - // at org.sosy_lab.java_smt.basicimpl.AbstractProofDag.AbstractProver.addConstraint + // at + // org.sosy_lab.java_smt.basicimpl.AbstractProofDag.AbstractProver.addConstraint // (AbstractProver.java:108) // at .. prover.push(formula); From 07e5866d31204bcc0ce4a018fb1d7e35742c41eb Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sat, 29 Mar 2025 22:25:57 +0100 Subject: [PATCH 056/132] Delete useless test in `SmtInterpolProofsTest` --- .../smtinterpol/SmtInterpolProofsTest.java | 43 ------------------- 1 file changed, 43 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java index bfe26ad3a8..59519ed5af 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java @@ -149,49 +149,6 @@ public void testGetProofClause() throws Exception { } } - @Test - public void testProofTermParserIntegration() throws Exception { - // Arrange: parse constraints as in the SmtInterpolProofsTest. - String constraint1 = - "(set-logic QF_UF)\n" - + "(declare-fun q1 () Bool)\n" - + "(declare-fun q2 () Bool)\n" - + "(assert (or (not q1) q2))"; - String constraint2 = "(assert q1)"; - String constraint3 = "(assert (not q2))"; - - BooleanFormula formula1 = context.getFormulaManager().parse(constraint1); - BooleanFormula formula2 = context.getFormulaManager().parse(constraint2); - BooleanFormula formula3 = context.getFormulaManager().parse(constraint3); - - // Create a prover with proof and model generation enabled. - SmtInterpolTheoremProver prover = - (SmtInterpolTheoremProver) - context.newProverEnvironment0( - ImmutableSet.of(ProverOptions.GENERATE_PROOFS, ProverOptions.GENERATE_MODELS)); - SMTInterpol smtInterpol = (SMTInterpol) prover.env; - try { - // Act: add constraints and check unsat. - prover.addConstraint(formula1); - prover.addConstraint(formula2); - prover.addConstraint(formula3); - assertTrue(prover.isUnsat()); - - // Retrieve the proof term from SMTInterpol. - Term proofTerm = smtInterpol.getProof(); - assertNotNull(proofTerm); - - // Convert the retrieved proof term to a ResolutionProofDAG using the context's formula - // creator - // and the asserted formulas. - ResolutionProofDag dag = (ResolutionProofDag) prover.getProof(); - assertNotNull(dag); - - // Optionally, additional assertions on the dag structure can be added here. - } finally { - prover.close(); - } - } @Test public void testSmtInterpolProof() throws Exception { From 912e315a5391528ad56b3081aaca2524cc334b64 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sat, 29 Mar 2025 23:10:26 +0100 Subject: [PATCH 057/132] `ProofRuleRegistry` and method `ProofRule.fromName` no longer used --- src/org/sosy_lab/java_smt/api/proofs/ProofRule.java | 7 +++---- .../java_smt/{ => api/proofs}/ProofRuleRegistry.java | 10 ++++++---- .../java_smt/solvers/cvc5/CVC5ProofProcessor.java | 7 ++++--- .../solvers/z3/Z3NonRecursiveProofProcessor.java | 5 +++-- src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java | 3 ++- 5 files changed, 18 insertions(+), 14 deletions(-) rename src/org/sosy_lab/java_smt/{ => api/proofs}/ProofRuleRegistry.java (89%) diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofRule.java b/src/org/sosy_lab/java_smt/api/proofs/ProofRule.java index cfcec6859f..f4b88de64f 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofRule.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofRule.java @@ -10,8 +10,6 @@ package org.sosy_lab.java_smt.api.proofs; -import org.sosy_lab.java_smt.ProofRuleRegistry; - /** A proof rule from a given proof format. */ public interface ProofRule { @@ -23,11 +21,11 @@ default String getFormula() { return "no formula available"; } - /** + /* * Get a proof rule from its name. * * @return A proof rule. - */ + static T fromName(Class clazz, String name) { ProofRule rule = ProofRuleRegistry.fromName(clazz, name); if (rule == null) { @@ -36,4 +34,5 @@ static T fromName(Class clazz, String name) { } return clazz.cast(rule); } + */ } diff --git a/src/org/sosy_lab/java_smt/ProofRuleRegistry.java b/src/org/sosy_lab/java_smt/api/proofs/ProofRuleRegistry.java similarity index 89% rename from src/org/sosy_lab/java_smt/ProofRuleRegistry.java rename to src/org/sosy_lab/java_smt/api/proofs/ProofRuleRegistry.java index 4cd19080d4..e71931787a 100644 --- a/src/org/sosy_lab/java_smt/ProofRuleRegistry.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofRuleRegistry.java @@ -8,20 +8,20 @@ * SPDX-License-Identifier: Apache-2.0 */ -package org.sosy_lab.java_smt; +package org.sosy_lab.java_smt.api.proofs; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.solvers.cvc5.CVC5ProofRule; -import org.sosy_lab.java_smt.solvers.z3.Z3ProofRule; +//import org.sosy_lab.java_smt.solvers.z3.Z3ProofRule; /** * Registry for proof rules. This class is used to register and retrieve proof rules by their name. * It checks for the solver that called to retrieve the according rule. */ -public class ProofRuleRegistry { + class ProofRuleRegistry { + /* // Key: ProofRule class, Value: (Key: Name, Value: ProofRule) private static final Map, Map> RULES = new ConcurrentHashMap<>(); @@ -43,4 +43,6 @@ public static ProofRule fromName(Class clazz, String name) ProofRuleRegistry.register(Z3ProofRule.class, rule); } } + + */ } diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java index 04af15e26b..1a367e5461 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java @@ -74,9 +74,10 @@ CVC5ProofNode fromCVC5Proof(Proof pProof) throws CVC5ApiException { continue; } - CVC5ProofRule proofRule = - ProofRule.fromName( - CVC5ProofRule.class, frame.getProof().getRule().toString().toLowerCase()); + CVC5ProofRule proofRule = Enum.valueOf(CVC5ProofRule.class, + frame.getProof().getRule().toString()); + //ProofRule.fromName( + //CVC5ProofRule.class, frame.getProof().getRule().toString().toLowerCase()); CVC5ProofNode pn = new CVC5ProofNode(proofRule, generateFormula(frame.getProof())); for (int i = 0; i < numChildren; i++) { Proof child = frame.getProof().getChildren()[i]; diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java index 1a9181b006..344f8e0502 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java @@ -19,6 +19,7 @@ import java.util.Map; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.ProofRule; +import org.sosy_lab.java_smt.solvers.cvc5.CVC5ProofRule; /** * This class is used to process the proof generated by Z3 and store it as a ProofNode. It is a @@ -113,8 +114,8 @@ Z3ProofDag.Z3ProofNode fromASTIterative(long rootProof) { private ProofRule getPRfromDK(int declKind) { String rawName = Z3_decl_kind.fromInt(declKind).name(); String prName = rawName.replaceFirst("Z3_OP_PR_", ""); - return ProofRule.fromName(Z3ProofRule.class, prName); - // return ProofRuleRegistry.fromName(Z3ProofRule.class, prName); + //return ProofRule.fromName(Z3ProofRule.class, prName); + return Enum.valueOf(Z3ProofRule.class, prName); } private Formula generateFormula(long proof) { diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java index 6d9f301006..1b2e0c4045 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java @@ -15,7 +15,8 @@ // TODO correctly document the formula strings /** Proof rules for Z3. These can be found in the Z3 API source code in the file Z3_api.h */ -public enum Z3ProofRule implements ProofRule { + +enum Z3ProofRule implements ProofRule { // Undefined proof object UNDEF("undef", "undefined proof object"), From e942121dd76ed51959a83c65e1854e8bbab1de64 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sat, 29 Mar 2025 23:17:16 +0100 Subject: [PATCH 058/132] `ProofRuleRegistry` deleted `ProofRule` inheritor classes no longer public --- .../java_smt/api/proofs/ProofRule.java | 15 ------ .../api/proofs/ProofRuleRegistry.java | 48 ------------------- .../java_smt/solvers/cvc5/CVC5ProofRule.java | 2 +- .../z3/Z3NonRecursiveProofProcessor.java | 2 +- 4 files changed, 2 insertions(+), 65 deletions(-) delete mode 100644 src/org/sosy_lab/java_smt/api/proofs/ProofRuleRegistry.java diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofRule.java b/src/org/sosy_lab/java_smt/api/proofs/ProofRule.java index f4b88de64f..0199864eb5 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofRule.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofRule.java @@ -20,19 +20,4 @@ public interface ProofRule { default String getFormula() { return "no formula available"; } - - /* - * Get a proof rule from its name. - * - * @return A proof rule. - - static T fromName(Class clazz, String name) { - ProofRule rule = ProofRuleRegistry.fromName(clazz, name); - if (rule == null) { - throw new IllegalArgumentException( - "Unknown proof rule in " + clazz.getSimpleName() + ": " + name); - } - return clazz.cast(rule); - } - */ } diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofRuleRegistry.java b/src/org/sosy_lab/java_smt/api/proofs/ProofRuleRegistry.java deleted file mode 100644 index e71931787a..0000000000 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofRuleRegistry.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * This file is part of JavaSMT, - * an API wrapper for a collection of SMT solvers: - * https://github.com/sosy-lab/java-smt - * - * SPDX-FileCopyrightText: 2024 Dirk Beyer - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.sosy_lab.java_smt.api.proofs; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import org.sosy_lab.java_smt.solvers.cvc5.CVC5ProofRule; -//import org.sosy_lab.java_smt.solvers.z3.Z3ProofRule; - -/** - * Registry for proof rules. This class is used to register and retrieve proof rules by their name. - * It checks for the solver that called to retrieve the according rule. - */ - class ProofRuleRegistry { - /* - // Key: ProofRule class, Value: (Key: Name, Value: ProofRule) - private static final Map, Map> RULES = - new ConcurrentHashMap<>(); - - private static void register(Class clazz, ProofRule rule) { - RULES.computeIfAbsent(clazz, k -> new HashMap<>()).put(rule.getName(), rule); - } - - public static ProofRule fromName(Class clazz, String name) { - return RULES.getOrDefault(clazz, new HashMap<>()).get(name.toLowerCase()); - } - - static { - for (CVC5ProofRule rule : CVC5ProofRule.values()) { - ProofRuleRegistry.register(CVC5ProofRule.class, rule); - } - - for (Z3ProofRule rule : Z3ProofRule.values()) { - ProofRuleRegistry.register(Z3ProofRule.class, rule); - } - } - - */ -} diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofRule.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofRule.java index 33730cfead..b73ded009d 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofRule.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofRule.java @@ -13,7 +13,7 @@ import org.sosy_lab.java_smt.api.proofs.ProofRule; // TODO: Properly include the formulas for the proof rules. -public enum CVC5ProofRule implements ProofRule { +enum CVC5ProofRule implements ProofRule { ASSUME("assume", ""), SCOPE("scope", ""), SUBS("subs", ""), diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java index 344f8e0502..18fc7d3f55 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java @@ -19,7 +19,7 @@ import java.util.Map; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.ProofRule; -import org.sosy_lab.java_smt.solvers.cvc5.CVC5ProofRule; + /** * This class is used to process the proof generated by Z3 and store it as a ProofNode. It is a From a88864638ea1ad7d415eaadf62873bdbd9e1be36 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sat, 29 Mar 2025 23:17:46 +0100 Subject: [PATCH 059/132] Removed unwanted test --- src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java index 3f08ec5904..e67e6cc2ee 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java @@ -107,12 +107,6 @@ public void getFormulaTest() throws SolverException, InterruptedException { assertThat(proof.getFormula()).isEqualTo(bmgr.makeFalse()); } - @Test - public void getProofTermTest() throws SolverException, InterruptedException { - ProofNode proof = q1q2prover.getProof(); - - System.out.println(((Z3ProofDag.Z3ProofNode) proof).asString()); - } @Test public void Z3handleTransitivityTest() { From 9fc4a2228c1d55725a9c0eddf3d9cc338caf370f Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Tue, 1 Apr 2025 15:08:14 +0200 Subject: [PATCH 060/132] Checkstyle --- .../sosy_lab/java_smt/basicimpl/AbstractProofDag.java | 1 - .../java_smt/solvers/cvc5/CVC5AbstractProver.java | 2 +- .../java_smt/solvers/cvc5/CVC5ProofProcessor.java | 9 ++++----- .../solvers/z3/Z3NonRecursiveProofProcessor.java | 3 +-- src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java | 1 - src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java | 1 - 6 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java index 8a444b54c2..c84afc0eab 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java @@ -10,7 +10,6 @@ package org.sosy_lab.java_smt.basicimpl; - import java.util.ArrayList; import java.util.Collection; import java.util.Collections; diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java index f6caf6f1b4..010cd5506d 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java @@ -14,8 +14,8 @@ import com.google.common.collect.ImmutableMap; import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.github.cvc5.CVC5ApiException; -import io.github.cvc5.Proof; import io.github.cvc5.CVC5ApiRecoverableException; +import io.github.cvc5.Proof; import io.github.cvc5.Result; import io.github.cvc5.Solver; import io.github.cvc5.Term; diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java index 1a367e5461..5390c55927 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java @@ -20,7 +20,6 @@ import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.proofs.ProofFrame; -import org.sosy_lab.java_smt.api.proofs.ProofRule; public class CVC5ProofProcessor { @@ -74,10 +73,10 @@ CVC5ProofNode fromCVC5Proof(Proof pProof) throws CVC5ApiException { continue; } - CVC5ProofRule proofRule = Enum.valueOf(CVC5ProofRule.class, - frame.getProof().getRule().toString()); - //ProofRule.fromName( - //CVC5ProofRule.class, frame.getProof().getRule().toString().toLowerCase()); + CVC5ProofRule proofRule = + Enum.valueOf(CVC5ProofRule.class, frame.getProof().getRule().toString()); + // ProofRule.fromName( + // CVC5ProofRule.class, frame.getProof().getRule().toString().toLowerCase()); CVC5ProofNode pn = new CVC5ProofNode(proofRule, generateFormula(frame.getProof())); for (int i = 0; i < numChildren; i++) { Proof child = frame.getProof().getChildren()[i]; diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java index 18fc7d3f55..0ac613eec9 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java @@ -20,7 +20,6 @@ import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.ProofRule; - /** * This class is used to process the proof generated by Z3 and store it as a ProofNode. It is a * non-(java-)recursive implementation of the proof processor.# @@ -114,7 +113,7 @@ Z3ProofDag.Z3ProofNode fromASTIterative(long rootProof) { private ProofRule getPRfromDK(int declKind) { String rawName = Z3_decl_kind.fromInt(declKind).name(); String prName = rawName.replaceFirst("Z3_OP_PR_", ""); - //return ProofRule.fromName(Z3ProofRule.class, prName); + // return ProofRule.fromName(Z3ProofRule.class, prName); return Enum.valueOf(Z3ProofRule.class, prName); } diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java index 1b2e0c4045..794a91fed0 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofRule.java @@ -15,7 +15,6 @@ // TODO correctly document the formula strings /** Proof rules for Z3. These can be found in the Z3 API source code in the file Z3_api.h */ - enum Z3ProofRule implements ProofRule { // Undefined proof object diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java index e67e6cc2ee..2162bb98b2 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java @@ -107,7 +107,6 @@ public void getFormulaTest() throws SolverException, InterruptedException { assertThat(proof.getFormula()).isEqualTo(bmgr.makeFalse()); } - @Test public void Z3handleTransitivityTest() { BooleanFormula f1 = bmgr.makeVariable("f1"); From a268761fe78776350c0b401e654e8e505b88fbc4 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Tue, 1 Apr 2025 15:08:29 +0200 Subject: [PATCH 061/132] Removed duplicates --- .../source/libmathsat5j/includes/defines.h | 10 --- ..._1smt_solvers_mathsat5_Mathsat5NativeApi.c | 73 ------------------- 2 files changed, 83 deletions(-) diff --git a/lib/native/source/libmathsat5j/includes/defines.h b/lib/native/source/libmathsat5j/includes/defines.h index aef6cac536..57d1b5e0b4 100644 --- a/lib/native/source/libmathsat5j/includes/defines.h +++ b/lib/native/source/libmathsat5j/includes/defines.h @@ -382,16 +382,6 @@ typedef jvoid jjfailureCode; typedef jobject jjnamedtermswrapper; -typedef jlong jjproofManager; -#define MANAGER_ARG(num) STRUCT_ARG(msat_proof_manager, num) -#define MANAGER_ARG_VOID(num) STRUCT_ARG_VOID(msat_proof_manager, num) -#define MANAGER_RETURN STRUCT_RETURN - -typedef jlong jjproof; -#define PROOF_ARG(num) STRUCT_ARG(msat_proof, num) -#define PROOF_ARG_VOID(num) STRUCT_ARG_VOID(msat_proof, num) -#define PROOF_RETURN STRUCT_RETURN - // Abbreviations for common combinations of return and argument types // // Parameter explanation: diff --git a/lib/native/source/libmathsat5j/org_sosy_1lab_java_1smt_solvers_mathsat5_Mathsat5NativeApi.c b/lib/native/source/libmathsat5j/org_sosy_1lab_java_1smt_solvers_mathsat5_Mathsat5NativeApi.c index c492874601..e8c2d2120f 100644 --- a/lib/native/source/libmathsat5j/org_sosy_1lab_java_1smt_solvers_mathsat5_Mathsat5NativeApi.c +++ b/lib/native/source/libmathsat5j/org_sosy_1lab_java_1smt_solvers_mathsat5_Mathsat5NativeApi.c @@ -1265,79 +1265,6 @@ TERM_ARRAY_OUTPUT_ARG(2) CALL2(msat_term*, get_unsat_core) RETURN_TERM_ARRAY(2) -//Proof functions -/* - * msat_proof_manager msat_get_proof_manager(msat_env e) - */ -DEFINE_FUNC(jproofManager, 1get_1proof_1manager) WITH_ONE_ARG(jenv) -ENV_ARG(1) -CALL1(msat_proof_manager, get_proof_manager) -STRUCT_RETURN_WITH_ENV - -/* - * void msat_destroy_proof_manager(msat_proof_manager m) - */ -DEFINE_FUNC(void, 1destroy_1proof_1manager) WITH_ONE_ARG(jproofManager) -MANAGER_ARG_VOID(1) -VOID_CALL1(destroy_proof_manager) - -/* - * msat_proof msat_get_proof(msat_proof_manager m) - */ -DEFINE_FUNC(jproof, 1get_1proof) WITH_ONE_ARG(jproofManager) -MANAGER_ARG(1) -CALL1(msat_proof, get_proof) -PROOF_RETURN - -/* - * size_t msat_proof_id(msat_proof p) - */ -DEFINE_FUNC(int, 1proof_1id) WITH_ONE_ARG(jproof) -PROOF_ARG(1) -CALL1(int, proof_id) -INT_RETURN - -/* - * int msat_proof_is_term(msat_proof p) - */ -DEFINE_FUNC(int, 1proof_1is_1term) WITH_ONE_ARG(jproof) -PROOF_ARG(1) -CALL1(int, proof_is_term) -BOOLEAN_RETURN - -/* - * msat_term msat_proof_get_term(msat_proof p) - */ -DEFINE_FUNC(jterm, 1proof_1get_1term) WITH_ONE_ARG(jproof) -PROOF_ARG(1) -CALL1(msat_term, proof_get_term) -STRUCT_RETURN - -/* - * const char* msat_proof_get_name(msat_proof p) - */ -DEFINE_FUNC(string, 1proof_1get_1name) WITH_ONE_ARG(jproof) -PROOF_ARG(1) -CALL1(const char*, proof_get_name) -PLAIN_CONST_STRING_RETURN - -/* - * size_t msat_proof_get_arity(msat_proof p) - */ -DEFINE_FUNC(int, 1proof_1get_1arity) WITH_ONE_ARG(jproof) -PROOF_ARG(1) -CALL1(size_t, proof_get_arity) -INT_RETURN - -/* - * msat_proof msat_proof_get_child(msat_proof p, size_t i) - */ -DEFINE_FUNC(jproof, 1proof_1get_1child) WITH_TWO_ARGS(jproof, int) -PROOF_ARG(1) -SIMPLE_ARG(size_t, 2) -CALL2(msat_proof, proof_get_child) -PROOF_RETURN - DEFINE_FUNC(jterm, 1simplify) WITH_FOUR_ARGS(jenv, jterm, jtermArray, int) ENV_ARG(1) TERM_ARG(2) From fd5ae78eae4a1d730de22c3af79271f99f536d46 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Tue, 1 Apr 2025 15:10:41 +0200 Subject: [PATCH 062/132] SMTInterpol: `SmtInterpolProofNodeCreator` creates a provitional proof node for processing the proof terms. Renamed `getResAxiomRuleByName` to `getFromName` in `ResProofRule` --- src/org/sosy_lab/java_smt/ResProofRule.java | 31 ++- .../SmtInterpolProofNodeCreator.java | 252 +++++++++++++---- .../smtinterpol/SmtInterpolProofsTest.java | 254 ++++++++++++------ 3 files changed, 396 insertions(+), 141 deletions(-) diff --git a/src/org/sosy_lab/java_smt/ResProofRule.java b/src/org/sosy_lab/java_smt/ResProofRule.java index 65db377168..ab4d00a3ad 100644 --- a/src/org/sosy_lab/java_smt/ResProofRule.java +++ b/src/org/sosy_lab/java_smt/ResProofRule.java @@ -10,7 +10,8 @@ package org.sosy_lab.java_smt; -import org.checkerframework.checker.nullness.qual.Nullable; +import java.util.HashMap; +import java.util.Map; import org.sosy_lab.java_smt.api.proofs.ProofRule; /** @@ -24,12 +25,18 @@ */ public class ResProofRule { + private static final Map RULE_MAP = new HashMap<>(); + + static { + for (ResAxiom rule : ResAxiom.values()) { + RULE_MAP.put(rule.getName().toLowerCase(), rule); + } + } + /** Any operation that proves a term. */ public enum ResAxiom implements ProofRule { // Resolution Rule RESOLUTION("res", "(res t proof1 proof2)"), - - // RUP("rup", null), ASSUME("assume", "(assume t)"), // Logical operators TRUE_POSITIVE("true+", "(+ true)"), @@ -111,9 +118,9 @@ public enum ResAxiom implements ProofRule { "(= (match t ((p1 x1) c1) ...) (ite ((_ is p1) t) (let (x1 (sel1 t)) c1) ...))"); private final String name; - @Nullable private final String formula; + private final String formula; - ResAxiom(String pName, @Nullable String pFormula) { + ResAxiom(String pName, String pFormula) { name = pName; formula = pFormula; } @@ -137,17 +144,13 @@ public String getFormula() { * @throws NullPointerException if the name is null. * @throws IllegalArgumentException if the name does not match any rule. */ - public static ResAxiom getResAxiomRuleByName(String name) { - if (name == null) { - throw new NullPointerException("Rule name cannot be null"); - } + public static ResAxiom getFromName(String name) { - for (ResAxiom rule : ResAxiom.values()) { - if (rule.getName().equalsIgnoreCase(name)) { - return rule; - } + ResAxiom rule = RULE_MAP.get(name.toLowerCase()); + if (rule == null) { + throw new IllegalArgumentException("Rule not found or not specified: " + name); } - throw new IllegalArgumentException("Rule not found or not specified: " + name); + return rule; } } diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java index 7b87c6942d..e5d536cb97 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java @@ -12,12 +12,19 @@ import de.uni_freiburg.informatik.ultimate.logic.AnnotatedTerm; import de.uni_freiburg.informatik.ultimate.logic.Annotation; +import de.uni_freiburg.informatik.ultimate.logic.ApplicationTerm; +import de.uni_freiburg.informatik.ultimate.logic.Sort; import de.uni_freiburg.informatik.ultimate.logic.Term; +import de.uni_freiburg.informatik.ultimate.logic.Util; import io.github.cvc5.Proof; import java.util.ArrayDeque; +import java.util.ArrayList; import java.util.Deque; import java.util.HashMap; +import java.util.List; import java.util.Map; +import org.sosy_lab.java_smt.ResProofRule; +import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.api.proofs.ProofFrame; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.api.proofs.ProofRule; @@ -36,6 +43,15 @@ class SmtInterpolProofNodeCreator { prover = pProver; } + private enum Rup implements ProofRule { + RUP; + + @Override + public String getName() { + return "rup"; + } + } + private class SmtTermFrame extends ProofFrame { public SmtTermFrame(Term term) { super(term); @@ -44,22 +60,19 @@ public SmtTermFrame(Term term) { ProofNode fromTerm(Term rootProof) { - Deque stack = new ArrayDeque<>(); + Deque stack = new ArrayDeque<>(); - Map computed = new HashMap<>(); + Map computed = new HashMap<>(); - stack.push(new SmtTermFrame(rootProof)); + stack.push(new ProvitionalProofNode(rootProof)); while (!stack.isEmpty()) { - SmtTermFrame frame = stack.peek(); + ProvitionalProofNode frame = stack.peek(); - // Skip processing the frame if its rule is "SCOPE" - // This rule seems to just help the processing by CVC5 - if (!frame.isVisited() && frame.getProof() == null) { - // Pop the SCOPE frame and push its children onto the stack - stack.pop(); - // frame.setNumArgs(rootProof. - frame.setAsVisited(true); + if (!frame.isVisited) { + + + frame.isVisited = true; // numChildren - 1 iterations for (int i = 10 - 1; i >= 0; i--) { // Proof child = rootProof.getChildren()[i]; @@ -71,7 +84,7 @@ ProofNode fromTerm(Term rootProof) { } else { stack.pop(); - int numChildren = frame.getNumArgs(); + int numChildren = frame.children.size(); // ProofRule proofRule = // new source node or resolution node @@ -89,67 +102,202 @@ ProofNode fromTerm(Term rootProof) { return computed.get(rootProof); } - private class ProvitionalProofNode { - private Term pivot; - private ProofRule proofRule; - private Term formula; - private int numChildren; + ProvitionalProofNode createPPNDag(Term proof) { + return new ProvitionalProofNode(proof); + } - public ProvitionalProofNode() {} + class ProvitionalProofNode { + Term pivot; + ProofRule proofRule; + List formulas = new ArrayList<>(); + boolean axiom; + List children = new ArrayList<>(); + Term unprocessedTerm; + boolean isVisited = false; - public void setFormula(Term pFormula) { - formula = pFormula; + public ProvitionalProofNode(Term pParameter) { + this.unprocessedTerm = pParameter; + processTerm(pParameter); } - public void setPivot(Term pPivot) { - pivot = pPivot; + void processTerm(Term pParameter) { + if (pParameter instanceof ApplicationTerm) { + processApplication((ApplicationTerm) pParameter); + } else if (pParameter instanceof AnnotatedTerm) { + processAnnotated((AnnotatedTerm) pParameter); + } } - public void setProofRule(ProofRule pProofRule) { - proofRule = pProofRule; - } + void processApplication(ApplicationTerm term) { + Term[] parameters = term.getParameters(); + if (parameters.length == 3) { + this.proofRule = ResAxiom.RESOLUTION; + //This should be a resolution rule + Term first = parameters[0]; + if (first instanceof AnnotatedTerm) { + pivot = ((AnnotatedTerm) first).getSubterm(); + } else if (first instanceof ApplicationTerm) { + pivot = first; + } + + for (int i = 1; i < parameters.length; i++) { + Sort sort = term.getSort(); + if (sort.toString().equals("..Proof")) { + children.add(new ProvitionalProofNode(parameters[i])); + } + } + } + + if (term.getFunction().toString().contains("..assume")) { + //This should be the assume axiom + this.axiom = true; + this.proofRule = ResAxiom.ASSUME; + if (parameters[0] instanceof AnnotatedTerm) { + this.formulas.add(((AnnotatedTerm) parameters[0]).getSubterm()); + } else { + this.formulas.add(parameters[0]); + } + + } - public void setNumChildren(int pNumChildren) { - numChildren = pNumChildren; } - public Term getFormula() { - return formula; + void processAnnotated(AnnotatedTerm term) { + processAnnotated0(term); } - public Term getPivot() { - return pivot; + private void processAnnotated0(AnnotatedTerm term) { + + boolean rup = false; + + if (term.getSort().toString().equals("Bool")) { + if (this.axiom) { + this.pivot = term.getSubterm(); + } else { + this.formulas.add(term.getSubterm()); + } + } + + for (Annotation annotation : term.getAnnotations()) { + ResAxiom rule; + String key = annotation.getKey().substring(1); + + if (term.getSubterm().toString().equals("..axiom")) { + this.axiom = true; + // Annotation key should contain axiom name and value should contain an array with some + // of its objects being Terms and the index before each one of those contains the + // polarity. + key = key.startsWith(":") ? key.substring(1) : key; + + rule = ResProofRule.getFromName(key); + + this.proofRule = rule; + // This Annotation's value should have an array with the polarities and Terms that are + // proven. This is the clause proven the ApplicationTerm. The array is empty for the + // very first Term. + // Now we need to go through the array and find the Term objects and their polarity. + // This is the same for proves. + if (annotation.getValue() instanceof Object[]) { + Object[] values = (Object[]) annotation.getValue(); + addTermsFromAnnotationValue(values, false); + } else if (annotation.getValue() instanceof AnnotatedTerm) { + processAnnotated((AnnotatedTerm) annotation.getValue()); + } else if (annotation.getValue() instanceof ApplicationTerm) { + formulas.add((Term) annotation.getValue()); + } + } + + if (key.equals("rup")) { + this.proofRule = Rup.RUP; + this.children.add(new ProvitionalProofNode(term.getSubterm())); + rup = true; + } + + if (key.equals("proves")) { + Object[] values = (Object[]) annotation.getValue(); + addTermsFromAnnotationValue(values, true); + } + + } + if (!rup) { + processTerm(term.getSubterm()); + } } - public ProofRule getProofRule() { - return proofRule; + void addTermsFromAnnotationValue(Object[] values, boolean isProves) { + for (int i = 0; values.length > i; i++) { + if (values[i] instanceof Term) { + // We found a Term and the index before it should contain the polarity, but only if + // this is the value of the proves Annotation. + if (isProves) { + assert values[i - 1].getClass() == String.class; + if (((String)values[i - 1]).contains("+")) { + this.formulas.add((Term) values[i]); + } else { + // We try to create the negative polarity Term + this.formulas.add(Util.not(creator.getEnv(), (Term) values[i])); + } + } else { + this.formulas.add((Term) values[i]); + } + + } + } } - public int getNumChildren() { - return numChildren; + public String asString() { + return asString(0); } - void processAnnotated(AnnotatedTerm term) { - for (Annotation annotation : term.getAnnotations()) { - String key = annotation.getKey().substring(1); - if (annotation.getKey().equals("proves")) { - this.setFormula((Term) annotation.getValue()); + String asString(int indentLevel) { + StringBuilder sb = new StringBuilder(); + String indent = " ".repeat(indentLevel); + + // Node header + sb.append(indent).append("ProofNode {\n"); + + // Node properties + sb.append(indent).append(" pivot: ").append(pivot != null ? pivot : "null").append("\n"); + sb.append(indent).append(" proofRule: ") + .append(proofRule != null ? proofRule.getName() : "null").append("\n"); + sb.append(indent).append(" axiom: ").append(axiom).append("\n"); + sb.append(indent).append(" isVisited: ").append(isVisited).append("\n"); + + // Formulas + sb.append(indent).append(" formulas: [\n"); + if (formulas.isEmpty()) { + sb.append(indent).append(" empty\n"); + } else { + for (Term formula : formulas) { + sb.append(indent).append(" ").append(formula != null ? formula : "null").append("\n"); } + } + sb.append(indent).append(" ]\n"); - switch (annotation.getKey()) { - case ":proves": - this.setFormula((Term) annotation.getValue()); - break; - case ":rup": - this.setFormula((Term) annotation.getValue()); - break; - case ":input": - this.setFormula((Term) annotation.getValue()); - break; - default: - break; + // Unprocessed term + sb.append(indent).append(" unprocessedTerm: ") + .append(unprocessedTerm != null ? unprocessedTerm : "null") + .append("\n"); + + // Children nodes + sb.append(indent).append(" children: [\n"); + if (children.isEmpty()) { + sb.append(indent).append(" empty\n"); + } else { + for (ProvitionalProofNode child : children) { + if (child != null) { + sb.append(child.asString(indentLevel + 2)); + } else { + sb.append(indent).append(" null\n"); + } } } + sb.append(indent).append(" ]\n"); + + // Close node + sb.append(indent).append("}\n"); + + return sb.toString(); } } } diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java index 59519ed5af..4e3959f3a5 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java @@ -11,15 +11,16 @@ package org.sosy_lab.java_smt.solvers.smtinterpol; import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import com.google.common.collect.ImmutableSet; +import de.uni_freiburg.informatik.ultimate.logic.AnnotatedTerm; +import de.uni_freiburg.informatik.ultimate.logic.ApplicationTerm; +import de.uni_freiburg.informatik.ultimate.logic.ConstantTerm; +import de.uni_freiburg.informatik.ultimate.logic.LambdaTerm; +import de.uni_freiburg.informatik.ultimate.logic.LetTerm; +import de.uni_freiburg.informatik.ultimate.logic.MatchTerm; +import de.uni_freiburg.informatik.ultimate.logic.QuantifiedFormula; import de.uni_freiburg.informatik.ultimate.logic.Term; -import de.uni_freiburg.informatik.ultimate.smtinterpol.dpll.Clause; -import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.ProofNode; -import de.uni_freiburg.informatik.ultimate.smtinterpol.smtlib2.SMTInterpol; -import java.lang.reflect.Method; +import de.uni_freiburg.informatik.ultimate.logic.TermVariable; import java.util.Set; import org.junit.After; import org.junit.Before; @@ -30,7 +31,6 @@ import org.sosy_lab.common.configuration.InvalidConfigurationException; import org.sosy_lab.common.log.BasicLogManager; import org.sosy_lab.common.log.LogManager; -import org.sosy_lab.java_smt.ResolutionProofDag; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; @@ -97,106 +97,210 @@ public void testGetProofTerm() throws SolverException, InterruptedException { // String proofStr = proof.toString(); // System.out.println(proofStr); - System.out.println(proof); + + processTerm(proof); } finally { prover.close(); } } - @Test - public void testGetProofClause() throws Exception { - // example from the 2022 paper - String constraint1 = - "(set-logic QF_UF)\n" - + "(declare-fun q1 () Bool)\n" - + "(declare-fun q2 () Bool)\n" - + "(assert (or (not q1) q2))"; - String constraint2 = "(assert q1)"; - String constraint3 = "(assert (not q2))"; + private int indentLevel = 0; - BooleanFormula formula1 = context.getFormulaManager().parse(constraint1); + private void printIndented(String message) { + System.out.println(" ".repeat(indentLevel * 2) + message); + } - BooleanFormula formula2 = context.getFormulaManager().parse(constraint2); + void processTerm(Term term) { + printIndented("Processing term: " + term.getClass().getSimpleName()); + if (term instanceof ApplicationTerm) { + processAppTerm((ApplicationTerm) term); + } else if (term instanceof AnnotatedTerm) { + processAnnotatedTerm((AnnotatedTerm) term); + } else if (term instanceof LetTerm) { + processLetTerm((LetTerm) term); + } else if (term instanceof ConstantTerm) { + processConstTerm((ConstantTerm) term); + } else if (term instanceof LambdaTerm) { + processLambdaTerm((LambdaTerm) term); + } else if (term instanceof MatchTerm) { + processMatchTerm((MatchTerm) term); + } else if (term instanceof QuantifiedFormula) { + processQuantifiedFormula((QuantifiedFormula) term); + } else if (term instanceof TermVariable) { + processTermVariable((TermVariable) term); + } else { + printIndented("Unknown term type: " + term.getClass()); + } + } - BooleanFormula formula3 = context.getFormulaManager().parse(constraint3); + private void processTermVariable(TermVariable term) { + printIndented("TermVariable: " + term.toString()); + indentLevel++; + printIndented("Sort: " + term.getSort().toString()); + printIndented("Declared Sort: " + term.getDeclaredSort().toString()); + printIndented("Name: " + term.getName()); + indentLevel--; + } - SmtInterpolTheoremProver prover = - (SmtInterpolTheoremProver) - context.newProverEnvironment0( - Set.of(ProverOptions.GENERATE_PROOFS, ProverOptions.GENERATE_MODELS)); + private void processQuantifiedFormula(QuantifiedFormula term) { + printIndented("QuantifiedFormula: " + term.toString()); + indentLevel++; + printIndented("Sort: " + term.getSort().toString()); + printIndented("Quantifier: " + term.getQuantifier()); + printIndented("Subformula: " + term.getSubformula().toString()); + for (int i = 0; i < term.getVariables().length; i++) { + printIndented("Variable " + i + ": " + term.getVariables()[i]); + processTerm(term.getVariables()[i]); + } + indentLevel--; + } - SMTInterpol smtinterpol = (SMTInterpol) prover.env; - try { - prover.addConstraint(formula1); - prover.addConstraint(formula2); - prover.addConstraint(formula3); - assertThat(prover.isUnsat()).isTrue(); + private void processMatchTerm(MatchTerm term) { + printIndented("MatchTerm: " + term.toString()); + indentLevel++; + printIndented("Sort: " + term.getSort().toString()); + printIndented("DataTerm: " + term.getDataTerm().toString()); + for (int i = 0; i < term.getVariables().length; i++) { + for (int j = 0; j < term.getVariables()[i].length; j++) { + printIndented("Variable " + i + " " + j + ": " + term.getVariables()[i][j]); + processTerm(term.getVariables()[i][j]); + } + } + for (int i = 0; i < term.getCases().length; i++) { + printIndented("Case " + i + ": " + term.getCases()[i]); + processTerm(term.getCases()[i]); + } + for (int i = 0; i < term.getConstructors().length; i++) { + printIndented("Constructor " + i + ": " + term.getConstructors()[i].toString()); + } + indentLevel--; + } - Clause proof = smtinterpol.retrieveProof(); - ProofNode proofNode = proof.getProof(); - Term term = smtinterpol.getProof(); + private void processLambdaTerm(LambdaTerm term) { + printIndented("LambdaTerm: " + term.toString()); + indentLevel++; + printIndented("Sort: " + term.getSort().toString()); + printIndented("Subterm: " + term.getSubterm().toString()); + for (int i = 0; i < term.getVariables().length; i++) { + printIndented("Variable " + i + ": " + term.getVariables()[i]); + processTerm(term.getVariables()[i]); + } + printIndented("Subterm will be processed"); + processTerm(term.getSubterm()); + indentLevel--; + } - assertThat(proof).isNotNull(); + private void processConstTerm(ConstantTerm term) { + printIndented("ConstantTerm: " + term.toString()); + indentLevel++; + printIndented("Sort: " + term.getSort().toString()); + printIndented("Value: " + term.getValue()); + if (term.getValue() instanceof Term) { + printIndented("Value is a term"); + processTerm((Term) term.getValue()); + } + indentLevel--; + } - // String proofStr = proof.toString(); - System.out.println(invokeGetProofMode(smtinterpol).toString()); - System.out.println(proof.toTerm(smtinterpol.getTheory())); - System.out.println(proof); - System.out.println(proofNode); - System.out.println(term); - } finally { - prover.close(); + private void processLetTerm(LetTerm term) { + printIndented("LetTerm: " + term.toString()); + indentLevel++; + printIndented("Sort: " + term.getSort().toString()); + printIndented("Subterm: " + term.getSubTerm().toString()); + for (int i = 0; i < term.getValues().length; i++) { + printIndented("value " + i + ": " + term.getValues()[i]); + processTerm(term.getValues()[i]); + } + for (int i = 0; i < term.getVariables().length; i++) { + printIndented("variable " + i + ": " + term.getVariables()[i]); + processTerm(term.getVariables()[i]); } + printIndented("Subterm will be processed"); + processTerm(term.getSubTerm()); + indentLevel--; } + private void processAnnotatedTerm(AnnotatedTerm term) { + printIndented("AnnotatedTerm: " + term.toString()); + indentLevel++; + printIndented("Sort: " + term.getSort().toString()); + printIndented("Subterm: " + term.getSubterm().toString()); + for (int i = 0; i < term.getFreeVars().length; i++) { + printIndented("Free Variable " + i + ": " + term.getFreeVars()[i]); + processTerm(term.getFreeVars()[i]); + } + for (int i = 0; i < term.getAnnotations().length; i++) { + printIndented("Annotation " + i + ": " + term.getAnnotations()[i]); + printIndented("Key: " + term.getAnnotations()[i].getKey()); + Object value = term.getAnnotations()[i].getValue(); + if (value != null) { + printIndented("Value: " + value); + printIndented("value class: " + value.getClass()); + if (value instanceof Object[]) { + Object[] valueArray = (Object[]) value; + for (Object element : valueArray) { + // Process each element in the array + printIndented("Array element: " + element); + printIndented("element class: " + element.getClass()); + } + } + } + } + printIndented("Subterm will be processed"); + processTerm(term.getSubterm()); + indentLevel--; + } - @Test - public void testSmtInterpolProof() throws Exception { - // Arrange: parse constraints as in the SmtInterpolProofsTest. - String constraint1 = - "(set-logic QF_UF)\n" - + "(declare-fun q1 () Bool)\n" - + "(declare-fun q2 () Bool)\n" - + "(assert (or (not q1) q2))"; - String constraint2 = "(assert q1)"; - String constraint3 = "(assert (not q2))"; + private void processAppTerm(ApplicationTerm term) { + printIndented("ApplicationTerm: " + term.toString()); + indentLevel++; + printIndented("Function Symbol: " + term.getFunction().toString()); + Term[] parameters = term.getParameters(); + printIndented("Sort: " + term.getSort().toString()); + printIndented("Parameters: " + parameters.length); + for (int i = 0; i < parameters.length; i++) { + printIndented("Parameter " + i + ": " + parameters[i]); + processTerm(parameters[i]); + } + indentLevel--; + } + @Test + public void testPPN(){ + // example from the 2022 paper BooleanFormula q1 = bmgr.makeVariable("q1"); BooleanFormula q2 = bmgr.makeVariable("q2"); + BooleanFormula notQ1OrQ2 = bmgr.or(bmgr.not(q1), q2); + BooleanFormula q1True = bmgr.equivalence(q1, bmgr.makeTrue()); + BooleanFormula q2False = bmgr.equivalence(q2, bmgr.makeFalse()); - // Create a prover with proof and model generation enabled. SmtInterpolTheoremProver prover = (SmtInterpolTheoremProver) - context.newProverEnvironment0( - ImmutableSet.of(ProverOptions.GENERATE_PROOFS, ProverOptions.GENERATE_MODELS)); - SMTInterpol smtInterpol = (SMTInterpol) prover.env; + context.newProverEnvironment0(Set.of(ProverOptions.GENERATE_PROOFS)); try { - // Act: add constraints and check unsat. - prover.addConstraint(bmgr.or(bmgr.not(q1), q2)); - prover.addConstraint(q1); - prover.addConstraint(bmgr.not(q2)); - assertTrue(prover.isUnsat()); - - // Retrieve the proof term from SMTInterpol. - Term proofTerm = smtInterpol.getProof(); - assertNotNull(proofTerm); + prover.addConstraint(notQ1OrQ2); + prover.addConstraint(q1True); + prover.addConstraint(q2False); + assertThat(prover.isUnsat()).isTrue(); Term proof = prover.smtInterpolGetProof(); assertThat(proof).isNotNull(); // String proofStr = proof.toString(); // System.out.println(proofStr); - System.out.println(proof); - // Optionally, additional assertions on the dag structure can be added here. + SmtInterpolProofNodeCreator pc = + new SmtInterpolProofNodeCreator( + (SmtInterpolFormulaCreator) prover.mgr.getFormulaCreator(),prover); + + assertThat(pc.createPPNDag(proof)).isNotNull(); + + System.out.println(pc.createPPNDag(proof).asString()); + + } catch (InterruptedException pE) { + throw new RuntimeException(pE); } finally { prover.close(); } } - - public static Object invokeGetProofMode(SMTInterpol instance) throws Exception { - Method getProofModeMethod = SMTInterpol.class.getDeclaredMethod("getProofMode"); - getProofModeMethod.setAccessible(true); - return getProofModeMethod.invoke(instance); - } } From 4e9bd1816954a5f724bc6c4a3113e4b9e1f131f8 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Tue, 1 Apr 2025 19:24:16 +0200 Subject: [PATCH 063/132] SMTInterpol: First implementation of non recursive processing of the proof. Not working --- .../java_smt/api/proofs/ProofFrame.java | 8 +- .../SmtInterpolProofNodeCreator.java | 91 +++++++++++++++---- 2 files changed, 80 insertions(+), 19 deletions(-) diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java b/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java index d22846f3d3..ceb66b4146 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java @@ -10,6 +10,8 @@ package org.sosy_lab.java_smt.api.proofs; + + /** * Stores proof related information and gets stored in a stack when processing proofs. Each frame * contains a proof object and the number of arguments it has. @@ -17,7 +19,7 @@ * @param The type of the proof object. */ public abstract class ProofFrame { - final T proof; + T proof; int numArgs; boolean visited; @@ -50,4 +52,8 @@ public void setAsVisited(boolean visited) { public void setNumArgs(int numArgs) { this.numArgs = numArgs; } + + public void setProof(T proof) { + this.proof = proof; + } } diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java index e5d536cb97..4fa3478d6c 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java @@ -16,13 +16,13 @@ import de.uni_freiburg.informatik.ultimate.logic.Sort; import de.uni_freiburg.informatik.ultimate.logic.Term; import de.uni_freiburg.informatik.ultimate.logic.Util; -import io.github.cvc5.Proof; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.sosy_lab.java_smt.ResProofRule; import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.api.proofs.ProofFrame; @@ -36,6 +36,8 @@ class SmtInterpolProofNodeCreator { private final SmtInterpolFormulaCreator creator; private final SmtInterpolTheoremProver prover; + private Map computed = new ConcurrentHashMap<>(); + private Deque stack = new ArrayDeque<>(); SmtInterpolProofNodeCreator( SmtInterpolFormulaCreator pCreator, SmtInterpolTheoremProver pProver) { @@ -53,6 +55,7 @@ public String getName() { } private class SmtTermFrame extends ProofFrame { + List children = new ArrayList<>(); public SmtTermFrame(Term term) { super(term); } @@ -103,7 +106,14 @@ ProofNode fromTerm(Term rootProof) { } ProvitionalProofNode createPPNDag(Term proof) { - return new ProvitionalProofNode(proof); + try { + ProvitionalProofNode root = new ProvitionalProofNode(proof); + root.buildDag(proof); + return root; + } finally { + stack.clear(); + computed.clear(); + } } class ProvitionalProofNode { @@ -117,18 +127,47 @@ class ProvitionalProofNode { public ProvitionalProofNode(Term pParameter) { this.unprocessedTerm = pParameter; - processTerm(pParameter); + //processTerm(pParameter); } - void processTerm(Term pParameter) { + void buildDag(Term term) { + + + stack.push(new SmtTermFrame(term)); + + while (!stack.isEmpty()) { + SmtTermFrame frame = stack.peek(); + + if (!frame.isVisited()) { + frame.setAsVisited(true); + processTerm(frame); + } else { + + stack.pop(); + + + for (int i = 0; i < frame.children.size(); i++) { + Term child = frame.children.get(i).getProof(); + ProvitionalProofNode childNode = computed.get(child); + this.children.add(childNode); + } + + } + } + } + + void processTerm(SmtTermFrame frame) { + Term pParameter = frame.getProof(); + if (pParameter instanceof ApplicationTerm) { - processApplication((ApplicationTerm) pParameter); + processApplication(frame); } else if (pParameter instanceof AnnotatedTerm) { - processAnnotated((AnnotatedTerm) pParameter); + processAnnotated(frame); } } - void processApplication(ApplicationTerm term) { + void processApplication(SmtTermFrame frame) { + ApplicationTerm term = (ApplicationTerm) frame.getProof(); Term[] parameters = term.getParameters(); if (parameters.length == 3) { this.proofRule = ResAxiom.RESOLUTION; @@ -140,10 +179,19 @@ void processApplication(ApplicationTerm term) { pivot = first; } - for (int i = 1; i < parameters.length; i++) { + for (int i = parameters.length-1; i > 1; i--) { Sort sort = term.getSort(); if (sort.toString().equals("..Proof")) { - children.add(new ProvitionalProofNode(parameters[i])); + //children.add(new ProvitionalProofNode(parameters[i])); + frame.setNumArgs(parameters.length-1); + if (!computed.containsKey(parameters[i])) { + SmtTermFrame childFrame = new SmtTermFrame(parameters[i]); + stack.push(childFrame); + frame.children.add(childFrame); + //children.add(new ProvitionalProofNode(parameters[i])); + computed.put(parameters[i], new ProvitionalProofNode(parameters[i])); + } + } } } @@ -162,12 +210,9 @@ void processApplication(ApplicationTerm term) { } - void processAnnotated(AnnotatedTerm term) { - processAnnotated0(term); - } - - private void processAnnotated0(AnnotatedTerm term) { + private void processAnnotated(SmtTermFrame frame) { + AnnotatedTerm term = (AnnotatedTerm) frame.getProof(); boolean rup = false; if (term.getSort().toString().equals("Bool")) { @@ -201,7 +246,8 @@ private void processAnnotated0(AnnotatedTerm term) { Object[] values = (Object[]) annotation.getValue(); addTermsFromAnnotationValue(values, false); } else if (annotation.getValue() instanceof AnnotatedTerm) { - processAnnotated((AnnotatedTerm) annotation.getValue()); + frame.setProof((AnnotatedTerm) annotation.getValue()); + processAnnotated(frame); } else if (annotation.getValue() instanceof ApplicationTerm) { formulas.add((Term) annotation.getValue()); } @@ -209,7 +255,15 @@ private void processAnnotated0(AnnotatedTerm term) { if (key.equals("rup")) { this.proofRule = Rup.RUP; - this.children.add(new ProvitionalProofNode(term.getSubterm())); + //this.children.add(new ProvitionalProofNode(term.getSubterm())); + frame.setNumArgs(1); + if (!computed.containsKey(term.getSubterm())) { + SmtTermFrame childFrame = new SmtTermFrame(term.getSubterm()); + stack.push(childFrame); + frame.children.add(childFrame); + //children.add(new ProvitionalProofNode(term.getSubterm())); + computed.put(term.getSubterm(), new ProvitionalProofNode(term.getSubterm())); + } rup = true; } @@ -220,7 +274,8 @@ private void processAnnotated0(AnnotatedTerm term) { } if (!rup) { - processTerm(term.getSubterm()); + frame.setProof(term.getSubterm()); + processTerm(frame); } } @@ -231,7 +286,7 @@ void addTermsFromAnnotationValue(Object[] values, boolean isProves) { // this is the value of the proves Annotation. if (isProves) { assert values[i - 1].getClass() == String.class; - if (((String)values[i - 1]).contains("+")) { + if (((String) values[i - 1]).contains("+")) { this.formulas.add((Term) values[i]); } else { // We try to create the negative polarity Term From 7d9ab9167664d75d9016d69a002775a0b4cb2032 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Wed, 2 Apr 2025 01:58:48 +0200 Subject: [PATCH 064/132] SMTInterpol: First implementation of non recursive processing of the proof. Not working. Fixed incorrect iteration over for loop. --- .../solvers/smtinterpol/SmtInterpolProofNodeCreator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java index 4fa3478d6c..4810f275df 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java @@ -179,7 +179,7 @@ void processApplication(SmtTermFrame frame) { pivot = first; } - for (int i = parameters.length-1; i > 1; i--) { + for (int i = parameters.length-1; i > 0; i--) { Sort sort = term.getSort(); if (sort.toString().equals("..Proof")) { //children.add(new ProvitionalProofNode(parameters[i])); @@ -262,6 +262,7 @@ private void processAnnotated(SmtTermFrame frame) { stack.push(childFrame); frame.children.add(childFrame); //children.add(new ProvitionalProofNode(term.getSubterm())); + //computed.put(term, this); computed.put(term.getSubterm(), new ProvitionalProofNode(term.getSubterm())); } rup = true; From a677bbb8615216d6cca559932e17d94be8c3f908 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sun, 6 Apr 2025 22:21:03 +0200 Subject: [PATCH 065/132] solved warnings. MathSAT5: nodes with rule `CLAUSE-HYP` now correctly store a `Formula` --- .../java_smt/basicimpl/ProofFactory.java | 7 ++- .../solvers/cvc5/CVC5AbstractProver.java | 3 +- .../solvers/cvc5/CVC5ProofProcessor.java | 7 +-- .../java_smt/solvers/cvc5/CVC5ProofsTest.java | 4 +- .../solvers/mathsat5/Mathsat5ProofNode.java | 52 +++++++++++++------ .../solvers/mathsat5/Mathsat5ProofRule.java | 16 +++++- .../mathsat5/Mathsat5TheoremProver.java | 2 +- .../SmtInterpolProofNodeCreator.java | 6 +-- 8 files changed, 63 insertions(+), 34 deletions(-) diff --git a/src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java b/src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java index f939ccc7d9..4327186737 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java +++ b/src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java @@ -27,7 +27,7 @@ */ public class ProofFactory { - private final FormulaCreator formulaCreator; + //private final FormulaCreator formulaCreator; private final ProverEnvironment prover; private final Solvers solver; @@ -44,9 +44,8 @@ enum Solvers { BITWUZLA } - protected ProofFactory( - FormulaCreator pCreator, ProverEnvironment pProver, String pSolver) { - formulaCreator = pCreator; + protected ProofFactory(ProverEnvironment pProver, String pSolver) { + //formulaCreator = pCreator; prover = pProver; solver = Solvers.valueOf(pSolver); } diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java index 010cd5506d..78de43cafc 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java @@ -36,7 +36,6 @@ import org.sosy_lab.java_smt.api.Evaluator; import org.sosy_lab.java_smt.api.FormulaManager; import org.sosy_lab.java_smt.api.Model.ValueAssignment; -import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; import org.sosy_lab.java_smt.api.proofs.ProofNode; @@ -257,7 +256,7 @@ public ProofNode getProof() { throw new IllegalStateException("No proof available"); } - CVC5ProofProcessor pp = new CVC5ProofProcessor(creator, (ProverEnvironment) this); + CVC5ProofProcessor pp = new CVC5ProofProcessor(creator); try { return pp.fromCVC5Proof(proofs[0]); } catch (CVC5ApiException pE) { diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java index 5390c55927..6260b7e18d 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java @@ -18,23 +18,20 @@ import java.util.HashMap; import java.util.Map; import org.sosy_lab.java_smt.api.Formula; -import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.proofs.ProofFrame; public class CVC5ProofProcessor { - private class CVC5Frame extends ProofFrame { + private static class CVC5Frame extends ProofFrame { CVC5Frame(Proof proof) { super(proof); } } private final CVC5FormulaCreator formulaCreator; - private final ProverEnvironment prover; - CVC5ProofProcessor(CVC5FormulaCreator creator, ProverEnvironment pProver) { + CVC5ProofProcessor(CVC5FormulaCreator creator) { formulaCreator = creator; - prover = pProver; } CVC5ProofNode fromCVC5Proof(Proof pProof) throws CVC5ApiException { diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java index 6d01e742eb..53c1288c6f 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java @@ -169,7 +169,7 @@ public void proofTest() throws CVC5ApiException { Term q1 = solver.declareFun("q1", new Sort[] {}, booleanSort); Term q2 = solver.declareFun("q2", new Sort[] {}, booleanSort); - solver.assertFormula(tm.mkTerm(Kind.OR, (tm.mkTerm(Kind.NOT, q1)), q2)); + solver.assertFormula(tm.mkTerm(Kind.OR, tm.mkTerm(Kind.NOT, q1), q2)); solver.assertFormula(q1); solver.assertFormula(tm.mkTerm(Kind.NOT, q2)); @@ -196,7 +196,7 @@ public void cvc5ProofToStringTest() { Term q1 = solver.declareFun("q1", new Sort[] {}, booleanSort); Term q2 = solver.declareFun("q2", new Sort[] {}, booleanSort); - solver.assertFormula(tm.mkTerm(Kind.OR, (tm.mkTerm(Kind.NOT, q1)), q2)); + solver.assertFormula(tm.mkTerm(Kind.OR, tm.mkTerm(Kind.NOT, q1), q2)); solver.assertFormula(q1); solver.assertFormula(tm.mkTerm(Kind.NOT, q2)); diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java index 27b7b36573..d6303dec8b 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java @@ -10,6 +10,7 @@ package org.sosy_lab.java_smt.solvers.mathsat5; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_make_or; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_get_arity; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_get_child; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_get_name; @@ -17,8 +18,10 @@ import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_is_term; import java.util.ArrayDeque; +import java.util.ArrayList; import java.util.Deque; import java.util.HashMap; +import java.util.List; import java.util.Map; import javax.annotation.Nullable; import org.sosy_lab.java_smt.api.Formula; @@ -27,10 +30,11 @@ import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.basicimpl.AbstractProofDag.AbstractProofNode; +import org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5ProofRule.Rule; public class Mathsat5ProofNode extends AbstractProofNode { - protected Mathsat5ProofNode(ProofRule rule, Formula formula) { + protected Mathsat5ProofNode(@Nullable ProofRule rule, Formula formula) { super(rule, formula); } @@ -41,11 +45,7 @@ protected static class MsatProofFrame extends ProofFrame { } public static Mathsat5ProofNode fromMsatProof(ProverEnvironment pProver, long rootProof) { - final Mathsat5SolverContext context = ((Mathsat5TheoremProver) pProver).context; - final long curEnv = ((Mathsat5TheoremProver) pProver).curEnv; - final Mathsat5FormulaCreator formulaCreator = ((Mathsat5TheoremProver) pProver).creator; - { Deque stack = new ArrayDeque<>(); Map computed = new HashMap<>(); @@ -70,24 +70,44 @@ public static Mathsat5ProofNode fromMsatProof(ProverEnvironment pProver, long ro stack.pop(); // Generate the formula and proof rule. - Formula formula = generateFormula(frame.getProof(), (Mathsat5TheoremProver) pProver); - Mathsat5ProofRule proofRule = - new Mathsat5ProofRule(msat_proof_get_name(frame.getProof())); - Mathsat5ProofNode node = new Mathsat5ProofNode(proofRule, formula); - // Retrieve computed child nodes and attach them. - for (int i = 0; i < frame.getNumArgs(); i++) { - long child = msat_proof_get_child(frame.getProof(), i); - Mathsat5ProofNode childNode = computed.get(child); - if (childNode != null) { - node.addChild(childNode); + String rule = msat_proof_get_name(frame.getProof()); + Mathsat5ProofRule.Rule proofRule = rule == null ? Rule.NULL : + Rule.valueOf(rule.toUpperCase().replace("-", "_")); + + Mathsat5ProofNode node; + Mathsat5TheoremProver prover = (Mathsat5TheoremProver) pProver; + if (proofRule == Rule.CLAUSE_HYP) { + // Reconstruct clause from children terms + long or = msat_proof_get_term(msat_proof_get_child(frame.getProof(), 0)); + for (int i = 1; i < frame.getNumArgs(); i++) { + long child = msat_proof_get_term(msat_proof_get_child(frame.getProof(), i)); + or = msat_make_or(prover.curEnv, or, child); + } + + node = new Mathsat5ProofNode(proofRule, + ((Mathsat5TheoremProver) pProver).creator.encapsulate(prover.creator.getFormulaType(or),or)); + + // Do not add children, as they are now embedded in the formula + } else { + Formula formula = generateFormula(frame.getProof(), (Mathsat5TheoremProver) pProver); + node = new Mathsat5ProofNode(proofRule, formula); + + // Retrieve computed child nodes and attach them. + for (int i = 0; i < frame.getNumArgs(); i++) { + long child = msat_proof_get_child(frame.getProof(), i); + Mathsat5ProofNode childNode = computed.get(child); + if (childNode != null) { + node.addChild(childNode); + } } + } + computed.put(frame.getProof(), node); } } return computed.get(rootProof); - } } @Nullable diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java index 9efa4c7e93..8f101651d1 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java @@ -12,8 +12,22 @@ import org.sosy_lab.java_smt.api.proofs.ProofRule; -public class Mathsat5ProofRule implements ProofRule { +class Mathsat5ProofRule implements ProofRule { +//Most comments are taken from the API Reference: https://mathsat.fbk.eu/apireference.html + // + enum Rule implements ProofRule{ + THEORY_LEMMA(),//" representing theory lemmas. They have as children a list of terms that consititute the lemma, plus an optional last element which is a more detailed proof produced by a theory solver." + RES_CHAIN(),//"representing Boolean resolution chains. The children are an interleaving of proofs and terms, where terms are the pivots for the resolution. For example: "res-chain p1 v p2" represents a resolution step between p1 and p2 on the pivot v" + CLAUSE_HYP(), //" which are the clauses of the (CNF conversion of the) input problem. They have + // a list of terms as children" + NULL()//We introduce this rule because Term Nodes in MathSAT5 do not have a rule associated with them. + ; + @Override + public String getName() { + return name(); + } + } private String name; Mathsat5ProofRule(String pName) { diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java index e57b16d41c..9156524c15 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java @@ -68,7 +68,7 @@ public ProofNode getProof() throws SolverException, InterruptedException { protected ProofNode getProof0() { var proofFactory = - new ProofFactory(this.creator, this, "MATHSAT5") { + new ProofFactory(this, "MATHSAT5") { public ProofNode createProofWrapper(long pProof) { return this.createProofNode(pProof); } diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java index 4810f275df..e754f471cb 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java @@ -32,7 +32,7 @@ // SMTInterpol gives back a Term (apparently) only of instance ApplicationTerm or AnnotatedTerm, // so the other instances are not needed. -@SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) +@SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access", "ModifiedButNotUsed"}) class SmtInterpolProofNodeCreator { private final SmtInterpolFormulaCreator creator; private final SmtInterpolTheoremProver prover; @@ -54,7 +54,7 @@ public String getName() { } } - private class SmtTermFrame extends ProofFrame { + private static class SmtTermFrame extends ProofFrame { List children = new ArrayList<>(); public SmtTermFrame(Term term) { super(term); @@ -102,7 +102,7 @@ ProofNode fromTerm(Term rootProof) { // computed.put(frame.proof, pn); } } - return computed.get(rootProof); + return null; } ProvitionalProofNode createPPNDag(Term proof) { From 11314562014e45c162ca76aceb10b2da0f83366d Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 7 Apr 2025 15:36:00 +0200 Subject: [PATCH 066/132] MathSAT5: nodes with rule `CLAUSE-HYP` are now leaves. --- .../solvers/mathsat5/Mathsat5ProofNode.java | 100 ++++++++++++++---- 1 file changed, 77 insertions(+), 23 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java index d6303dec8b..7f2107140b 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java @@ -10,6 +10,7 @@ package org.sosy_lab.java_smt.solvers.mathsat5; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_proof; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_make_or; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_get_arity; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_get_child; @@ -32,18 +33,32 @@ import org.sosy_lab.java_smt.basicimpl.AbstractProofDag.AbstractProofNode; import org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5ProofRule.Rule; + public class Mathsat5ProofNode extends AbstractProofNode { protected Mathsat5ProofNode(@Nullable ProofRule rule, Formula formula) { super(rule, formula); + } protected static class MsatProofFrame extends ProofFrame { MsatProofFrame(Long proof) { super(proof); } + boolean skip = false; } + /** + * Creates a proof node from a MathSAT5 proof object. + * + * Not all proof rules are known beforehand, so some are not in the enum. This means that + * (specifically) the sub-DAG of the theory-lemma rule may contain a sub-proof that does + * not have either a {@link ProofRule} or a {@link Formula} in a given node. + * + * @param pProver The prover environment. + * @param rootProof The root proof object. + * @return The proof node. + */ public static Mathsat5ProofNode fromMsatProof(ProverEnvironment pProver, long rootProof) { Deque stack = new ArrayDeque<>(); @@ -51,18 +66,34 @@ public static Mathsat5ProofNode fromMsatProof(ProverEnvironment pProver, long ro stack.push(new MsatProofFrame(rootProof)); + while (!stack.isEmpty()) { MsatProofFrame frame = stack.peek(); if (!frame.isVisited()) { frame.setNumArgs(msat_proof_get_arity(frame.getProof())); frame.setAsVisited(true); - // Push children first so that the leaves are processed first. - for (int i = 0; i < frame.getNumArgs(); i++) { + String rule = msat_proof_get_name(frame.getProof()) == null ? "null" : + msat_proof_get_name(frame.getProof()); + for (int i = frame.getNumArgs()-1; i >= 0; i--) { + long child = msat_proof_get_child(frame.getProof(), i); - if (!computed.containsKey(child)) { + + //If rule is claus-hyp, all the children get added to the dag in generateFormula + if (!computed.containsKey(child) && !rule.equals( + "clause" + + "-hyp")) { + //If the rules is theory-lemma and the child is a term, it gets added to the dag + // in generateFormula + if(rule.equals( + "theory-lemma") && msat_proof_is_term(frame.getProof())) { + frame.setNumArgs(frame.getNumArgs()-1); + continue; + } stack.push(new MsatProofFrame(child)); - } + } else { + frame.setNumArgs(frame.getNumArgs()-1); + } } } else { // Process the node after all its children have been processed. This should help to @@ -72,25 +103,22 @@ public static Mathsat5ProofNode fromMsatProof(ProverEnvironment pProver, long ro // Generate the formula and proof rule. String rule = msat_proof_get_name(frame.getProof()); - Mathsat5ProofRule.Rule proofRule = rule == null ? Rule.NULL : - Rule.valueOf(rule.toUpperCase().replace("-", "_")); + ProofRule proofRule; + + //If the theory-lemma rule includes a last argument that is not a term, it means it has + // a proof attached to it. Not all rules are known beforehand so they are not in the enum. + try { + proofRule = rule == null ? Rule.NULL : + Rule.valueOf(rule.toUpperCase().replace("-", "_")); + } catch (IllegalArgumentException e) { + proofRule = new Mathsat5ProofRule(rule); + } Mathsat5ProofNode node; Mathsat5TheoremProver prover = (Mathsat5TheoremProver) pProver; - if (proofRule == Rule.CLAUSE_HYP) { - // Reconstruct clause from children terms - long or = msat_proof_get_term(msat_proof_get_child(frame.getProof(), 0)); - for (int i = 1; i < frame.getNumArgs(); i++) { - long child = msat_proof_get_term(msat_proof_get_child(frame.getProof(), i)); - or = msat_make_or(prover.curEnv, or, child); - } + Formula formula = generateFormula(frame, prover, proofRule); - node = new Mathsat5ProofNode(proofRule, - ((Mathsat5TheoremProver) pProver).creator.encapsulate(prover.creator.getFormulaType(or),or)); - // Do not add children, as they are now embedded in the formula - } else { - Formula formula = generateFormula(frame.getProof(), (Mathsat5TheoremProver) pProver); node = new Mathsat5ProofNode(proofRule, formula); // Retrieve computed child nodes and attach them. @@ -102,7 +130,7 @@ public static Mathsat5ProofNode fromMsatProof(ProverEnvironment pProver, long ro } } - } + computed.put(frame.getProof(), node); } @@ -111,12 +139,38 @@ public static Mathsat5ProofNode fromMsatProof(ProverEnvironment pProver, long ro } @Nullable - private static Formula generateFormula(long proof, Mathsat5TheoremProver prover) { + private static Formula generateFormula(MsatProofFrame frame, Mathsat5TheoremProver prover, + ProofRule rule) { Mathsat5FormulaCreator formulaCreator = prover.creator; Formula formula = null; - if (msat_proof_is_term(proof)) { - long proofTerm = msat_proof_get_term(proof); - formula = formulaCreator.encapsulate(formulaCreator.getFormulaType(proofTerm), proofTerm); + long proof = frame.getProof(); + int children = msat_proof_get_arity(proof); + // If rule is NULL the proof should be a term and we encapsulate directly + if (rule.equals(Rule.NULL)) { + formula = + formulaCreator.encapsulate(formulaCreator.getFormulaType(msat_proof_get_term(proof)), msat_proof_get_term(proof)); + //For clause-hype, we create the clause using the children + } else if (rule.equals(Rule.CLAUSE_HYP)) { + long or = msat_proof_get_term(msat_proof_get_child(proof, 0)); + for (int i = 1; i < children ; i++) { + long child = msat_proof_get_term(msat_proof_get_child(proof, i)); + or = msat_make_or(prover.curEnv, or, child); + } + formula = formulaCreator.encapsulate(formulaCreator.getFormulaType(or), or); + } else if (rule.equals(Rule.RES_CHAIN)) { + //Generating the formula for the resolution chain should be easier after the whole DAG is + // built + } else if (rule.equals(Rule.THEORY_LEMMA)) { + if (msat_proof_is_term(msat_proof_get_child(proof, 0))) { + long and = msat_proof_get_term(msat_proof_get_child(proof, 0)); + for (int i = 1; i < children; i++) { + if (msat_proof_is_term(msat_proof_get_child(proof, i))) { + + long child = msat_proof_get_term(msat_proof_get_child(proof, i)); + and = msat_make_or(prover.curEnv, and, child); + } + } + } } return formula; } From f9e4209a074ffbc8ac2ce1c75d9dd8f37c8544d5 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 7 Apr 2025 21:06:52 +0200 Subject: [PATCH 067/132] Chekstyle --- .../java_smt/api/proofs/ProofFrame.java | 4 +- .../java_smt/basicimpl/ProofFactory.java | 4 +- .../SmtInterpolProofNodeCreator.java | 72 +++++++++---------- .../smtinterpol/SmtInterpolProofsTest.java | 4 +- 4 files changed, 38 insertions(+), 46 deletions(-) diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java b/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java index ceb66b4146..b4683b3fe3 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java @@ -10,8 +10,6 @@ package org.sosy_lab.java_smt.api.proofs; - - /** * Stores proof related information and gets stored in a stack when processing proofs. Each frame * contains a proof object and the number of arguments it has. @@ -20,7 +18,7 @@ */ public abstract class ProofFrame { T proof; - int numArgs; + int numArgs = 0; boolean visited; protected ProofFrame(T proof) { diff --git a/src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java b/src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java index 4327186737..8dffd7c38e 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java +++ b/src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java @@ -27,7 +27,7 @@ */ public class ProofFactory { - //private final FormulaCreator formulaCreator; + // private final FormulaCreator formulaCreator; private final ProverEnvironment prover; private final Solvers solver; @@ -45,7 +45,7 @@ enum Solvers { } protected ProofFactory(ProverEnvironment pProver, String pSolver) { - //formulaCreator = pCreator; + // formulaCreator = pCreator; prover = pProver; solver = Solvers.valueOf(pSolver); } diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java index e754f471cb..88364c2f3c 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java @@ -56,6 +56,7 @@ public String getName() { private static class SmtTermFrame extends ProofFrame { List children = new ArrayList<>(); + public SmtTermFrame(Term term) { super(term); } @@ -74,7 +75,6 @@ ProofNode fromTerm(Term rootProof) { if (!frame.isVisited) { - frame.isVisited = true; // numChildren - 1 iterations for (int i = 10 - 1; i >= 0; i--) { @@ -107,12 +107,12 @@ ProofNode fromTerm(Term rootProof) { ProvitionalProofNode createPPNDag(Term proof) { try { - ProvitionalProofNode root = new ProvitionalProofNode(proof); - root.buildDag(proof); - return root; + ProvitionalProofNode root = new ProvitionalProofNode(proof); + root.buildDag(proof); + return root; } finally { - stack.clear(); - computed.clear(); + stack.clear(); + computed.clear(); } } @@ -127,12 +127,11 @@ class ProvitionalProofNode { public ProvitionalProofNode(Term pParameter) { this.unprocessedTerm = pParameter; - //processTerm(pParameter); + // processTerm(pParameter); } void buildDag(Term term) { - stack.push(new SmtTermFrame(term)); while (!stack.isEmpty()) { @@ -145,13 +144,11 @@ void buildDag(Term term) { stack.pop(); - - for (int i = 0; i < frame.children.size(); i++) { - Term child = frame.children.get(i).getProof(); - ProvitionalProofNode childNode = computed.get(child); - this.children.add(childNode); - } - + for (int i = 0; i < frame.children.size(); i++) { + Term child = frame.children.get(i).getProof(); + ProvitionalProofNode childNode = computed.get(child); + this.children.add(childNode); + } } } } @@ -171,7 +168,7 @@ void processApplication(SmtTermFrame frame) { Term[] parameters = term.getParameters(); if (parameters.length == 3) { this.proofRule = ResAxiom.RESOLUTION; - //This should be a resolution rule + // This should be a resolution rule Term first = parameters[0]; if (first instanceof AnnotatedTerm) { pivot = ((AnnotatedTerm) first).getSubterm(); @@ -179,25 +176,24 @@ void processApplication(SmtTermFrame frame) { pivot = first; } - for (int i = parameters.length-1; i > 0; i--) { + for (int i = parameters.length - 1; i > 0; i--) { Sort sort = term.getSort(); if (sort.toString().equals("..Proof")) { - //children.add(new ProvitionalProofNode(parameters[i])); - frame.setNumArgs(parameters.length-1); - if (!computed.containsKey(parameters[i])) { - SmtTermFrame childFrame = new SmtTermFrame(parameters[i]); - stack.push(childFrame); - frame.children.add(childFrame); - //children.add(new ProvitionalProofNode(parameters[i])); - computed.put(parameters[i], new ProvitionalProofNode(parameters[i])); - } - + // children.add(new ProvitionalProofNode(parameters[i])); + frame.setNumArgs(parameters.length - 1); + if (!computed.containsKey(parameters[i])) { + SmtTermFrame childFrame = new SmtTermFrame(parameters[i]); + stack.push(childFrame); + frame.children.add(childFrame); + // children.add(new ProvitionalProofNode(parameters[i])); + computed.put(parameters[i], new ProvitionalProofNode(parameters[i])); + } } } } if (term.getFunction().toString().contains("..assume")) { - //This should be the assume axiom + // This should be the assume axiom this.axiom = true; this.proofRule = ResAxiom.ASSUME; if (parameters[0] instanceof AnnotatedTerm) { @@ -205,12 +201,9 @@ void processApplication(SmtTermFrame frame) { } else { this.formulas.add(parameters[0]); } - } - } - private void processAnnotated(SmtTermFrame frame) { AnnotatedTerm term = (AnnotatedTerm) frame.getProof(); boolean rup = false; @@ -255,14 +248,14 @@ private void processAnnotated(SmtTermFrame frame) { if (key.equals("rup")) { this.proofRule = Rup.RUP; - //this.children.add(new ProvitionalProofNode(term.getSubterm())); + // this.children.add(new ProvitionalProofNode(term.getSubterm())); frame.setNumArgs(1); if (!computed.containsKey(term.getSubterm())) { SmtTermFrame childFrame = new SmtTermFrame(term.getSubterm()); stack.push(childFrame); frame.children.add(childFrame); - //children.add(new ProvitionalProofNode(term.getSubterm())); - //computed.put(term, this); + // children.add(new ProvitionalProofNode(term.getSubterm())); + // computed.put(term, this); computed.put(term.getSubterm(), new ProvitionalProofNode(term.getSubterm())); } rup = true; @@ -272,7 +265,6 @@ private void processAnnotated(SmtTermFrame frame) { Object[] values = (Object[]) annotation.getValue(); addTermsFromAnnotationValue(values, true); } - } if (!rup) { frame.setProof(term.getSubterm()); @@ -296,7 +288,6 @@ void addTermsFromAnnotationValue(Object[] values, boolean isProves) { } else { this.formulas.add((Term) values[i]); } - } } } @@ -314,8 +305,10 @@ String asString(int indentLevel) { // Node properties sb.append(indent).append(" pivot: ").append(pivot != null ? pivot : "null").append("\n"); - sb.append(indent).append(" proofRule: ") - .append(proofRule != null ? proofRule.getName() : "null").append("\n"); + sb.append(indent) + .append(" proofRule: ") + .append(proofRule != null ? proofRule.getName() : "null") + .append("\n"); sb.append(indent).append(" axiom: ").append(axiom).append("\n"); sb.append(indent).append(" isVisited: ").append(isVisited).append("\n"); @@ -331,7 +324,8 @@ String asString(int indentLevel) { sb.append(indent).append(" ]\n"); // Unprocessed term - sb.append(indent).append(" unprocessedTerm: ") + sb.append(indent) + .append(" unprocessedTerm: ") .append(unprocessedTerm != null ? unprocessedTerm : "null") .append("\n"); diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java index 4e3959f3a5..fd3474f096 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java @@ -266,7 +266,7 @@ private void processAppTerm(ApplicationTerm term) { } @Test - public void testPPN(){ + public void testPPN() { // example from the 2022 paper BooleanFormula q1 = bmgr.makeVariable("q1"); BooleanFormula q2 = bmgr.makeVariable("q2"); @@ -291,7 +291,7 @@ public void testPPN(){ SmtInterpolProofNodeCreator pc = new SmtInterpolProofNodeCreator( - (SmtInterpolFormulaCreator) prover.mgr.getFormulaCreator(),prover); + (SmtInterpolFormulaCreator) prover.mgr.getFormulaCreator(), prover); assertThat(pc.createPPNDag(proof)).isNotNull(); From f81f2e3d5f02523964bb4dba7721c73a2f5b0b37 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 7 Apr 2025 21:10:52 +0200 Subject: [PATCH 068/132] Mathsat5: nodes with the `THEORY_LEMMA` `ProofRule` now also have a non `null` value for the `Formula`, a conjunction of the terms that Mathsat5 returns as children. The only children of these nodes are now the optional extra proof. These extra proofs do not conform to the format: not every node has both `Formula` and `ProofRule` --- .../solvers/mathsat5/Mathsat5ProofNode.java | 171 +++++++++--------- .../solvers/mathsat5/Mathsat5ProofRule.java | 31 ++-- .../mathsat5/Mathsat5TheoremProver.java | 88 ++++++++- 3 files changed, 194 insertions(+), 96 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java index 7f2107140b..9ef94c5eb8 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java @@ -10,7 +10,7 @@ package org.sosy_lab.java_smt.solvers.mathsat5; -import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_proof; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_make_and; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_make_or; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_get_arity; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_get_child; @@ -19,10 +19,8 @@ import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_proof_is_term; import java.util.ArrayDeque; -import java.util.ArrayList; import java.util.Deque; import java.util.HashMap; -import java.util.List; import java.util.Map; import javax.annotation.Nullable; import org.sosy_lab.java_smt.api.Formula; @@ -33,114 +31,119 @@ import org.sosy_lab.java_smt.basicimpl.AbstractProofDag.AbstractProofNode; import org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5ProofRule.Rule; - public class Mathsat5ProofNode extends AbstractProofNode { protected Mathsat5ProofNode(@Nullable ProofRule rule, Formula formula) { super(rule, formula); - } protected static class MsatProofFrame extends ProofFrame { MsatProofFrame(Long proof) { super(proof); } + boolean skip = false; } - /** - * Creates a proof node from a MathSAT5 proof object. - * - * Not all proof rules are known beforehand, so some are not in the enum. This means that - * (specifically) the sub-DAG of the theory-lemma rule may contain a sub-proof that does - * not have either a {@link ProofRule} or a {@link Formula} in a given node. - * - * @param pProver The prover environment. - * @param rootProof The root proof object. - * @return The proof node. - */ + /** + * Creates a proof node from a MathSAT5 proof object. + * + *

Not all proof rules are known beforehand, so some are not in the enum. This means that + * (specifically) the sub-DAG of the theory-lemma rule may contain a sub-proof that does not have + * either a {@link ProofRule} or a {@link Formula} in a given node. + * + * @param pProver The prover environment. + * @param rootProof The root proof object. + * @return The proof node. + */ public static Mathsat5ProofNode fromMsatProof(ProverEnvironment pProver, long rootProof) { - Deque stack = new ArrayDeque<>(); - Map computed = new HashMap<>(); + Deque stack = new ArrayDeque<>(); + Map computed = new HashMap<>(); - stack.push(new MsatProofFrame(rootProof)); + stack.push(new MsatProofFrame(rootProof)); + while (!stack.isEmpty()) { + MsatProofFrame frame = stack.peek(); - while (!stack.isEmpty()) { - MsatProofFrame frame = stack.peek(); + if (!frame.isVisited()) { + frame.setAsVisited(true); + String rule = + msat_proof_get_name(frame.getProof()) == null + ? "null" + : msat_proof_get_name(frame.getProof()); - if (!frame.isVisited()) { + // If rule is claus-hyp, all the children get added to the dag in generateFormula + if (!rule.equals("clause-hyp")) { frame.setNumArgs(msat_proof_get_arity(frame.getProof())); - frame.setAsVisited(true); - String rule = msat_proof_get_name(frame.getProof()) == null ? "null" : - msat_proof_get_name(frame.getProof()); - for (int i = frame.getNumArgs()-1; i >= 0; i--) { - + for (int i = frame.getNumArgs() - 1; i >= 0; i--) { long child = msat_proof_get_child(frame.getProof(), i); - - //If rule is claus-hyp, all the children get added to the dag in generateFormula - if (!computed.containsKey(child) && !rule.equals( - "clause" - + "-hyp")) { - //If the rules is theory-lemma and the child is a term, it gets added to the dag - // in generateFormula - if(rule.equals( - "theory-lemma") && msat_proof_is_term(frame.getProof())) { - frame.setNumArgs(frame.getNumArgs()-1); - continue; - } - stack.push(new MsatProofFrame(child)); - } else { - frame.setNumArgs(frame.getNumArgs()-1); + if (!computed.containsKey(child)) { + // If the rules is theory-lemma and the child is a term, it gets added to the dag + // in generateFormula otherwise we push it to the stack to be processed later. + switch (rule) { + case "theory-lemma": + if (msat_proof_is_term(child)) { + frame.setNumArgs(frame.getNumArgs() - 1); + System.out.println("theory-lemma rule has " + frame.getNumArgs() + " children"); + } else { + System.out.println("pushing theoryy-lemma non term child " + child); + System.out.println("thoryy-lemma rule has " + frame.getNumArgs() + " children"); + stack.push(new MsatProofFrame(child)); + } + break; + default: + stack.push(new MsatProofFrame(child)); + break; } + } } - } else { - // Process the node after all its children have been processed. This should help to - // recreate the formula for the node correctly. - stack.pop(); - - // Generate the formula and proof rule. - - String rule = msat_proof_get_name(frame.getProof()); - ProofRule proofRule; - - //If the theory-lemma rule includes a last argument that is not a term, it means it has - // a proof attached to it. Not all rules are known beforehand so they are not in the enum. - try { - proofRule = rule == null ? Rule.NULL : - Rule.valueOf(rule.toUpperCase().replace("-", "_")); - } catch (IllegalArgumentException e) { - proofRule = new Mathsat5ProofRule(rule); - } + } + } else { + + stack.pop(); - Mathsat5ProofNode node; - Mathsat5TheoremProver prover = (Mathsat5TheoremProver) pProver; - Formula formula = generateFormula(frame, prover, proofRule); + String rule = msat_proof_get_name(frame.getProof()); + ProofRule proofRule; + // If the theory-lemma rule includes a last argument that is not a term, it means it has + // a proof attached to it. Not all rules are known beforehand so they are not in the enum. + try { + proofRule = rule == null ? Rule.NULL : Rule.valueOf(rule.toUpperCase().replace("-", "_")); + } catch (IllegalArgumentException e) { + proofRule = new Mathsat5ProofRule(rule); + } - node = new Mathsat5ProofNode(proofRule, formula); + Mathsat5ProofNode node; + Mathsat5TheoremProver prover = (Mathsat5TheoremProver) pProver; + Formula formula = generateFormula(frame, prover, proofRule); - // Retrieve computed child nodes and attach them. - for (int i = 0; i < frame.getNumArgs(); i++) { - long child = msat_proof_get_child(frame.getProof(), i); - Mathsat5ProofNode childNode = computed.get(child); - if (childNode != null) { - node.addChild(childNode); - } - } + node = new Mathsat5ProofNode(proofRule, formula); + // Retrieve computed child nodes and attach them. In this case the subtraction is due to + // the processing of the theory-lemma rule. + for (int i = (msat_proof_get_arity(frame.getProof()) - frame.getNumArgs()); + i < msat_proof_get_arity(frame.getProof()); + i++) { - computed.put(frame.getProof(), node); + // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + long child = msat_proof_get_child(frame.getProof(), i); + + Mathsat5ProofNode childNode = computed.get(child); + if (childNode != null) { + node.addChild(childNode); + } } + computed.put(frame.getProof(), node); } - return computed.get(rootProof); + } + return computed.get(rootProof); } @Nullable - private static Formula generateFormula(MsatProofFrame frame, Mathsat5TheoremProver prover, - ProofRule rule) { + private static Formula generateFormula( + MsatProofFrame frame, Mathsat5TheoremProver prover, ProofRule rule) { Mathsat5FormulaCreator formulaCreator = prover.creator; Formula formula = null; long proof = frame.getProof(); @@ -148,29 +151,31 @@ private static Formula generateFormula(MsatProofFrame frame, Mathsat5TheoremProv // If rule is NULL the proof should be a term and we encapsulate directly if (rule.equals(Rule.NULL)) { formula = - formulaCreator.encapsulate(formulaCreator.getFormulaType(msat_proof_get_term(proof)), msat_proof_get_term(proof)); - //For clause-hype, we create the clause using the children + formulaCreator.encapsulate( + formulaCreator.getFormulaType(msat_proof_get_term(proof)), + msat_proof_get_term(proof)); + // For clause-hype, we create the clause using the children } else if (rule.equals(Rule.CLAUSE_HYP)) { long or = msat_proof_get_term(msat_proof_get_child(proof, 0)); - for (int i = 1; i < children ; i++) { + for (int i = 1; i < children; i++) { long child = msat_proof_get_term(msat_proof_get_child(proof, i)); or = msat_make_or(prover.curEnv, or, child); } formula = formulaCreator.encapsulate(formulaCreator.getFormulaType(or), or); } else if (rule.equals(Rule.RES_CHAIN)) { - //Generating the formula for the resolution chain should be easier after the whole DAG is + // Generating the formula for the resolution chain should be easier after the whole DAG is // built } else if (rule.equals(Rule.THEORY_LEMMA)) { if (msat_proof_is_term(msat_proof_get_child(proof, 0))) { long and = msat_proof_get_term(msat_proof_get_child(proof, 0)); for (int i = 1; i < children; i++) { if (msat_proof_is_term(msat_proof_get_child(proof, i))) { - long child = msat_proof_get_term(msat_proof_get_child(proof, i)); - and = msat_make_or(prover.curEnv, and, child); + and = msat_make_and(prover.curEnv, and, child); } } - } + formula = formulaCreator.encapsulate(formulaCreator.getFormulaType(and), and); + } } return formula; } diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java index 8f101651d1..9982bf88b9 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java @@ -13,21 +13,28 @@ import org.sosy_lab.java_smt.api.proofs.ProofRule; class Mathsat5ProofRule implements ProofRule { -//Most comments are taken from the API Reference: https://mathsat.fbk.eu/apireference.html + // Most comments are taken from the API Reference: https://mathsat.fbk.eu/apireference.html // - enum Rule implements ProofRule{ - THEORY_LEMMA(),//" representing theory lemmas. They have as children a list of terms that consititute the lemma, plus an optional last element which is a more detailed proof produced by a theory solver." - RES_CHAIN(),//"representing Boolean resolution chains. The children are an interleaving of proofs and terms, where terms are the pivots for the resolution. For example: "res-chain p1 v p2" represents a resolution step between p1 and p2 on the pivot v" - CLAUSE_HYP(), //" which are the clauses of the (CNF conversion of the) input problem. They have - // a list of terms as children" - NULL()//We introduce this rule because Term Nodes in MathSAT5 do not have a rule associated with them. - ; - @Override - public String getName() { - return name(); - } + enum Rule implements ProofRule { + THEORY_LEMMA(), // " representing theory lemmas. They have as children a list of terms that + // consititute the lemma, plus an optional last element which is a more detailed + // proof produced by a theory solver." + RES_CHAIN(), // "representing Boolean resolution chains. The children are an interleaving of + // proofs and terms, where terms are the pivots for the resolution. For example: + // "res-chain p1 v p2" represents a resolution step between p1 and p2 on the pivot + // v" + CLAUSE_HYP(), // " which are the clauses of the (CNF conversion of the) input problem. They have + // a list of terms as children" + NULL() // We introduce this rule because Term Nodes in MathSAT5 do not have a rule associated + // with them. + ; + @Override + public String getName() { + return name(); + } } + private String name; Mathsat5ProofRule(String pName) { diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java index 9156524c15..8ae3900f71 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java @@ -15,15 +15,23 @@ import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_proof_manager; import com.google.common.base.Preconditions; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Set; import org.checkerframework.checker.nullness.qual.Nullable; import org.sosy_lab.common.ShutdownNotifier; import org.sosy_lab.java_smt.api.BooleanFormula; +import org.sosy_lab.java_smt.api.BooleanFormulaManager; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.FunctionDeclaration; import org.sosy_lab.java_smt.api.ProverEnvironment; +import org.sosy_lab.java_smt.api.QuantifiedFormulaManager.Quantifier; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.visitors.BooleanFormulaVisitor; +import org.sosy_lab.java_smt.api.visitors.TraversalProcess; import org.sosy_lab.java_smt.basicimpl.ProofFactory; class Mathsat5TheoremProver extends Mathsat5AbstractProver implements ProverEnvironment { @@ -59,13 +67,91 @@ public ProofNode getProof() throws SolverException, InterruptedException { long pm = msat_get_proof_manager(curEnv); long proof = msat_get_proof(pm); pn = Mathsat5ProofNode.fromMsatProof(this, proof); + context.getFormulaManager().getBooleanFormulaManager(); + ProofNode result = pn; + // ProofNode result = clausifyResChain(pn, context.getFormulaManager() + // .getBooleanFormulaManager()); msat_destroy_proof_manager(pm); - return pn; + return result; // return getProof0(); } + private ProofNode clausifyResChain(ProofNode proof, BooleanFormulaManager bfmgr) { + BooleanFormulaVisitor extractor = + new BooleanFormulaVisitor<>() { + List andList = new ArrayList<>(); + List orList = new ArrayList<>(); + + @Override + public TraversalProcess visitConstant(boolean value) { + return TraversalProcess.CONTINUE; + } + + @Override + public TraversalProcess visitBoundVar(BooleanFormula var, int deBruijnIdx) { + return TraversalProcess.CONTINUE; + } + + @Override + public TraversalProcess visitNot(BooleanFormula operand) { + return TraversalProcess.CONTINUE; + } + + @Override + public TraversalProcess visitAnd(List operands) { + andList.addAll(operands); + return TraversalProcess.CONTINUE; + } + + @Override + public TraversalProcess visitOr(List operands) { + orList.addAll(operands); + return TraversalProcess.CONTINUE; + } + + @Override + public TraversalProcess visitXor(BooleanFormula operand1, BooleanFormula operand2) { + return TraversalProcess.CONTINUE; + } + + @Override + public TraversalProcess visitEquivalence( + BooleanFormula operand1, BooleanFormula operand2) { + return TraversalProcess.CONTINUE; + } + + @Override + public TraversalProcess visitImplication( + BooleanFormula operand1, BooleanFormula operand2) { + return TraversalProcess.CONTINUE; + } + + @Override + public TraversalProcess visitIfThenElse( + BooleanFormula condition, BooleanFormula thenFormula, BooleanFormula elseFormula) { + return TraversalProcess.CONTINUE; + } + + @Override + public TraversalProcess visitQuantifier( + Quantifier quantifier, + BooleanFormula quantifiedAST, + List boundVars, + BooleanFormula body) { + return TraversalProcess.CONTINUE; + } + + @Override + public TraversalProcess visitAtom( + BooleanFormula atom, FunctionDeclaration funcDecl) { + return TraversalProcess.CONTINUE; + } + }; + return null; + } + protected ProofNode getProof0() { var proofFactory = new ProofFactory(this, "MATHSAT5") { From 6fa3a60870295c263a2c6310267aeead47f502cb Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Tue, 8 Apr 2025 09:34:19 +0200 Subject: [PATCH 069/132] Mathsat5: nodes with the `RES_CHAIN` `ProofRule` now also have a non `null` value for the `Formula`, a clause derived from applying chain resolution to the formulas of its children. --- .../java_smt/basicimpl/AbstractProofDag.java | 2 +- .../solvers/mathsat5/Mathsat5ProofNode.java | 7 +- .../mathsat5/Mathsat5TheoremProver.java | 204 +++++++++++++----- 3 files changed, 159 insertions(+), 54 deletions(-) diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java index c84afc0eab..730e022440 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java @@ -64,7 +64,7 @@ public void accept(ProofVisitor visitor) { public abstract static class AbstractProofNode implements ProofNode { private final List children; private ProofRule rule; - private Formula formula; + protected Formula formula; private static final UniqueIdGenerator idGenerator = new UniqueIdGenerator(); private final int id; diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java index 9ef94c5eb8..5bb86ef121 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java @@ -85,10 +85,7 @@ public static Mathsat5ProofNode fromMsatProof(ProverEnvironment pProver, long ro case "theory-lemma": if (msat_proof_is_term(child)) { frame.setNumArgs(frame.getNumArgs() - 1); - System.out.println("theory-lemma rule has " + frame.getNumArgs() + " children"); } else { - System.out.println("pushing theoryy-lemma non term child " + child); - System.out.println("thoryy-lemma rule has " + frame.getNumArgs() + " children"); stack.push(new MsatProofFrame(child)); } break; @@ -180,6 +177,10 @@ private static Formula generateFormula( return formula; } + void setFormula(Formula formula) { + this.formula = formula; + } + String asString() { return asString(0); } diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java index 8ae3900f71..2f01038591 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java @@ -33,6 +33,7 @@ import org.sosy_lab.java_smt.api.visitors.BooleanFormulaVisitor; import org.sosy_lab.java_smt.api.visitors.TraversalProcess; import org.sosy_lab.java_smt.basicimpl.ProofFactory; +import org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5ProofRule.Rule; class Mathsat5TheoremProver extends Mathsat5AbstractProver implements ProverEnvironment { @@ -69,8 +70,7 @@ public ProofNode getProof() throws SolverException, InterruptedException { pn = Mathsat5ProofNode.fromMsatProof(this, proof); context.getFormulaManager().getBooleanFormulaManager(); ProofNode result = pn; - // ProofNode result = clausifyResChain(pn, context.getFormulaManager() - // .getBooleanFormulaManager()); + result = clausifyResChain(pn, context.getFormulaManager().getBooleanFormulaManager()); msat_destroy_proof_manager(pm); return result; @@ -78,80 +78,184 @@ public ProofNode getProof() throws SolverException, InterruptedException { // return getProof0(); } - private ProofNode clausifyResChain(ProofNode proof, BooleanFormulaManager bfmgr) { - BooleanFormulaVisitor extractor = - new BooleanFormulaVisitor<>() { - List andList = new ArrayList<>(); - List orList = new ArrayList<>(); + // Entry point: recursively update all RES_CHAIN nodes in the proof DAG by computing resolution +// formulas and return the updated root node with formulas attached. + private ProofNode clausifyResChain(ProofNode root, BooleanFormulaManager bfmgr) { + return processResChain(root, bfmgr); // Start traversal and resolution from root node + } - @Override - public TraversalProcess visitConstant(boolean value) { - return TraversalProcess.CONTINUE; - } + // Recursively process proof nodes and compute formulas for res-chain nodes + private ProofNode processResChain(ProofNode node, BooleanFormulaManager bfmgr) { + List children = node.getChildren(); + List newChildren = new ArrayList<>(); - @Override - public TraversalProcess visitBoundVar(BooleanFormula var, int deBruijnIdx) { - return TraversalProcess.CONTINUE; - } + // First process all children recursively so their formulas are computed + for (ProofNode child : children) { + newChildren.add(processResChain(child, bfmgr)); + } - @Override - public TraversalProcess visitNot(BooleanFormula operand) { - return TraversalProcess.CONTINUE; - } + // If the current node is a RES_CHAIN, compute the resolved formula + if (node.getRule().equals(Rule.RES_CHAIN)) { + // Sanity check: res-chain nodes must have an odd number of children (clause, pivot, clause, ..., clause) + if (newChildren.size() < 3 || newChildren.size() % 2 == 0) { + throw new IllegalArgumentException("Invalid res-chain structure: must be odd and >= 3"); + } - @Override - public TraversalProcess visitAnd(List operands) { - andList.addAll(operands); - return TraversalProcess.CONTINUE; - } + // Begin resolution chain: start with the first clause + BooleanFormula current = (BooleanFormula) newChildren.get(0).getFormula(); + // Apply resolution iteratively using pivot, clause pairs + for (int i = 1; i < newChildren.size() - 1; i += 2) { + BooleanFormula pivot = (BooleanFormula) newChildren.get(i).getFormula(); + BooleanFormula nextClause = (BooleanFormula) newChildren.get(i + 1).getFormula(); + current = resolve(current, nextClause, pivot, bfmgr); // Perform resolution step + } + + // Store the resolved formula in the current node + ((Mathsat5ProofNode) node).setFormula(current); + } + + return node; // Return updated node (either modified or unchanged) + } + + // Perform resolution between two disjunctive clauses using a given pivot + private BooleanFormula resolve(BooleanFormula clause1, BooleanFormula clause2, + BooleanFormula pivot, BooleanFormulaManager bfmgr) { + List literals1 = flattenLiterals(clause1, bfmgr); + List literals2 = flattenLiterals(clause2, bfmgr); + List combined = new ArrayList<>(); + + boolean removed = false; + + for (BooleanFormula lit : literals1) { + if (isComplement(lit, pivot, bfmgr)) { + removed = true; + } else { + combined.add(lit); + } + } + + List temp = new ArrayList<>(); + boolean removed2 = false; + for (BooleanFormula lit : literals2) { + if (isComplement(lit, pivot, bfmgr)) { + removed2 = true; + } else { + temp.add(lit); + } + } + + combined.addAll(temp); + + if (!(removed && removed2)) { + System.err.println("Warning: Pivot not found correctly in clauses during resolution."); + System.err.println("Clause 1: " + clause1); + System.err.println("Clause 2: " + clause2); + System.err.println("Pivot: " + pivot); + } + + if (combined.isEmpty()) { + return bfmgr.makeFalse(); + } else if (combined.size() == 1) { + return combined.get(0); + } else { + return bfmgr.or(combined); + } + } + + + + // Helper method to flatten an OR-formula into a list of disjunctive literals + private List flattenLiterals(BooleanFormula formula, BooleanFormulaManager bfmgr) { + List result = new ArrayList<>(); + + bfmgr.visit( + formula, + new BooleanFormulaVisitor<>() { @Override public TraversalProcess visitOr(List operands) { - orList.addAll(operands); - return TraversalProcess.CONTINUE; + for (BooleanFormula op : operands) { + result.addAll(flattenLiterals(op, bfmgr)); + } + return TraversalProcess.SKIP; } @Override - public TraversalProcess visitXor(BooleanFormula operand1, BooleanFormula operand2) { - return TraversalProcess.CONTINUE; + public TraversalProcess visitAnd(List operands) { + for (BooleanFormula op : operands) { + result.addAll(flattenLiterals(op, bfmgr)); + } + return TraversalProcess.SKIP; } @Override - public TraversalProcess visitEquivalence( - BooleanFormula operand1, BooleanFormula operand2) { - return TraversalProcess.CONTINUE; + public TraversalProcess visitNot(BooleanFormula operand) { + result.add(formula); // ✅ add original NOT node + return TraversalProcess.SKIP; } @Override - public TraversalProcess visitImplication( - BooleanFormula operand1, BooleanFormula operand2) { - return TraversalProcess.CONTINUE; + public TraversalProcess visitAtom(BooleanFormula atom, FunctionDeclaration decl) { + result.add(formula); // ✅ add original atom + return TraversalProcess.SKIP; } - @Override - public TraversalProcess visitIfThenElse( - BooleanFormula condition, BooleanFormula thenFormula, BooleanFormula elseFormula) { - return TraversalProcess.CONTINUE; - } + // others unchanged... + @Override public TraversalProcess visitXor(BooleanFormula a, BooleanFormula b) { return TraversalProcess.SKIP; } + @Override public TraversalProcess visitEquivalence(BooleanFormula a, BooleanFormula b) { return TraversalProcess.SKIP; } + @Override public TraversalProcess visitImplication(BooleanFormula a, BooleanFormula b) { return TraversalProcess.SKIP; } + @Override public TraversalProcess visitIfThenElse(BooleanFormula c, BooleanFormula t, BooleanFormula e) { return TraversalProcess.SKIP; } + @Override public TraversalProcess visitQuantifier(Quantifier q, BooleanFormula qBody, List vars, BooleanFormula body) { return TraversalProcess.SKIP; } + @Override public TraversalProcess visitConstant(boolean value) { return TraversalProcess.SKIP; } + @Override public TraversalProcess visitBoundVar(BooleanFormula var, int index) { return TraversalProcess.SKIP; } + }); + + return result; + } + + + // Check whether two formulas are logical complements + private boolean isComplement(BooleanFormula a, BooleanFormula b, BooleanFormulaManager bfmgr) { + // Define the visitor to check for complement relation + final boolean[] isComplement = {false}; + bfmgr.visitRecursively( + a, + new BooleanFormulaVisitor<>() { @Override - public TraversalProcess visitQuantifier( - Quantifier quantifier, - BooleanFormula quantifiedAST, - List boundVars, - BooleanFormula body) { - return TraversalProcess.CONTINUE; + public TraversalProcess visitNot(BooleanFormula operand) { + // Check if the negation of 'operand' equals 'b' + if (operand.equals(b)) { + isComplement[0] = true; + } + return TraversalProcess.SKIP; } @Override - public TraversalProcess visitAtom( - BooleanFormula atom, FunctionDeclaration funcDecl) { - return TraversalProcess.CONTINUE; + public TraversalProcess visitAtom(BooleanFormula atom, FunctionDeclaration decl) { + if (atom.equals(b)) { + isComplement[0] = true; + } + return TraversalProcess.SKIP; } - }; - return null; + + // Default implementation for other nodes, such as OR, AND, etc. + @Override public TraversalProcess visitOr(List operands) { return TraversalProcess.SKIP; } + @Override public TraversalProcess visitAnd(List operands) { return TraversalProcess.SKIP; } + @Override public TraversalProcess visitXor(BooleanFormula a, BooleanFormula b) { return TraversalProcess.SKIP; } + @Override public TraversalProcess visitEquivalence(BooleanFormula a, BooleanFormula b) { return TraversalProcess.SKIP; } + @Override public TraversalProcess visitImplication(BooleanFormula a, BooleanFormula b) { return TraversalProcess.SKIP; } + @Override public TraversalProcess visitIfThenElse(BooleanFormula c, BooleanFormula t, BooleanFormula e) { return TraversalProcess.SKIP; } + @Override public TraversalProcess visitQuantifier(Quantifier q, BooleanFormula qBody, List vars, BooleanFormula body) { return TraversalProcess.SKIP; } + @Override public TraversalProcess visitConstant(boolean value) { return TraversalProcess.SKIP; } + @Override public TraversalProcess visitBoundVar(BooleanFormula var, int index) { return TraversalProcess.SKIP; } + }); + + return isComplement[0]; } + + protected ProofNode getProof0() { var proofFactory = new ProofFactory(this, "MATHSAT5") { From 7fa1304a55c4d44a8eae4ea0f5f64beafbee5044 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Tue, 8 Apr 2025 20:45:23 +0200 Subject: [PATCH 070/132] Documentation, checkstyle and deleted unnecessary checks --- .../solvers/mathsat5/Mathsat5ProofRule.java | 12 +- .../mathsat5/Mathsat5TheoremProver.java | 135 +++++++++++++----- 2 files changed, 104 insertions(+), 43 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java index 9982bf88b9..742098f19d 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java @@ -17,16 +17,16 @@ class Mathsat5ProofRule implements ProofRule { // enum Rule implements ProofRule { THEORY_LEMMA(), // " representing theory lemmas. They have as children a list of terms that - // consititute the lemma, plus an optional last element which is a more detailed - // proof produced by a theory solver." + // consititute the lemma, plus an optional last element which is a more detailed + // proof produced by a theory solver." RES_CHAIN(), // "representing Boolean resolution chains. The children are an interleaving of - // proofs and terms, where terms are the pivots for the resolution. For example: - // "res-chain p1 v p2" represents a resolution step between p1 and p2 on the pivot - // v" + // proofs and terms, where terms are the pivots for the resolution. For example: + // "res-chain p1 v p2" represents a resolution step between p1 and p2 on the pivot + // v" CLAUSE_HYP(), // " which are the clauses of the (CNF conversion of the) input problem. They have // a list of terms as children" NULL() // We introduce this rule because Term Nodes in MathSAT5 do not have a rule associated - // with them. + // with them. ; @Override diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java index 2f01038591..29b9efcb8b 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java @@ -78,8 +78,8 @@ public ProofNode getProof() throws SolverException, InterruptedException { // return getProof0(); } - // Entry point: recursively update all RES_CHAIN nodes in the proof DAG by computing resolution -// formulas and return the updated root node with formulas attached. + // recursively update all RES_CHAIN nodes in the proof DAG by computing resolution + // formulas and return the updated root node with formulas attached. private ProofNode clausifyResChain(ProofNode root, BooleanFormulaManager bfmgr) { return processResChain(root, bfmgr); // Start traversal and resolution from root node } @@ -96,7 +96,8 @@ private ProofNode processResChain(ProofNode node, BooleanFormulaManager bfmgr) { // If the current node is a RES_CHAIN, compute the resolved formula if (node.getRule().equals(Rule.RES_CHAIN)) { - // Sanity check: res-chain nodes must have an odd number of children (clause, pivot, clause, ..., clause) + // Sanity check: res-chain nodes must have an odd number of children (clause, pivot, clause, + // ..., clause) if (newChildren.size() < 3 || newChildren.size() % 2 == 0) { throw new IllegalArgumentException("Invalid res-chain structure: must be odd and >= 3"); } @@ -115,12 +116,15 @@ private ProofNode processResChain(ProofNode node, BooleanFormulaManager bfmgr) { ((Mathsat5ProofNode) node).setFormula(current); } - return node; // Return updated node (either modified or unchanged) + return node; } // Perform resolution between two disjunctive clauses using a given pivot - private BooleanFormula resolve(BooleanFormula clause1, BooleanFormula clause2, - BooleanFormula pivot, BooleanFormulaManager bfmgr) { + private BooleanFormula resolve( + BooleanFormula clause1, + BooleanFormula clause2, + BooleanFormula pivot, + BooleanFormulaManager bfmgr) { List literals1 = flattenLiterals(clause1, bfmgr); List literals2 = flattenLiterals(clause2, bfmgr); List combined = new ArrayList<>(); @@ -147,13 +151,6 @@ private BooleanFormula resolve(BooleanFormula clause1, BooleanFormula clause2, combined.addAll(temp); - if (!(removed && removed2)) { - System.err.println("Warning: Pivot not found correctly in clauses during resolution."); - System.err.println("Clause 1: " + clause1); - System.err.println("Clause 2: " + clause2); - System.err.println("Pivot: " + pivot); - } - if (combined.isEmpty()) { return bfmgr.makeFalse(); } else if (combined.size() == 1) { @@ -163,10 +160,9 @@ private BooleanFormula resolve(BooleanFormula clause1, BooleanFormula clause2, } } - - // Helper method to flatten an OR-formula into a list of disjunctive literals - private List flattenLiterals(BooleanFormula formula, BooleanFormulaManager bfmgr) { + private List flattenLiterals( + BooleanFormula formula, BooleanFormulaManager bfmgr) { List result = new ArrayList<>(); bfmgr.visit( @@ -195,25 +191,54 @@ public TraversalProcess visitNot(BooleanFormula operand) { } @Override - public TraversalProcess visitAtom(BooleanFormula atom, FunctionDeclaration decl) { + public TraversalProcess visitAtom( + BooleanFormula atom, FunctionDeclaration decl) { result.add(formula); // ✅ add original atom return TraversalProcess.SKIP; } // others unchanged... - @Override public TraversalProcess visitXor(BooleanFormula a, BooleanFormula b) { return TraversalProcess.SKIP; } - @Override public TraversalProcess visitEquivalence(BooleanFormula a, BooleanFormula b) { return TraversalProcess.SKIP; } - @Override public TraversalProcess visitImplication(BooleanFormula a, BooleanFormula b) { return TraversalProcess.SKIP; } - @Override public TraversalProcess visitIfThenElse(BooleanFormula c, BooleanFormula t, BooleanFormula e) { return TraversalProcess.SKIP; } - @Override public TraversalProcess visitQuantifier(Quantifier q, BooleanFormula qBody, List vars, BooleanFormula body) { return TraversalProcess.SKIP; } - @Override public TraversalProcess visitConstant(boolean value) { return TraversalProcess.SKIP; } - @Override public TraversalProcess visitBoundVar(BooleanFormula var, int index) { return TraversalProcess.SKIP; } + @Override + public TraversalProcess visitXor(BooleanFormula a, BooleanFormula b) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitEquivalence(BooleanFormula a, BooleanFormula b) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitImplication(BooleanFormula a, BooleanFormula b) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitIfThenElse( + BooleanFormula c, BooleanFormula t, BooleanFormula e) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitQuantifier( + Quantifier q, BooleanFormula qBody, List vars, BooleanFormula body) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitConstant(boolean value) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitBoundVar(BooleanFormula var, int index) { + return TraversalProcess.SKIP; + } }); return result; } - // Check whether two formulas are logical complements private boolean isComplement(BooleanFormula a, BooleanFormula b, BooleanFormulaManager bfmgr) { // Define the visitor to check for complement relation @@ -232,7 +257,8 @@ public TraversalProcess visitNot(BooleanFormula operand) { } @Override - public TraversalProcess visitAtom(BooleanFormula atom, FunctionDeclaration decl) { + public TraversalProcess visitAtom( + BooleanFormula atom, FunctionDeclaration decl) { if (atom.equals(b)) { isComplement[0] = true; } @@ -240,22 +266,57 @@ public TraversalProcess visitAtom(BooleanFormula atom, FunctionDeclaration operands) { return TraversalProcess.SKIP; } - @Override public TraversalProcess visitAnd(List operands) { return TraversalProcess.SKIP; } - @Override public TraversalProcess visitXor(BooleanFormula a, BooleanFormula b) { return TraversalProcess.SKIP; } - @Override public TraversalProcess visitEquivalence(BooleanFormula a, BooleanFormula b) { return TraversalProcess.SKIP; } - @Override public TraversalProcess visitImplication(BooleanFormula a, BooleanFormula b) { return TraversalProcess.SKIP; } - @Override public TraversalProcess visitIfThenElse(BooleanFormula c, BooleanFormula t, BooleanFormula e) { return TraversalProcess.SKIP; } - @Override public TraversalProcess visitQuantifier(Quantifier q, BooleanFormula qBody, List vars, BooleanFormula body) { return TraversalProcess.SKIP; } - @Override public TraversalProcess visitConstant(boolean value) { return TraversalProcess.SKIP; } - @Override public TraversalProcess visitBoundVar(BooleanFormula var, int index) { return TraversalProcess.SKIP; } + @Override + public TraversalProcess visitOr(List operands) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitAnd(List operands) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitXor(BooleanFormula a, BooleanFormula b) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitEquivalence(BooleanFormula a, BooleanFormula b) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitImplication(BooleanFormula a, BooleanFormula b) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitIfThenElse( + BooleanFormula c, BooleanFormula t, BooleanFormula e) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitQuantifier( + Quantifier q, BooleanFormula qBody, List vars, BooleanFormula body) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitConstant(boolean value) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitBoundVar(BooleanFormula var, int index) { + return TraversalProcess.SKIP; + } }); return isComplement[0]; } - - protected ProofNode getProof0() { var proofFactory = new ProofFactory(this, "MATHSAT5") { From 50ecf104171be424a9165c1cc97fcfa9a8379ec1 Mon Sep 17 00:00:00 2001 From: BaierD Date: Thu, 10 Apr 2025 16:32:13 +0200 Subject: [PATCH 071/132] Add a Mathsat5 native test for proof generation options in shared environments --- .../mathsat5/Mathsat5NativeApiTest.java | 40 ++++++++++++++----- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java index 261c2f305f..c3fe83bfaf 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java @@ -13,6 +13,7 @@ import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_check_sat; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_create_config; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_create_env; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_create_shared_env; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_decl_get_arity; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_decl_get_name; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_destroy_config; @@ -107,20 +108,41 @@ public void proofTest() throws IllegalStateException, InterruptedException, Solv env = msat_create_env(cfg); msat_destroy_config(cfg); - const0 = msat_make_number(env, "0"); - const1 = msat_make_number(env, "1"); - long rationalType = msat_get_rational_type(env); - var = msat_make_variable(env, "rat", rationalType); + testProofManager(env); + } - msat_push_backtrack_point(env); + // Tests if it is possible to enable proof generation in a shared environment after it was not + // enabled in the original + @Test + public void proofSharedEnvironmentTest() + throws IllegalStateException, InterruptedException, SolverException { + long cfg = msat_create_config(); + env = msat_create_env(cfg); + msat_destroy_config(cfg); - msat_assert_formula(env, msat_make_equal(env, var, const0)); - msat_assert_formula(env, msat_make_equal(env, var, const1)); + cfg = msat_create_config(); + msat_set_option_checked(cfg, "proof_generation", "true"); + long sharedEnv = msat_create_shared_env(cfg, env); + msat_destroy_config(cfg); + + testProofManager(sharedEnv); + } + + private void testProofManager(long testEnv) throws InterruptedException, SolverException { + const0 = msat_make_number(testEnv, "0"); + const1 = msat_make_number(testEnv, "1"); + long rationalType = msat_get_rational_type(testEnv); + var = msat_make_variable(testEnv, "rat", rationalType); + + msat_push_backtrack_point(testEnv); + + msat_assert_formula(testEnv, msat_make_equal(testEnv, var, const0)); + msat_assert_formula(testEnv, msat_make_equal(testEnv, var, const1)); // UNSAT - assertThat(msat_check_sat(env)).isFalse(); + assertThat(msat_check_sat(testEnv)).isFalse(); - long proofMgr = msat_get_proof_manager(env); + long proofMgr = msat_get_proof_manager(testEnv); long proof = msat_get_proof(proofMgr); assertThat(msat_proof_is_term(proof)).isFalse(); From 15f4bc70b7ac78129a6a8b3a9e72102c07d4cf95 Mon Sep 17 00:00:00 2001 From: gcarpio21 Date: Thu, 10 Apr 2025 18:17:34 +0200 Subject: [PATCH 072/132] Delete src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java The tests for the API are in the `CVC5NativeAPITest` class other relevant tests will be in the `org.sosy_lab.java_smt.test` package --- .../java_smt/solvers/cvc5/CVC5ProofsTest.java | 213 ------------------ 1 file changed, 213 deletions(-) delete mode 100644 src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java deleted file mode 100644 index 53c1288c6f..0000000000 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofsTest.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * This file is part of JavaSMT, - * an API wrapper for a collection of SMT solvers: - * https://github.com/sosy-lab/java-smt - * - * SPDX-FileCopyrightText: 2024 Dirk Beyer - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.sosy_lab.java_smt.solvers.cvc5; - -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertTrue; - -import io.github.cvc5.CVC5ApiException; -import io.github.cvc5.Kind; -import io.github.cvc5.Proof; -import io.github.cvc5.Solver; -import io.github.cvc5.Sort; -import io.github.cvc5.Term; -import io.github.cvc5.TermManager; -import org.junit.After; -import org.junit.AssumptionViolatedException; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.sosy_lab.common.NativeLibraries; -import org.sosy_lab.common.ShutdownManager; -import org.sosy_lab.common.configuration.Configuration; -import org.sosy_lab.common.log.BasicLogManager; -import org.sosy_lab.common.log.LogManager; -import org.sosy_lab.java_smt.api.BooleanFormula; -import org.sosy_lab.java_smt.api.FloatingPointRoundingMode; -import org.sosy_lab.java_smt.api.ProverEnvironment; -import org.sosy_lab.java_smt.api.SolverContext; -import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; -import org.sosy_lab.java_smt.api.SolverException; -import org.sosy_lab.java_smt.api.proofs.ProofNode; -import org.sosy_lab.java_smt.basicimpl.AbstractNumeralFormulaManager.NonLinearArithmetic; - -@SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) -public class CVC5ProofsTest { - - @BeforeClass - public static void loadCVC5() { - try { - CVC5SolverContext.loadLibrary(NativeLibraries::loadLibrary); - } catch (UnsatisfiedLinkError e) { - throw new AssumptionViolatedException("CVC5 is not available", e); - } - } - - private static TermManager tm; - private static Sort booleanSort; - private Solver solver; - private SolverContext context; - private CVC5FormulaManager mgr; - private CVC5BooleanFormulaManager bmgr; - - @Before - public void init() throws CVC5ApiException { - tm = new TermManager(); - booleanSort = tm.getBooleanSort(); - solver = createEnvironment(); - } - - @Before - public void setUpSolver() throws Exception { - Configuration config = Configuration.defaultConfiguration(); - LogManager logger = BasicLogManager.create(config); - ShutdownManager shutdown = ShutdownManager.create(); - - context = - CVC5SolverContext.create( - logger, - config, - shutdown.getNotifier(), - 42, // random seed value - NonLinearArithmetic.USE, - FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN, - NativeLibraries::loadLibrary); - mgr = (CVC5FormulaManager) context.getFormulaManager(); - bmgr = (CVC5BooleanFormulaManager) mgr.getBooleanFormulaManager(); - } - - @After - public void freeEnvironment() { - solver.deletePointer(); - tm.deletePointer(); - } - - private static Solver createEnvironment() throws CVC5ApiException { - - Solver newSolver = new Solver(tm); - newSolver.setLogic("ALL"); - - // options - newSolver.setOption("incremental", "true"); - newSolver.setOption("produce-models", "true"); - newSolver.setOption("finite-model-find", "true"); - // newSolver.setOption("sets-ext", "true"); - newSolver.setOption("output-language", "smtlib2"); - newSolver.setOption("strings-exp", "true"); - newSolver.setOption("produce-proofs", "true"); - - return newSolver; - } - - @Test - public void getProofTest() { - // (declare-fun q1 () Bool) - // (declare-fun q2 () Bool) - // (assert (or (not q1) q2)) - // (assert q1) - // (assert (not q2)) - // (check-sat) - // (get-proof) - // This problem is from the paper found in - // https://ultimate.informatik.uni-freiburg.de/smtinterpol/proofs.html - - BooleanFormula q1 = bmgr.makeVariable("q1"); - BooleanFormula q2 = bmgr.makeVariable("q2"); - - ProverEnvironment prover = context.newProverEnvironment(ProverOptions.GENERATE_PROOFS); - try { - prover.addConstraint(bmgr.or(bmgr.not(q1), q2)); - prover.addConstraint(q1); - prover.addConstraint(bmgr.not(q2)); - assertTrue(prover.isUnsat()); - - ProofNode proof = prover.getProof(); - assertThat(proof).isNotNull(); - } catch (SolverException | InterruptedException pE) { - throw new RuntimeException(pE); - } - } - - private void processProof(Proof proof, int depth, int childNumber) throws CVC5ApiException { - String indent = " ".repeat(depth); // Indentation for readability - - System.out.println(indent + "Proof " + childNumber + ":"); - System.out.println(indent + " Result: " + proof.getResult()); - System.out.println(indent + " Rule: " + proof.getRule()); - System.out.println(indent + " Num args: " + proof.getArguments().length); - - // Display arguments - for (int j = 0; j < proof.getArguments().length; j++) { - System.out.println(indent + " Arg " + j + ": " + proof.getArguments()[j]); - } - - Proof[] proofChildren = proof.getChildren(); - System.out.println(indent + " Proof children length: " + proofChildren.length); - - for (int i = 0; i < proofChildren.length; i++) { - System.out.println(indent + " Child " + (i + 1) + " of Proof " + childNumber + ":"); - processProof(proofChildren[i], depth + 1, i + 1); - } - } - - @Test - public void proofTest() throws CVC5ApiException { - // (declare-fun q1 () Bool) - // (declare-fun q2 () Bool) - // (assert (or (not q1) q2)) - // (assert q1) - // (assert (not q2)) - Sort booleanSort = tm.getBooleanSort(); - Term q1 = solver.declareFun("q1", new Sort[] {}, booleanSort); - Term q2 = solver.declareFun("q2", new Sort[] {}, booleanSort); - - solver.assertFormula(tm.mkTerm(Kind.OR, tm.mkTerm(Kind.NOT, q1), q2)); - solver.assertFormula(q1); - solver.assertFormula(tm.mkTerm(Kind.NOT, q2)); - - assertThat(solver.checkSat().isUnsat()).isTrue(); - - Proof[] proof = solver.getProof(); - - System.out.println("Proof length: " + proof.length); - - // Process each proof in the array - for (int i = 0; i < proof.length; i++) { - processProof(proof[i], 0, i + 1); - } - } - - @Test - public void cvc5ProofToStringTest() { - // (declare-fun q1 () Bool) - // (declare-fun q2 () Bool) - // (assert (or (not q1) q2)) - // (assert q1) - // (assert (not q2)) - Sort booleanSort = tm.getBooleanSort(); - Term q1 = solver.declareFun("q1", new Sort[] {}, booleanSort); - Term q2 = solver.declareFun("q2", new Sort[] {}, booleanSort); - - solver.assertFormula(tm.mkTerm(Kind.OR, tm.mkTerm(Kind.NOT, q1), q2)); - solver.assertFormula(q1); - solver.assertFormula(tm.mkTerm(Kind.NOT, q2)); - - assertThat(solver.checkSat().isUnsat()).isTrue(); - - Proof[] proof = solver.getProof(); - - System.out.println("Proof length: " + proof.length); - - for (Proof p : proof) { - System.out.println(solver.proofToString(p)); - } - } -} From 9166aee4b69f00a39fb079187ba38564f22e3aeb Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Thu, 10 Apr 2025 21:28:17 +0200 Subject: [PATCH 073/132] MathSAT5: the resolution chain for the proofs is now executed iteratively --- .../mathsat5/Mathsat5TheoremProver.java | 84 ++++++++++++------- 1 file changed, 53 insertions(+), 31 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java index 29b9efcb8b..435329935f 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java @@ -16,9 +16,11 @@ import com.google.common.base.Preconditions; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.Stack; import org.checkerframework.checker.nullness.qual.Nullable; import org.sosy_lab.common.ShutdownNotifier; import org.sosy_lab.java_smt.api.BooleanFormula; @@ -69,57 +71,81 @@ public ProofNode getProof() throws SolverException, InterruptedException { long proof = msat_get_proof(pm); pn = Mathsat5ProofNode.fromMsatProof(this, proof); context.getFormulaManager().getBooleanFormulaManager(); - ProofNode result = pn; - result = clausifyResChain(pn, context.getFormulaManager().getBooleanFormulaManager()); + clausifyResChain(pn, context.getFormulaManager().getBooleanFormulaManager()); msat_destroy_proof_manager(pm); - return result; + return pn; // return getProof0(); } - // recursively update all RES_CHAIN nodes in the proof DAG by computing resolution + // update all RES_CHAIN nodes in the proof DAG by computing resolution // formulas and return the updated root node with formulas attached. - private ProofNode clausifyResChain(ProofNode root, BooleanFormulaManager bfmgr) { - return processResChain(root, bfmgr); // Start traversal and resolution from root node + private void clausifyResChain(ProofNode root, BooleanFormulaManager bfmgr) { + Map visited = new HashMap<>(); // Track visited nodes + Stack stack = new Stack<>(); + Stack processStack = + new Stack<>(); // Stack to hold nodes for post-processing after children + + stack.push(root); // Start with the root node + visited.put(root, Boolean.FALSE); // Mark root as unvisited + + while (!stack.isEmpty()) { + ProofNode node = stack.peek(); // Look at the top node, but don't pop yet + + if (visited.get(node) == Boolean.FALSE) { + // First time visiting this node + visited.put(node, Boolean.TRUE); // Mark node as visited + + // Push all children onto stack + List children = node.getChildren(); + for (int i = children.size() - 1; i >= 0; i--) { + ProofNode child = children.get(i); + if (!visited.containsKey(child)) { + stack.push(child); // Only push unvisited children + visited.put(child, Boolean.FALSE); // Mark child as unvisited + } + } + } else { + // All children have been visited, now process the node + stack.pop(); // Pop the current node as we are done processing its children + + // Check if this node is a RES_CHAIN, process if true + if (node.getRule().equals(Rule.RES_CHAIN)) { + processResChain(node, bfmgr); // Process RES_CHAIN node + } + } + } } - // Recursively process proof nodes and compute formulas for res-chain nodes - private ProofNode processResChain(ProofNode node, BooleanFormulaManager bfmgr) { + // process proof nodes and compute formulas for res-chain nodes + private void processResChain(ProofNode node, BooleanFormulaManager bfmgr) { List children = node.getChildren(); - List newChildren = new ArrayList<>(); - - // First process all children recursively so their formulas are computed - for (ProofNode child : children) { - newChildren.add(processResChain(child, bfmgr)); - } // If the current node is a RES_CHAIN, compute the resolved formula if (node.getRule().equals(Rule.RES_CHAIN)) { // Sanity check: res-chain nodes must have an odd number of children (clause, pivot, clause, // ..., clause) - if (newChildren.size() < 3 || newChildren.size() % 2 == 0) { + if (children.size() < 3 || children.size() % 2 == 0) { throw new IllegalArgumentException("Invalid res-chain structure: must be odd and >= 3"); } // Begin resolution chain: start with the first clause - BooleanFormula current = (BooleanFormula) newChildren.get(0).getFormula(); + BooleanFormula current = (BooleanFormula) children.get(0).getFormula(); // Apply resolution iteratively using pivot, clause pairs - for (int i = 1; i < newChildren.size() - 1; i += 2) { - BooleanFormula pivot = (BooleanFormula) newChildren.get(i).getFormula(); - BooleanFormula nextClause = (BooleanFormula) newChildren.get(i + 1).getFormula(); + for (int i = 1; i < children.size() - 1; i += 2) { + BooleanFormula pivot = (BooleanFormula) children.get(i).getFormula(); + BooleanFormula nextClause = (BooleanFormula) children.get(i + 1).getFormula(); current = resolve(current, nextClause, pivot, bfmgr); // Perform resolution step } // Store the resolved formula in the current node ((Mathsat5ProofNode) node).setFormula(current); } - - return node; } - // Perform resolution between two disjunctive clauses using a given pivot + // Perform resolution between two clauses using a given pivot private BooleanFormula resolve( BooleanFormula clause1, BooleanFormula clause2, @@ -132,9 +158,7 @@ private BooleanFormula resolve( boolean removed = false; for (BooleanFormula lit : literals1) { - if (isComplement(lit, pivot, bfmgr)) { - removed = true; - } else { + if (!isComplement(lit, pivot, bfmgr)) { combined.add(lit); } } @@ -142,9 +166,7 @@ private BooleanFormula resolve( List temp = new ArrayList<>(); boolean removed2 = false; for (BooleanFormula lit : literals2) { - if (isComplement(lit, pivot, bfmgr)) { - removed2 = true; - } else { + if (!isComplement(lit, pivot, bfmgr)) { temp.add(lit); } } @@ -160,7 +182,7 @@ private BooleanFormula resolve( } } - // Helper method to flatten an OR-formula into a list of disjunctive literals + // Helper method to flatten an OR/AND-formula into a list of disjunctive literals private List flattenLiterals( BooleanFormula formula, BooleanFormulaManager bfmgr) { List result = new ArrayList<>(); @@ -186,14 +208,14 @@ public TraversalProcess visitAnd(List operands) { @Override public TraversalProcess visitNot(BooleanFormula operand) { - result.add(formula); // ✅ add original NOT node + result.add(formula); // add original NOT node return TraversalProcess.SKIP; } @Override public TraversalProcess visitAtom( BooleanFormula atom, FunctionDeclaration decl) { - result.add(formula); // ✅ add original atom + result.add(formula); // add original atom return TraversalProcess.SKIP; } From 6c0fc0ab6f33ad5dba8a70c3ef46232efeccaef7 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 11 Apr 2025 13:40:47 +0200 Subject: [PATCH 074/132] Z3: The state of the solver is checked as well as whether the assertions evaluate to unsat --- src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java index a3fa8a0432..a7d8ad6ffd 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java @@ -148,7 +148,9 @@ protected long getZ3Model() { } @Override - public ProofNode getProof() { + public ProofNode getProof() throws SolverException, InterruptedException { + Preconditions.checkState(!closed); + Preconditions.checkState(this.isUnsat()); long proofAst = Native.solverGetProof(z3context, z3solver); return new Z3NonRecursiveProofProcessor(z3context, z3solver, creator, this) .fromASTIterative(proofAst); From f81fbe83c6b77c175cda832824a1d5bc84ee6969 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 21 Apr 2025 14:18:34 +0200 Subject: [PATCH 075/132] Renamed for clarity --- ...nProofDag.java => ResolutionProofDAG.java} | 4 +- .../proofs/{ProofDag.java => ProofDAG.java} | 2 +- ...actProofDag.java => AbstractProofDAG.java} | 4 +- .../java_smt/solvers/z3/Z3ProofDAG.java | 150 ++++++++++++++++++ .../java_smt/solvers/z3/Z3ProofDag.java | 48 ------ ...java => Z3ToResolutionProofConverter.java} | 116 +++++++------- 6 files changed, 213 insertions(+), 111 deletions(-) rename src/org/sosy_lab/java_smt/{ResolutionProofDag.java => ResolutionProofDAG.java} (93%) rename src/org/sosy_lab/java_smt/api/proofs/{ProofDag.java => ProofDAG.java} (97%) rename src/org/sosy_lab/java_smt/basicimpl/{AbstractProofDag.java => AbstractProofDAG.java} (95%) create mode 100644 src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDAG.java delete mode 100644 src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDag.java rename src/org/sosy_lab/java_smt/solvers/z3/{Z3ToResoluteProofConverter.java => Z3ToResolutionProofConverter.java} (79%) diff --git a/src/org/sosy_lab/java_smt/ResolutionProofDag.java b/src/org/sosy_lab/java_smt/ResolutionProofDAG.java similarity index 93% rename from src/org/sosy_lab/java_smt/ResolutionProofDag.java rename to src/org/sosy_lab/java_smt/ResolutionProofDAG.java index b11597a794..f62da7a4fb 100644 --- a/src/org/sosy_lab/java_smt/ResolutionProofDag.java +++ b/src/org/sosy_lab/java_smt/ResolutionProofDAG.java @@ -15,7 +15,7 @@ import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.api.proofs.ProofRule; -import org.sosy_lab.java_smt.basicimpl.AbstractProofDag; +import org.sosy_lab.java_smt.basicimpl.AbstractProofDAG; /** * This class represents a resolution proof DAG. Its nodes might be of the type {@link @@ -25,7 +25,7 @@ * @see ResProofRule */ @SuppressWarnings("all") -public class ResolutionProofDag extends AbstractProofDag { +public class ResolutionProofDAG extends AbstractProofDAG { // Work in progress. The functionality of producing just nodes should be provided first. // The idea is to provide extended functionality (by providng a set of edges for example). diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofDag.java b/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java similarity index 97% rename from src/org/sosy_lab/java_smt/api/proofs/ProofDag.java rename to src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java index c38ecd81a2..76fd4df922 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofDag.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java @@ -17,7 +17,7 @@ * A DAG representing a proof. Each node in the DAG is a {@link ProofNode} and each edge is a * directed edge from a parent node to a child node. */ -public interface ProofDag { +public interface ProofDAG { /** * Add a node to the DAG. diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java similarity index 95% rename from src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java rename to src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java index 730e022440..680bce9a36 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDag.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java @@ -18,7 +18,7 @@ import java.util.Map; import org.sosy_lab.common.UniqueIdGenerator; import org.sosy_lab.java_smt.api.Formula; -import org.sosy_lab.java_smt.api.proofs.ProofDag; +import org.sosy_lab.java_smt.api.proofs.ProofDAG; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.api.proofs.visitors.ProofVisitor; @@ -28,7 +28,7 @@ * * @author Gabriel Carpio */ -public abstract class AbstractProofDag implements ProofDag { +public abstract class AbstractProofDAG implements ProofDAG { private final Map nodes = new HashMap<>(); private int nodeIdCounter = 0; diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDAG.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDAG.java new file mode 100644 index 0000000000..c21c7fcdb0 --- /dev/null +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDAG.java @@ -0,0 +1,150 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.solvers.z3; + +import com.microsoft.z3.Native; +import com.microsoft.z3.enumerations.Z3_decl_kind; +import com.microsoft.z3.enumerations.Z3_sort_kind; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.proofs.ProofFrame; +import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.ProofRule; +import org.sosy_lab.java_smt.basicimpl.AbstractProofDAG; +import org.sosy_lab.java_smt.basicimpl.FormulaCreator; + +public class Z3ProofDAG extends AbstractProofDAG { + protected static class Frame extends ProofFrame { + protected Frame(Long proof) { + super(proof); + } + } + + public static class Z3ProofNode extends AbstractProofNode { + + Z3ProofNode(Formula pFormula, ProofRule pProofRule) { + super(pProofRule, pFormula); + } + + /** + * This transformation omits one level of the proofs from Z3, as the leaves in that case are the + * operands of the boolean formulas used as the very first proof steps in the whole proof .E.g., + * when asserting (or (not q2) q1) that produces a single {@link Z3ProofNode}, but the input for + * that is a whole subtree from Z3 composed of the asseertion, the OR operation and the + * operands. + * + * @param rootProof + * @param formulaCreator + * @return + */ + static Z3ProofNode fromZ3Proof(long rootProof, FormulaCreator formulaCreator) { + long z3context = (long) formulaCreator.getEnv(); + // proof ast to be processed wrapped inside a frame + Deque stack = new ArrayDeque<>(); + + // proof ast has been converted into ProofNode + Map computed = new HashMap<>(); + + stack.push(new Frame(rootProof)); + + while (!stack.isEmpty()) { + Frame frame = stack.peek(); + + // prevent processing the same proof ast multiple times + if (!frame.isVisited()) { + + Native.incRef(z3context, frame.getProof()); + + // The number of children of the proof node + frame.setNumArgs(Native.getAppNumArgs(z3context, frame.getProof())); + frame.setAsVisited(true); + + for (int i = frame.getNumArgs() - 2; i >= 0; i--) { + long arg = Native.getAppArg(z3context, frame.getProof(), i); + + if (!computed.containsKey(arg)) { + stack.push(new Frame(arg)); + } + } + } else { + + stack.pop(); + int numArgs = frame.getNumArgs(); + Formula formula; + + // needed for the sortKind + long sort = Native.getSort(z3context, frame.getProof()); + long sortKind = Native.getSortKind(z3context, sort); + Z3_sort_kind sk = Z3_sort_kind.fromInt((int) sortKind); + if (sk != Z3_sort_kind.Z3_UNKNOWN_SORT) { + // This should be a proof sort, this is not included in the enum class provided by the + // API + formula = + formulaCreator.encapsulate( + formulaCreator.getFormulaType(frame.getProof()), frame.getProof()); + } else { + // Return the i-th argument of the given application. The formula resulting from + // applying the proof rule is the last argument of the proof node. + long z3expr = Native.getAppArg(z3context, frame.getProof(), numArgs - 1); + formula = formulaCreator.encapsulate(formulaCreator.getFormulaType(z3expr), z3expr); + } + int declKind = + Native.getDeclKind(z3context, Native.getAppDecl(z3context, frame.getProof())); + ProofRule proofRule = getPRfromDK(declKind); + Z3ProofDAG.Z3ProofNode node = new Z3ProofDAG.Z3ProofNode(formula, proofRule); + + for (int i = 0; i < numArgs - 1; i++) { + long arg = Native.getAppArg(z3context, frame.getProof(), i); + if (computed.containsKey(arg)) { + node.addChild(computed.get(arg)); + } + } + computed.put(frame.getProof(), node); + Native.decRef(z3context, frame.getProof()); + } + } + return computed.get(rootProof); + } + + private static ProofRule getPRfromDK(int declKind) { + String rawName = Z3_decl_kind.fromInt(declKind).name(); + String prName = rawName.replaceFirst("Z3_OP_PR_", ""); + // return ProofRule.fromName(Z3ProofRule.class, prName); + return Enum.valueOf(Z3ProofRule.class, prName); + } + + String asString() { + return asString(0); + } + + private String asString(int indentLevel) { + StringBuilder proof = new StringBuilder(); + String indent = " ".repeat(indentLevel); + + proof.append(indent).append("Formula: ").append(getFormula().toString()).append("\n"); + proof.append(indent).append("Rule: ").append(getRule().getName()).append("\n"); + proof.append(indent).append("No. Children: ").append(getChildren().size()).append("\n"); + proof.append(indent).append("ID: ").append(getId()).append("\n"); + proof.append(indent).append("leaf: ").append(isLeaf()).append("\n"); + + int i = 0; + for (ProofNode child : getChildren()) { + proof.append(indent).append("Child ").append(++i).append(":\n"); + proof.append(((Z3ProofNode) child).asString(indentLevel + 1)); + } + + return proof.toString(); + } + } +} diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDag.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDag.java deleted file mode 100644 index 635f44b2ff..0000000000 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDag.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * This file is part of JavaSMT, - * an API wrapper for a collection of SMT solvers: - * https://github.com/sosy-lab/java-smt - * - * SPDX-FileCopyrightText: 2024 Dirk Beyer - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.sosy_lab.java_smt.solvers.z3; - -import org.sosy_lab.java_smt.api.Formula; -import org.sosy_lab.java_smt.api.proofs.ProofNode; -import org.sosy_lab.java_smt.api.proofs.ProofRule; -import org.sosy_lab.java_smt.basicimpl.AbstractProofDag; - -public class Z3ProofDag extends AbstractProofDag { - public static class Z3ProofNode extends AbstractProofNode { - - Z3ProofNode(Formula pFormula, ProofRule pProofRule) { - super(pProofRule, pFormula); - } - - String asString() { - return asString(0); - } - - private String asString(int indentLevel) { - StringBuilder proof = new StringBuilder(); - String indent = " ".repeat(indentLevel); - - proof.append(indent).append("Formula: ").append(getFormula().toString()).append("\n"); - proof.append(indent).append("Rule: ").append(getRule().getName()).append("\n"); - proof.append(indent).append("No. Children: ").append(getChildren().size()).append("\n"); - proof.append(indent).append("ID: ").append(getId()).append("\n"); - proof.append(indent).append("leaf: ").append(isLeaf()).append("\n"); - - int i = 0; - for (ProofNode child : getChildren()) { - proof.append(indent).append("Child ").append(++i).append(":\n"); - proof.append(((Z3ProofNode) child).asString(indentLevel + 1)); - } - - return proof.toString(); - } - } -} diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java similarity index 79% rename from src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java rename to src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java index 5d89a743cd..bf763c85a7 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResoluteProofConverter.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java @@ -18,9 +18,9 @@ import java.util.List; import java.util.Map; import org.sosy_lab.java_smt.ResProofRule.ResAxiom; -import org.sosy_lab.java_smt.ResolutionProofDag; -import org.sosy_lab.java_smt.ResolutionProofDag.AxiomProofNode; -import org.sosy_lab.java_smt.ResolutionProofDag.ResolutionProofNode; +import org.sosy_lab.java_smt.ResolutionProofDAG; +import org.sosy_lab.java_smt.ResolutionProofDAG.AxiomProofNode; +import org.sosy_lab.java_smt.ResolutionProofDAG.ResolutionProofNode; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.BooleanFormulaManager; import org.sosy_lab.java_smt.api.Formula; @@ -46,13 +46,13 @@ * @see org.sosy_lab.java_smt.ResProofRule for the list of RESOLUTE axioms. */ @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access", "ModifiedButNotUsed"}) -public class Z3ToResoluteProofConverter { // This class is inclompete and currently not used. The +public class Z3ToResolutionProofConverter { // This class is inclompete and currently not used. The // strategy for transforming proof rules should be proved first. private final Z3FormulaManager formulaManager; private final BooleanFormulaManager bfm; - Z3ToResoluteProofConverter(Z3FormulaManager creator) { + Z3ToResolutionProofConverter(Z3FormulaManager creator) { formulaManager = creator; bfm = formulaManager.getBooleanFormulaManager(); } @@ -60,15 +60,15 @@ public class Z3ToResoluteProofConverter { // This class is inclompete and curren private static final Map ruleMapping = new HashMap<>(); /** - * This method converts a set of Z3ProofNodes into a {@link ResolutionProofDag}. + * This method converts a set of Z3ProofNodes into a {@link ResolutionProofDAG}. * * @param z3ProofNodes - * @return {@link ResolutionProofDag} + * @return {@link ResolutionProofDAG} */ - static ResolutionProofDag convertToResolutionProofDag(Z3ProofDag.Z3ProofNode[] z3ProofNodes) { - ResolutionProofDag dag = new ResolutionProofDag(); + static ResolutionProofDAG convertToResolutionProofDag(Z3ProofDAG.Z3ProofNode[] z3ProofNodes) { + ResolutionProofDAG dag = new ResolutionProofDAG(); - for (Z3ProofDag.Z3ProofNode z3Node : z3ProofNodes) { + for (Z3ProofDAG.Z3ProofNode z3Node : z3ProofNodes) { if (z3Node.getRule() == MODUS_PONENS) { } else { @@ -161,13 +161,13 @@ public List extractEquivalenceOperands(BooleanFormula formula) { } /** - * Converts a {@link Z3ProofDag.Z3ProofNode} into either a {@link ResolutionProofNode} or a {@link + * Converts a {@link Z3ProofDAG.Z3ProofNode} into either a {@link ResolutionProofNode} or a {@link * AxiomProofNode}, depending on its rule. * - * @param node the {@link Z3ProofDag.Z3ProofNode} to convert + * @param node the {@link Z3ProofDAG.Z3ProofNode} to convert * @return the resulting {@link ProofNode} */ - ProofNode handleNode(Z3ProofDag.Z3ProofNode node) { + ProofNode handleNode(Z3ProofDAG.Z3ProofNode node) { Z3ProofRule rule = (Z3ProofRule) node.getRule(); switch (rule) { @@ -302,34 +302,34 @@ ProofNode handleNode(Z3ProofDag.Z3ProofNode node) { } } - ProofNode handleTrue(Z3ProofDag.Z3ProofNode node) { + ProofNode handleTrue(Z3ProofDAG.Z3ProofNode node) { BooleanFormula formula = (BooleanFormula) node.getFormula(); AxiomProofNode pn = new AxiomProofNode(ResAxiom.TRUE_POSITIVE, formula); return pn; } - ProofNode handleAsserted(Z3ProofDag.Z3ProofNode node) { + ProofNode handleAsserted(Z3ProofDAG.Z3ProofNode node) { BooleanFormula formula = (BooleanFormula) node.getFormula(); AxiomProofNode pn = new AxiomProofNode(ResAxiom.ASSUME, formula); return pn; } - ProofNode handleModusPonens(Z3ProofDag.Z3ProofNode node) { + ProofNode handleModusPonens(Z3ProofDAG.Z3ProofNode node) { BooleanFormula formula = (BooleanFormula) node.getFormula(); BooleanFormula pivot = (BooleanFormula) node.getChildren().get(0).getFormula(); ResolutionProofNode pn = new ResolutionProofNode(formula, pivot); - ProofNode c1 = handleNode((Z3ProofDag.Z3ProofNode) node.getChildren().get(0)); - ProofNode c2 = handleNode((Z3ProofDag.Z3ProofNode) node.getChildren().get(1)); + ProofNode c1 = handleNode((Z3ProofDAG.Z3ProofNode) node.getChildren().get(0)); + ProofNode c2 = handleNode((Z3ProofDAG.Z3ProofNode) node.getChildren().get(1)); return pn; } - ProofNode handleReflexivity(Z3ProofDag.Z3ProofNode node) { + ProofNode handleReflexivity(Z3ProofDAG.Z3ProofNode node) { BooleanFormula formula = (BooleanFormula) node.getFormula(); AxiomProofNode pn = new AxiomProofNode(ResAxiom.REFLEXIVITY, formula); return pn; } - ProofNode handleSymmetry(Z3ProofDag.Z3ProofNode node) { + ProofNode handleSymmetry(Z3ProofDAG.Z3ProofNode node) { BooleanFormula formula = (BooleanFormula) node.getFormula(); BooleanFormula pivot = (BooleanFormula) node.getChildren().get(0).getFormula(); BooleanFormula snFormula = bfm.or(bfm.not(pivot), formula); @@ -337,11 +337,11 @@ ProofNode handleSymmetry(Z3ProofDag.Z3ProofNode node) { ResolutionProofNode pn = new ResolutionProofNode(formula, pivot); AxiomProofNode sn = new AxiomProofNode(ResAxiom.SYMMETRY, snFormula); pn.addChild(sn); - pn.addChild(handleNode((Z3ProofDag.Z3ProofNode) node.getChildren().get(0))); + pn.addChild(handleNode((Z3ProofDAG.Z3ProofNode) node.getChildren().get(0))); return pn; } - ProofNode handleTransitivity(Z3ProofDag.Z3ProofNode node) { + ProofNode handleTransitivity(Z3ProofDAG.Z3ProofNode node) { BooleanFormula t1 = (BooleanFormula) node.getChildren().get(0).getFormula(); BooleanFormula t2 = (BooleanFormula) node.getChildren().get(1).getFormula(); @@ -371,7 +371,7 @@ ProofNode handleTransitivity(Z3ProofDag.Z3ProofNode node) { return transResNode; } - ProofNode handleTransitivityStar(Z3ProofDag.Z3ProofNode node) { + ProofNode handleTransitivityStar(Z3ProofDAG.Z3ProofNode node) { BooleanFormula resPivot = null; Collection formulas = new ArrayList<>(); List> formulaList = new ArrayList<>(); @@ -400,143 +400,143 @@ ProofNode handleTransitivityStar(Z3ProofDag.Z3ProofNode node) { return resNode; } - ProofNode handleMonotonicity(Z3ProofDag.Z3ProofNode node) { + ProofNode handleMonotonicity(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleQuantIntro(Z3ProofDag.Z3ProofNode node) { + ProofNode handleQuantIntro(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleBind(Z3ProofDag.Z3ProofNode node) { + ProofNode handleBind(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleDistributivity(Z3ProofDag.Z3ProofNode node) { + ProofNode handleDistributivity(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleAndElim(Z3ProofDag.Z3ProofNode node) { + ProofNode handleAndElim(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleNotOrElim(Z3ProofDag.Z3ProofNode node) { + ProofNode handleNotOrElim(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleRewrite(Z3ProofDag.Z3ProofNode node) { + ProofNode handleRewrite(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleRewriteStar(Z3ProofDag.Z3ProofNode node) { + ProofNode handleRewriteStar(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handlePullQuant(Z3ProofDag.Z3ProofNode node) { + ProofNode handlePullQuant(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleElimUnusedVars(Z3ProofDag.Z3ProofNode node) { + ProofNode handleElimUnusedVars(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handlePushQuant(Z3ProofDag.Z3ProofNode node) { + ProofNode handlePushQuant(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleDer(Z3ProofDag.Z3ProofNode node) { + ProofNode handleDer(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleQuantInst(Z3ProofDag.Z3ProofNode node) { + ProofNode handleQuantInst(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleHypothesis(Z3ProofDag.Z3ProofNode node) { + ProofNode handleHypothesis(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleLemma(Z3ProofDag.Z3ProofNode node) { + ProofNode handleLemma(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleUnitResolution(Z3ProofDag.Z3ProofNode node) { + ProofNode handleUnitResolution(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleIffTrue(Z3ProofDag.Z3ProofNode node) { + ProofNode handleIffTrue(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleIffFalse(Z3ProofDag.Z3ProofNode node) { + ProofNode handleIffFalse(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleCommutativity(Z3ProofDag.Z3ProofNode node) { + ProofNode handleCommutativity(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleDefAxiom(Z3ProofDag.Z3ProofNode node) { + ProofNode handleDefAxiom(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleAssumptionAdd(Z3ProofDag.Z3ProofNode node) { + ProofNode handleAssumptionAdd(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleLemmaAdd(Z3ProofDag.Z3ProofNode node) { + ProofNode handleLemmaAdd(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleRedundantDel(Z3ProofDag.Z3ProofNode node) { + ProofNode handleRedundantDel(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleClauseTrail(Z3ProofDag.Z3ProofNode node) { + ProofNode handleClauseTrail(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleDefIntro(Z3ProofDag.Z3ProofNode node) { + ProofNode handleDefIntro(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleApplyDef(Z3ProofDag.Z3ProofNode node) { + ProofNode handleApplyDef(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleIffOeq(Z3ProofDag.Z3ProofNode node) { + ProofNode handleIffOeq(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleNnfPos(Z3ProofDag.Z3ProofNode node) { + ProofNode handleNnfPos(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleNnfNeg(Z3ProofDag.Z3ProofNode node) { + ProofNode handleNnfNeg(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleSkolemize(Z3ProofDag.Z3ProofNode node) { + ProofNode handleSkolemize(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleModusPonensOeq(Z3ProofDag.Z3ProofNode node) { + ProofNode handleModusPonensOeq(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleThLemma(Z3ProofDag.Z3ProofNode node) { + ProofNode handleThLemma(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleHyperResolve(Z3ProofDag.Z3ProofNode node) { + ProofNode handleHyperResolve(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleOperation(Z3ProofDag.Z3ProofNode node) { + ProofNode handleOperation(Z3ProofDAG.Z3ProofNode node) { return null; } - ProofNode handleDefault(Z3ProofDag.Z3ProofNode node) { + ProofNode handleDefault(Z3ProofDAG.Z3ProofNode node) { return null; } From f9fd81ea949c6f83801299a7742360059cbd50f3 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 21 Apr 2025 14:20:23 +0200 Subject: [PATCH 076/132] Documentation and rename --- .../api/proofs/visitors/ProofTraversalVisitor.java | 4 ++-- .../java_smt/api/proofs/visitors/ProofVisitor.java | 4 ++-- src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java | 4 ++-- .../java_smt/solvers/cvc5/CVC5NativeAPITest.java | 2 +- .../sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java | 2 +- .../java_smt/solvers/mathsat5/Mathsat5ProofNode.java | 2 +- .../java_smt/solvers/mathsat5/Mathsat5ProofRule.java | 5 +++++ .../java_smt/solvers/smtinterpol/ProofTermParser.java | 10 +++++----- .../solvers/smtinterpol/SmtInterpolAbstractProver.java | 4 ++-- 9 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java index dc9f2f54ed..ea4edb0f4b 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java +++ b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java @@ -12,7 +12,7 @@ import java.util.HashSet; import java.util.Set; -import org.sosy_lab.java_smt.api.proofs.ProofDag; +import org.sosy_lab.java_smt.api.proofs.ProofDAG; import org.sosy_lab.java_smt.api.proofs.ProofNode; public class ProofTraversalVisitor implements ProofVisitor { @@ -28,7 +28,7 @@ public void visitNode(ProofNode node) { } @Override - public void visitDAG(ProofDag dag) { + public void visitDAG(ProofDAG dag) { for (ProofNode node : dag.getNodes()) { if (!visited.contains(node)) { visitNode(node); diff --git a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofVisitor.java b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofVisitor.java index 562412bfd9..68dd15d6a8 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofVisitor.java +++ b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofVisitor.java @@ -10,11 +10,11 @@ package org.sosy_lab.java_smt.api.proofs.visitors; -import org.sosy_lab.java_smt.api.proofs.ProofDag; +import org.sosy_lab.java_smt.api.proofs.ProofDAG; import org.sosy_lab.java_smt.api.proofs.ProofNode; public interface ProofVisitor { void visitNode(ProofNode node); - void visitDAG(ProofDag dag); + void visitDAG(ProofDAG dag); } diff --git a/src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java b/src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java index 8dffd7c38e..be85cba931 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java +++ b/src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java @@ -11,8 +11,8 @@ package org.sosy_lab.java_smt.basicimpl; import org.sosy_lab.java_smt.ResProofRule.ResAxiom; -import org.sosy_lab.java_smt.ResolutionProofDag.AxiomProofNode; -import org.sosy_lab.java_smt.ResolutionProofDag.ResolutionProofNode; +import org.sosy_lab.java_smt.ResolutionProofDAG.AxiomProofNode; +import org.sosy_lab.java_smt.ResolutionProofDAG.ResolutionProofNode; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.proofs.ProofNode; diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5NativeAPITest.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5NativeAPITest.java index e15fdec270..535c12599f 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5NativeAPITest.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5NativeAPITest.java @@ -1416,7 +1416,7 @@ public void testProofMethods() throws CVC5ApiException { assertThat(proof.getChildren()[0]).isNotNull(); - // The way the proof DAG is structured, the root has one child, which has also one child and + // The way this proof DAG is structured, the root has one child, which has also one child and // the child of the latter has more than one child. Proof[] childOfSecondProof = proof.getChildren()[0].getChildren(); diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java index c3d0510406..94ffc81322 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java @@ -13,7 +13,7 @@ import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.api.proofs.ProofRule; -import org.sosy_lab.java_smt.basicimpl.AbstractProofDag.AbstractProofNode; +import org.sosy_lab.java_smt.basicimpl.AbstractProofDAG.AbstractProofNode; public class CVC5ProofNode extends AbstractProofNode { diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java index 5bb86ef121..14bbed29a4 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java @@ -28,7 +28,7 @@ import org.sosy_lab.java_smt.api.proofs.ProofFrame; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.api.proofs.ProofRule; -import org.sosy_lab.java_smt.basicimpl.AbstractProofDag.AbstractProofNode; +import org.sosy_lab.java_smt.basicimpl.AbstractProofDAG.AbstractProofNode; import org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5ProofRule.Rule; public class Mathsat5ProofNode extends AbstractProofNode { diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java index 742098f19d..1b42cd78ae 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java @@ -45,4 +45,9 @@ public String getName() { public String getName() { return name; } + + @Override + public String toString() { + return getName(); + } } diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java index 2f5877c2b1..71a45d23dd 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java @@ -9,8 +9,8 @@ import java.util.HashMap; import java.util.Map; import org.sosy_lab.java_smt.ResProofRule.ResAxiom; -import org.sosy_lab.java_smt.ResolutionProofDag; -import org.sosy_lab.java_smt.ResolutionProofDag.AxiomProofNode; +import org.sosy_lab.java_smt.ResolutionProofDAG; +import org.sosy_lab.java_smt.ResolutionProofDAG.AxiomProofNode; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.FormulaManager; import org.sosy_lab.java_smt.api.proofs.ProofNode; @@ -20,7 +20,7 @@ @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) public class ProofTermParser { - private final ResolutionProofDag proofDag; + private final ResolutionProofDAG proofDag; private final Map annotatedTerms; private final Map letBindings = new HashMap<>(); private final Map termToNode = new HashMap<>(); @@ -29,10 +29,10 @@ public class ProofTermParser { public ProofTermParser(Map pAnnotatedTerms, FormulaManager pMgr) { annotatedTerms = pAnnotatedTerms; mgr = pMgr; - proofDag = new ResolutionProofDag(); + proofDag = new ResolutionProofDAG(); } - public static ResolutionProofDag convert( + public static ResolutionProofDAG convert( Term proof, FormulaManager pManager, Map pAnnotatedTerms) { ProofTermParser parser = new ProofTermParser(pAnnotatedTerms, pManager); ProofNode rootNode = parser.parseProofTerm(proof); diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java index bafc1aab8e..18844df8ef 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java @@ -41,7 +41,7 @@ import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; -import org.sosy_lab.java_smt.api.proofs.ProofDag; +import org.sosy_lab.java_smt.api.proofs.ProofDAG; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.AbstractProver; import org.sosy_lab.java_smt.basicimpl.CachingModel; @@ -222,7 +222,7 @@ public ProofNode getProof() { checkGenerateProofs(); final Term proof; - final ProofDag proofDAG; + final ProofDAG proofDAG; try { proof = env.getProof(); // proofDAG = ResolutionProofDAG.fromTerm(proof, mgr, annotatedTerms.peek()); From f0e702cf7dda700eaae9c89dc11fb6af2eacc91d Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 21 Apr 2025 14:21:41 +0200 Subject: [PATCH 077/132] Z3: No more ProofProcessor class, proofs are now processed in the 'Z3ProofNode' class --- .../z3/Z3NonRecursiveProofProcessor.java | 138 ------------------ .../java_smt/solvers/z3/Z3ProofsTest.java | 8 +- .../java_smt/solvers/z3/Z3TheoremProver.java | 4 +- 3 files changed, 6 insertions(+), 144 deletions(-) delete mode 100644 src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java deleted file mode 100644 index 0ac613eec9..0000000000 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3NonRecursiveProofProcessor.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * This file is part of JavaSMT, - * an API wrapper for a collection of SMT solvers: - * https://github.com/sosy-lab/java-smt - * - * SPDX-FileCopyrightText: 2024 Dirk Beyer - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.sosy_lab.java_smt.solvers.z3; - -import com.microsoft.z3.Native; -import com.microsoft.z3.enumerations.Z3_decl_kind; -import com.microsoft.z3.enumerations.Z3_sort_kind; -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.HashMap; -import java.util.Map; -import org.sosy_lab.java_smt.api.Formula; -import org.sosy_lab.java_smt.api.proofs.ProofRule; - -/** - * This class is used to process the proof generated by Z3 and store it as a ProofNode. It is a - * non-(java-)recursive implementation of the proof processor.# - * - *

The resulting DAG from transforming the proof from the Z3 provided structures into a set of - * {@link Z3ProofDag.Z3ProofNode} should enable an easier way to extract the information from the - * proofs. However, some information is lost from the original proof, as the Z3 provided proof makes - * uses of more general structures like AST, SortKind, DeclKind. E.g. the leafs in the {@link - * Z3ProofDag.Z3ProofNode} contain the whole formula used for the first proof rules in the tree, - * while these are internal nodes in the Z3 proof and leafs are the operands use in innermost terms. - */ -@SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) -class Z3NonRecursiveProofProcessor { - private final long z3context; - private final long z3solver; - private final Z3FormulaCreator formulaCreator; - private final Z3AbstractProver prover; - - Z3NonRecursiveProofProcessor( - long ctx, long solver, Z3FormulaCreator creator, Z3AbstractProver pProver) { - z3context = ctx; - z3solver = solver; - formulaCreator = creator; - prover = pProver; - } - - Z3ProofDag.Z3ProofNode fromASTIterative(long rootProof) { - // proof ast to be processed wrapped inside a frame - Deque stack = new ArrayDeque<>(); - - // proof ast has been converted into ProofNode - Map computed = new HashMap<>(); - - stack.push(new Frame(rootProof)); - - while (!stack.isEmpty()) { - Frame frame = stack.peek(); - - // prevent processing the same proof ast multiple times - if (!frame.visited) { - - Native.incRef(z3context, frame.proof); - - // The number of children of the proof node - frame.numArgs = Native.getAppNumArgs(z3context, frame.proof); - frame.visited = true; - - for (int i = frame.numArgs - 2; i >= 0; i--) { - long arg = Native.getAppArg(z3context, frame.proof, i); - - if (!computed.containsKey(arg)) { - stack.push(new Frame(arg)); - } - } - } else { - - stack.pop(); - int numArgs = frame.numArgs; - Formula formula; - - // needed for the sortKind - long sort = Native.getSort(z3context, frame.proof); - long sortKind = Native.getSortKind(z3context, sort); - Z3_sort_kind sk = Z3_sort_kind.fromInt((int) sortKind); - if (sk != Z3_sort_kind.Z3_UNKNOWN_SORT) { - // This should be a proof sort, this is not included in the enum class provided by the API - formula = generateFormula(frame.proof); - } else { - // Return the i-th argument of the given application. The formula resulting from - // applying the proof rule is the last argument of the proof node. - long z3expr = Native.getAppArg(z3context, frame.proof, numArgs - 1); - formula = generateFormula(z3expr); - } - int declKind = Native.getDeclKind(z3context, Native.getAppDecl(z3context, frame.proof)); - ProofRule proofRule = getPRfromDK(declKind); - Z3ProofDag.Z3ProofNode node = new Z3ProofDag.Z3ProofNode(formula, proofRule); - - for (int i = 0; i < numArgs - 1; i++) { - long arg = Native.getAppArg(z3context, frame.proof, i); - if (computed.containsKey(arg)) { - node.addChild(computed.get(arg)); - } - } - computed.put(frame.proof, node); - Native.decRef(z3context, frame.proof); - } - } - return computed.get(rootProof); - } - - private ProofRule getPRfromDK(int declKind) { - String rawName = Z3_decl_kind.fromInt(declKind).name(); - String prName = rawName.replaceFirst("Z3_OP_PR_", ""); - // return ProofRule.fromName(Z3ProofRule.class, prName); - return Enum.valueOf(Z3ProofRule.class, prName); - } - - private Formula generateFormula(long proof) { - Formula formula = null; - if (formula == null) { - formula = formulaCreator.encapsulate(formulaCreator.getFormulaType(proof), proof); - } - return formula; - } - - private static class Frame { - final long proof; - int numArgs; - boolean visited; - - Frame(long proof) { - this.proof = proof; - this.visited = false; - } - } -} diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java index 2162bb98b2..cb6a447c8d 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java @@ -116,11 +116,11 @@ public void Z3handleTransitivityTest() { BooleanFormula equiv2 = bmgr.equivalence(f2, f3); BooleanFormula equiv3 = bmgr.equivalence(f1, f3); - Z3ProofDag.Z3ProofNode pn = new Z3ProofDag.Z3ProofNode(equiv3, Z3ProofRule.TRANSITIVITY); - pn.addChild(new Z3ProofDag.Z3ProofNode(equiv1, Z3ProofRule.ASSERTED)); - pn.addChild(new Z3ProofDag.Z3ProofNode(equiv2, Z3ProofRule.ASSERTED)); + Z3ProofDAG.Z3ProofNode pn = new Z3ProofDAG.Z3ProofNode(equiv3, Z3ProofRule.TRANSITIVITY); + pn.addChild(new Z3ProofDAG.Z3ProofNode(equiv1, Z3ProofRule.ASSERTED)); + pn.addChild(new Z3ProofDAG.Z3ProofNode(equiv2, Z3ProofRule.ASSERTED)); - Z3ToResoluteProofConverter pc = new Z3ToResoluteProofConverter(mgr); + Z3ToResolutionProofConverter pc = new Z3ToResolutionProofConverter(mgr); ProofNode res = pc.handleTransitivity(pn); diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java index a7d8ad6ffd..2ca013cede 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java @@ -26,6 +26,7 @@ import org.sosy_lab.java_smt.api.SolverException; import org.sosy_lab.java_smt.api.UserPropagator; import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.solvers.z3.Z3ProofDAG.Z3ProofNode; class Z3TheoremProver extends Z3AbstractProver implements ProverEnvironment { @@ -152,8 +153,7 @@ public ProofNode getProof() throws SolverException, InterruptedException { Preconditions.checkState(!closed); Preconditions.checkState(this.isUnsat()); long proofAst = Native.solverGetProof(z3context, z3solver); - return new Z3NonRecursiveProofProcessor(z3context, z3solver, creator, this) - .fromASTIterative(proofAst); + return Z3ProofNode.fromZ3Proof(proofAst, creator); } // This method is used to get the Z3 proof as a long for testing exclusively From 35732edfde27c790c95d818acfb6b4ab16474b0e Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 21 Apr 2025 16:27:12 +0200 Subject: [PATCH 078/132] Test for handling proofs expanded, now tests if all methods from 'ProofNode' work, and that the proper Exception is thrown when the solver does not have the getProof() method implemented. --- .../java_smt/test/ProverEnvironmentTest.java | 96 ++++++++++++++----- .../java_smt/test/SolverBasedTest0.java | 5 +- 2 files changed, 77 insertions(+), 24 deletions(-) diff --git a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java index 174334c0c0..a5361ed628 100644 --- a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java +++ b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java @@ -11,11 +11,14 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.TruthJUnit.assume; import static org.junit.Assert.assertThrows; +import static org.junit.Assume.assumeTrue; import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.CVC4; import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.CVC5; import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.MATHSAT5; import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.OPENSMT; import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.PRINCESS; +import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.SMTINTERPOL; +import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.Z3; import static org.sosy_lab.java_smt.api.SolverContext.ProverOptions.GENERATE_UNSAT_CORE; import static org.sosy_lab.java_smt.api.SolverContext.ProverOptions.GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS; import static org.sosy_lab.java_smt.test.ProverEnvironmentSubject.assertThat; @@ -31,6 +34,13 @@ import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.ProofRule; +import org.sosy_lab.java_smt.solvers.bitwuzla.BitwuzlaSolverContext; +import org.sosy_lab.java_smt.solvers.boolector.BoolectorSolverContext; +import org.sosy_lab.java_smt.solvers.cvc4.CVC4SolverContext; +import org.sosy_lab.java_smt.solvers.opensmt.OpenSmtSolverContext; +import org.sosy_lab.java_smt.solvers.princess.PrincessSolverContext; +import org.sosy_lab.java_smt.solvers.yices2.Yices2SolverContext; public class ProverEnvironmentTest extends SolverBasedTest0.ParameterizedSolverBasedTest0 { @@ -84,7 +94,7 @@ public void unsatCoreTestForInterpolation() throws SolverException, InterruptedE requireUnsatCore(); requireInterpolation(); try (BasicProverEnvironment pe = - context.newProverEnvironmentWithInterpolation(GENERATE_UNSAT_CORE)) { + context.newProverEnvironmentWithInterpolation(GENERATE_UNSAT_CORE)) { unsatCoreTest0(pe); } } @@ -94,7 +104,7 @@ public void unsatCoreTestForOptimizationProver() throws SolverException, Interru requireUnsatCore(); requireOptimization(); try (BasicProverEnvironment pe = - context.newOptimizationProverEnvironment(GENERATE_UNSAT_CORE)) { + context.newOptimizationProverEnvironment(GENERATE_UNSAT_CORE)) { unsatCoreTest0(pe); } } @@ -124,7 +134,7 @@ public void unsatCoreWithAssumptionsNullTest() { .isNoneOf(PRINCESS, CVC4, CVC5, OPENSMT); try (ProverEnvironment pe = - context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { + context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { assertThrows(NullPointerException.class, () -> pe.unsatCoreOverAssumptions(null)); } } @@ -139,7 +149,7 @@ public void unsatCoreWithAssumptionsTest() throws SolverException, InterruptedEx .that(solverToUse()) .isNoneOf(PRINCESS, CVC4, CVC5, OPENSMT); try (ProverEnvironment pe = - context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { + context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { pe.push(); pe.addConstraint(imgr.equal(imgr.makeVariable("y"), imgr.makeNumber(2))); BooleanFormula selector = bmgr.makeVariable("b"); @@ -161,12 +171,13 @@ public void testSatWithUnsatUnsatCoreOptions() throws InterruptedException, Solv requireUnsatCoreOverAssumptions(); try (ProverEnvironment prover = - context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { + context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { checkSimpleQuery(prover); } try (ProverEnvironment prover = - context.newProverEnvironment(GENERATE_UNSAT_CORE, GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { + context.newProverEnvironment(GENERATE_UNSAT_CORE, + GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { checkSimpleQuery(prover); } } @@ -190,22 +201,63 @@ private void checkSimpleQuery(ProverEnvironment pProver) } @Test - public void testGetProof() throws InterruptedException { - requireProofGeneration(); // Ensures proofs are supported - BooleanFormula q1 = bmgr.makeVariable("q1"); - BooleanFormula q2 = bmgr.makeVariable("q2"); - - try (ProverEnvironment prover = context.newProverEnvironment(ProverOptions.GENERATE_PROOFS)) { - prover.addConstraint(bmgr.or(bmgr.not(q1), q2)); - prover.addConstraint(q1); - prover.addConstraint(bmgr.not(q2)); - - assertThat(prover.isUnsat()).isTrue(); - - ProofNode proof = prover.getProof(); - assertThat(proof).isNotNull(); - } catch (SolverException pE) { - throw new RuntimeException(pE); + public void testProof() throws InterruptedException, SolverException { + requireProofGeneration(); // Ensures proofs are supported + BooleanFormula q1 = bmgr.makeVariable("q1"); + BooleanFormula q2 = bmgr.makeVariable("q2"); + + try (ProverEnvironment prover = context.newProverEnvironment(ProverOptions.GENERATE_PROOFS)) { + prover.addConstraint(bmgr.or(bmgr.not(q1), q2)); + prover.addConstraint(q1); + prover.addConstraint(bmgr.not(q2)); + + assertThat(prover.isUnsat()).isTrue(); + + //Test getProof() + ProofNode proof = prover.getProof(); + assertThat(proof).isNotNull(); + + //Test getRule() + assertThat(proof.getRule()).isNotNull(); + assertThat(proof.getRule()).isInstanceOf(ProofRule.class); + + //Test getFormula(), the root should always be false + assertThat(proof.getFormula()).isEqualTo(bmgr.makeFalse()); + + //Test getChildren() + assertThat(proof.getChildren()).isNotNull(); + assertThat(proof.getChildren()).isNotEmpty(); + + //Test getId() + assertThat(proof.getId()).isNotNull(); + assertThat(proof.getId()).isNotEqualTo(proof.getChildren().get(0).getId()); + + //Test isLeaf() + assertThat(proof.isLeaf()).isFalse(); + ProofNode leaf = findanyProofLeaf(proof); + assertThat(leaf).isNotNull(); + assertThat(leaf.isLeaf()).isTrue(); + + + } catch (UnsupportedOperationException uE) { + assertThat(uE).hasMessageThat() + .isEqualTo("Proof generation is not available for the current solver."); + Class contextClass = context.getClass(); + boolean isExpected = contextClass.equals(CVC4SolverContext.class) + || contextClass.equals(PrincessSolverContext.class) + || contextClass.equals(OpenSmtSolverContext.class) + || contextClass.equals(BoolectorSolverContext.class) + || contextClass.equals(BitwuzlaSolverContext.class) + || contextClass.equals(Yices2SolverContext.class); + assertThat(isExpected).isTrue(); + } + } + + private ProofNode findanyProofLeaf(ProofNode pn) { + if (pn.isLeaf()) { + return pn; } + return findanyProofLeaf(pn.getChildren().get(0)); + } } diff --git a/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java b/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java index ef58d2e377..266410ccd1 100644 --- a/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java +++ b/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java @@ -382,9 +382,10 @@ protected void requireUserPropagators() { protected void requireProofGeneration() { assume() - .withMessage("Solver %s does not support proof generation", solverToUse()) + .withMessage("Current version of solver %s does not support proof generation", + solverToUse()) .that(solverToUse()) - .isNoneOf(Solvers.BOOLECTOR, Solvers.BITWUZLA, Solvers.YICES2); + .isNoneOf(Solvers.BOOLECTOR, Solvers.BITWUZLA, Solvers.YICES2, Solvers.CVC4); } /** From fce805391836def0011546db9bc432f6f1312b45 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 21 Apr 2025 16:27:51 +0200 Subject: [PATCH 079/132] Z3: Native method for retrieving proofs in 'Z3TheoremProver' now wrapped in a try catch block --- src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java index 2ca013cede..9d6467403c 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java @@ -152,7 +152,12 @@ protected long getZ3Model() { public ProofNode getProof() throws SolverException, InterruptedException { Preconditions.checkState(!closed); Preconditions.checkState(this.isUnsat()); - long proofAst = Native.solverGetProof(z3context, z3solver); + long proofAst; + try { + proofAst = Native.solverGetProof(z3context, z3solver); + } catch (Z3Exception e) { + throw creator.handleZ3Exception(e); + } return Z3ProofNode.fromZ3Proof(proofAst, creator); } From 1fbc3ccf8b1ce60de75883be4ecacfdfdbdb4ca0 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 21 Apr 2025 17:59:59 +0200 Subject: [PATCH 080/132] CVC5: 'CVC5ProofProcessor' deleted. Proofs are now processed in 'CVC5ProofNode' Z3: Frame class in 'Z3ProofDAG' now private. --- .../solvers/cvc5/CVC5AbstractProver.java | 5 +- .../java_smt/solvers/cvc5/CVC5ProofDAG.java | 122 ++++++++++++++++++ .../java_smt/solvers/cvc5/CVC5ProofNode.java | 43 ------ .../solvers/cvc5/CVC5ProofProcessor.java | 103 --------------- .../java_smt/solvers/z3/Z3ProofDAG.java | 2 +- 5 files changed, 126 insertions(+), 149 deletions(-) create mode 100644 src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofDAG.java delete mode 100644 src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java delete mode 100644 src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java index 78de43cafc..8b8d424a50 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java @@ -40,6 +40,7 @@ import org.sosy_lab.java_smt.api.SolverException; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.AbstractProverWithAllSat; +import org.sosy_lab.java_smt.solvers.cvc5.CVC5ProofDAG.CVC5ProofNode; abstract class CVC5AbstractProver extends AbstractProverWithAllSat { @@ -256,9 +257,9 @@ public ProofNode getProof() { throw new IllegalStateException("No proof available"); } - CVC5ProofProcessor pp = new CVC5ProofProcessor(creator); + //CVC5ProofProcessor pp = new CVC5ProofProcessor(creator); try { - return pp.fromCVC5Proof(proofs[0]); + return CVC5ProofNode.fromCVC5Proof(proofs[0], creator); } catch (CVC5ApiException pE) { throw new RuntimeException(pE); } diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofDAG.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofDAG.java new file mode 100644 index 0000000000..e161bece9e --- /dev/null +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofDAG.java @@ -0,0 +1,122 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.solvers.cvc5; + +import io.github.cvc5.CVC5ApiException; +import io.github.cvc5.Proof; +import io.github.cvc5.Term; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.proofs.ProofFrame; +import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.ProofRule; +import org.sosy_lab.java_smt.basicimpl.AbstractProofDAG; + + + +public class CVC5ProofDAG extends AbstractProofDAG { + private static class CVC5Frame extends ProofFrame { + CVC5Frame(Proof proof) { + super(proof); + } + } + public static class CVC5ProofNode extends AbstractProofNode { + + public CVC5ProofNode(ProofRule pProofRule, Formula formula) { + + super(pProofRule, formula); + } + + static CVC5ProofNode fromCVC5Proof(Proof pProof, CVC5FormulaCreator formulaCreator) throws CVC5ApiException { + + boolean skippedScope = false; + + Deque stack = new ArrayDeque<>(); + + Map computed = new HashMap<>(); + + stack.push(new CVC5Frame(pProof)); + + while (!stack.isEmpty()) { + CVC5Frame frame = stack.peek(); + + if (!frame.isVisited()) { + + frame.setNumArgs(frame.getProof().getChildren().length); + frame.setAsVisited(true); + + for (int i = frame.getNumArgs() - 1; i >= 0; i--) { + Proof child = frame.getProof().getChildren()[i]; + if (!computed.containsKey(child)) { + stack.push(new CVC5Frame(child)); + } + } + } else { + stack.pop(); + int numChildren = frame.getNumArgs(); + + if (frame.getProof().getRule().getValue() == 1 && !skippedScope) { + // Skip processing the frame if its rule is "SCOPE" + // This rule seems to just help the processing by CVC5 + pProof = changeRoot(frame.getProof()); + skippedScope = true; + continue; + } + + CVC5ProofRule proofRule = + Enum.valueOf(CVC5ProofRule.class, frame.getProof().getRule().toString()); + // ProofRule.fromName( + // CVC5ProofRule.class, frame.getProof().getRule().toString().toLowerCase()); + + //Generate formula + Term term = frame.getProof().getResult(); + Formula pFormula = formulaCreator.encapsulate(formulaCreator.getFormulaType(term), term); + CVC5ProofNode pn = new CVC5ProofNode(proofRule, pFormula); + for (int i = 0; i < numChildren; i++) { + Proof child = frame.getProof().getChildren()[i]; + + if (computed.containsKey(child)) { + pn.addChild(computed.get(child)); + } + } + computed.put(frame.getProof(), pn); + } + } + return computed.get(pProof); + } + + private static Proof changeRoot(Proof root) { + return root.getChildren()[0]; + } + + String asString(int indentLevel) { + StringBuilder proof = new StringBuilder(); + String indent = " ".repeat(indentLevel); + + proof.append(indent).append("Formula: ").append(getFormula().toString()).append("\n"); + proof.append(indent).append("Rule: ").append(getRule().getName()).append("\n"); + proof.append(indent).append("No. Children: ").append(getChildren().size()).append("\n"); + proof.append(indent).append("ID: ").append(getId()).append("\n"); + proof.append(indent).append("leaf: ").append(isLeaf()).append("\n"); + + int i = 0; + for (ProofNode child : getChildren()) { + proof.append(indent).append("Child ").append(++i).append(":\n"); + proof.append(((CVC5ProofNode) child).asString(indentLevel + 1)); + } + + return proof.toString(); + } + } +} diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java deleted file mode 100644 index 94ffc81322..0000000000 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofNode.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * This file is part of JavaSMT, - * an API wrapper for a collection of SMT solvers: - * https://github.com/sosy-lab/java-smt - * - * SPDX-FileCopyrightText: 2024 Dirk Beyer - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.sosy_lab.java_smt.solvers.cvc5; - -import org.sosy_lab.java_smt.api.Formula; -import org.sosy_lab.java_smt.api.proofs.ProofNode; -import org.sosy_lab.java_smt.api.proofs.ProofRule; -import org.sosy_lab.java_smt.basicimpl.AbstractProofDAG.AbstractProofNode; - -public class CVC5ProofNode extends AbstractProofNode { - - public CVC5ProofNode(ProofRule pProofRule, Formula formula) { - - super(pProofRule, formula); - } - - String asString(int indentLevel) { - StringBuilder proof = new StringBuilder(); - String indent = " ".repeat(indentLevel); - - proof.append(indent).append("Formula: ").append(getFormula().toString()).append("\n"); - proof.append(indent).append("Rule: ").append(getRule().getName()).append("\n"); - proof.append(indent).append("No. Children: ").append(getChildren().size()).append("\n"); - proof.append(indent).append("ID: ").append(getId()).append("\n"); - proof.append(indent).append("leaf: ").append(isLeaf()).append("\n"); - - int i = 0; - for (ProofNode child : getChildren()) { - proof.append(indent).append("Child ").append(++i).append(":\n"); - proof.append(((CVC5ProofNode) child).asString(indentLevel + 1)); - } - - return proof.toString(); - } -} diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java deleted file mode 100644 index 6260b7e18d..0000000000 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofProcessor.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * This file is part of JavaSMT, - * an API wrapper for a collection of SMT solvers: - * https://github.com/sosy-lab/java-smt - * - * SPDX-FileCopyrightText: 2024 Dirk Beyer - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.sosy_lab.java_smt.solvers.cvc5; - -import io.github.cvc5.CVC5ApiException; -import io.github.cvc5.Proof; -import io.github.cvc5.Term; -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.HashMap; -import java.util.Map; -import org.sosy_lab.java_smt.api.Formula; -import org.sosy_lab.java_smt.api.proofs.ProofFrame; - -public class CVC5ProofProcessor { - - private static class CVC5Frame extends ProofFrame { - CVC5Frame(Proof proof) { - super(proof); - } - } - - private final CVC5FormulaCreator formulaCreator; - - CVC5ProofProcessor(CVC5FormulaCreator creator) { - formulaCreator = creator; - } - - CVC5ProofNode fromCVC5Proof(Proof pProof) throws CVC5ApiException { - - boolean skippedScope = false; - - Deque stack = new ArrayDeque<>(); - - Map computed = new HashMap<>(); - - stack.push(new CVC5Frame(pProof)); - - while (!stack.isEmpty()) { - CVC5Frame frame = stack.peek(); - - if (!frame.isVisited()) { - - frame.setNumArgs(frame.getProof().getChildren().length); - frame.setAsVisited(true); - - for (int i = frame.getNumArgs() - 1; i >= 0; i--) { - Proof child = frame.getProof().getChildren()[i]; - if (!computed.containsKey(child)) { - stack.push(new CVC5Frame(child)); - } - } - } else { - stack.pop(); - int numChildren = frame.getNumArgs(); - - if (frame.getProof().getRule().getValue() == 1 && !skippedScope) { - // Skip processing the frame if its rule is "SCOPE" - // This rule seems to just help the processing by CVC5 - pProof = changeRoot(frame.getProof()); - skippedScope = true; - continue; - } - - CVC5ProofRule proofRule = - Enum.valueOf(CVC5ProofRule.class, frame.getProof().getRule().toString()); - // ProofRule.fromName( - // CVC5ProofRule.class, frame.getProof().getRule().toString().toLowerCase()); - CVC5ProofNode pn = new CVC5ProofNode(proofRule, generateFormula(frame.getProof())); - for (int i = 0; i < numChildren; i++) { - Proof child = frame.getProof().getChildren()[i]; - - if (computed.containsKey(child)) { - pn.addChild(computed.get(child)); - } - } - computed.put(frame.getProof(), pn); - } - } - return computed.get(pProof); - } - - private Formula generateFormula(Proof proof) { - Formula formula = null; - if (formula == null) { - Term term = proof.getResult(); - formula = formulaCreator.encapsulate(formulaCreator.getFormulaType(term), term); - } - return formula; - } - - private Proof changeRoot(Proof root) { - return root.getChildren()[0]; - } -} diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDAG.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDAG.java index c21c7fcdb0..ee3b3381af 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDAG.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDAG.java @@ -25,7 +25,7 @@ import org.sosy_lab.java_smt.basicimpl.FormulaCreator; public class Z3ProofDAG extends AbstractProofDAG { - protected static class Frame extends ProofFrame { + private static class Frame extends ProofFrame { protected Frame(Long proof) { super(proof); } From 2007795e59b6ec50441bfc546e676040ba903114 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 2 May 2025 14:05:24 +0200 Subject: [PATCH 081/132] AbstractProofDAG: formula is now nullable. 'setFormula' set to public. --- src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java index 680bce9a36..59b15cf7a4 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java @@ -16,6 +16,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.annotation.Nullable; import org.sosy_lab.common.UniqueIdGenerator; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.ProofDAG; @@ -64,7 +65,7 @@ public void accept(ProofVisitor visitor) { public abstract static class AbstractProofNode implements ProofNode { private final List children; private ProofRule rule; - protected Formula formula; + @Nullable protected Formula formula; private static final UniqueIdGenerator idGenerator = new UniqueIdGenerator(); private final int id; @@ -109,7 +110,7 @@ void setRule(ProofRule rule) { this.rule = rule; } - void setFormula(Formula pFormula) { + public void setFormula(Formula pFormula) { formula = pFormula; } } From 066de33a3e1f475d306ec86dd247895ecef397b1 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 2 May 2025 14:06:57 +0200 Subject: [PATCH 082/132] Checkstyle --- .../solvers/cvc5/CVC5AbstractProver.java | 2 +- .../java_smt/solvers/cvc5/CVC5ProofDAG.java | 8 +- .../java_smt/test/ProverEnvironmentTest.java | 118 +++++++++--------- .../java_smt/test/SolverBasedTest0.java | 4 +- 4 files changed, 64 insertions(+), 68 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java index 8b8d424a50..486fa90e83 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java @@ -257,7 +257,7 @@ public ProofNode getProof() { throw new IllegalStateException("No proof available"); } - //CVC5ProofProcessor pp = new CVC5ProofProcessor(creator); + // CVC5ProofProcessor pp = new CVC5ProofProcessor(creator); try { return CVC5ProofNode.fromCVC5Proof(proofs[0], creator); } catch (CVC5ApiException pE) { diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofDAG.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofDAG.java index e161bece9e..a1bd57f2c3 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofDAG.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofDAG.java @@ -23,14 +23,13 @@ import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.basicimpl.AbstractProofDAG; - - public class CVC5ProofDAG extends AbstractProofDAG { private static class CVC5Frame extends ProofFrame { CVC5Frame(Proof proof) { super(proof); } } + public static class CVC5ProofNode extends AbstractProofNode { public CVC5ProofNode(ProofRule pProofRule, Formula formula) { @@ -38,7 +37,8 @@ public CVC5ProofNode(ProofRule pProofRule, Formula formula) { super(pProofRule, formula); } - static CVC5ProofNode fromCVC5Proof(Proof pProof, CVC5FormulaCreator formulaCreator) throws CVC5ApiException { + static CVC5ProofNode fromCVC5Proof(Proof pProof, CVC5FormulaCreator formulaCreator) + throws CVC5ApiException { boolean skippedScope = false; @@ -79,7 +79,7 @@ static CVC5ProofNode fromCVC5Proof(Proof pProof, CVC5FormulaCreator formulaCreat // ProofRule.fromName( // CVC5ProofRule.class, frame.getProof().getRule().toString().toLowerCase()); - //Generate formula + // Generate formula Term term = frame.getProof().getResult(); Formula pFormula = formulaCreator.encapsulate(formulaCreator.getFormulaType(term), term); CVC5ProofNode pn = new CVC5ProofNode(proofRule, pFormula); diff --git a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java index a5361ed628..30b5ed9d04 100644 --- a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java +++ b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java @@ -11,14 +11,11 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.TruthJUnit.assume; import static org.junit.Assert.assertThrows; -import static org.junit.Assume.assumeTrue; import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.CVC4; import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.CVC5; import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.MATHSAT5; import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.OPENSMT; import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.PRINCESS; -import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.SMTINTERPOL; -import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.Z3; import static org.sosy_lab.java_smt.api.SolverContext.ProverOptions.GENERATE_UNSAT_CORE; import static org.sosy_lab.java_smt.api.SolverContext.ProverOptions.GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS; import static org.sosy_lab.java_smt.test.ProverEnvironmentSubject.assertThat; @@ -94,7 +91,7 @@ public void unsatCoreTestForInterpolation() throws SolverException, InterruptedE requireUnsatCore(); requireInterpolation(); try (BasicProverEnvironment pe = - context.newProverEnvironmentWithInterpolation(GENERATE_UNSAT_CORE)) { + context.newProverEnvironmentWithInterpolation(GENERATE_UNSAT_CORE)) { unsatCoreTest0(pe); } } @@ -104,7 +101,7 @@ public void unsatCoreTestForOptimizationProver() throws SolverException, Interru requireUnsatCore(); requireOptimization(); try (BasicProverEnvironment pe = - context.newOptimizationProverEnvironment(GENERATE_UNSAT_CORE)) { + context.newOptimizationProverEnvironment(GENERATE_UNSAT_CORE)) { unsatCoreTest0(pe); } } @@ -134,7 +131,7 @@ public void unsatCoreWithAssumptionsNullTest() { .isNoneOf(PRINCESS, CVC4, CVC5, OPENSMT); try (ProverEnvironment pe = - context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { + context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { assertThrows(NullPointerException.class, () -> pe.unsatCoreOverAssumptions(null)); } } @@ -149,7 +146,7 @@ public void unsatCoreWithAssumptionsTest() throws SolverException, InterruptedEx .that(solverToUse()) .isNoneOf(PRINCESS, CVC4, CVC5, OPENSMT); try (ProverEnvironment pe = - context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { + context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { pe.push(); pe.addConstraint(imgr.equal(imgr.makeVariable("y"), imgr.makeNumber(2))); BooleanFormula selector = bmgr.makeVariable("b"); @@ -171,13 +168,12 @@ public void testSatWithUnsatUnsatCoreOptions() throws InterruptedException, Solv requireUnsatCoreOverAssumptions(); try (ProverEnvironment prover = - context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { + context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { checkSimpleQuery(prover); } try (ProverEnvironment prover = - context.newProverEnvironment(GENERATE_UNSAT_CORE, - GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { + context.newProverEnvironment(GENERATE_UNSAT_CORE, GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { checkSimpleQuery(prover); } } @@ -202,62 +198,62 @@ private void checkSimpleQuery(ProverEnvironment pProver) @Test public void testProof() throws InterruptedException, SolverException { - requireProofGeneration(); // Ensures proofs are supported - BooleanFormula q1 = bmgr.makeVariable("q1"); - BooleanFormula q2 = bmgr.makeVariable("q2"); - - try (ProverEnvironment prover = context.newProverEnvironment(ProverOptions.GENERATE_PROOFS)) { - prover.addConstraint(bmgr.or(bmgr.not(q1), q2)); - prover.addConstraint(q1); - prover.addConstraint(bmgr.not(q2)); - - assertThat(prover.isUnsat()).isTrue(); - - //Test getProof() - ProofNode proof = prover.getProof(); - assertThat(proof).isNotNull(); - - //Test getRule() - assertThat(proof.getRule()).isNotNull(); - assertThat(proof.getRule()).isInstanceOf(ProofRule.class); - - //Test getFormula(), the root should always be false - assertThat(proof.getFormula()).isEqualTo(bmgr.makeFalse()); - - //Test getChildren() - assertThat(proof.getChildren()).isNotNull(); - assertThat(proof.getChildren()).isNotEmpty(); - - //Test getId() - assertThat(proof.getId()).isNotNull(); - assertThat(proof.getId()).isNotEqualTo(proof.getChildren().get(0).getId()); - - //Test isLeaf() - assertThat(proof.isLeaf()).isFalse(); - ProofNode leaf = findanyProofLeaf(proof); - assertThat(leaf).isNotNull(); - assertThat(leaf.isLeaf()).isTrue(); - - - } catch (UnsupportedOperationException uE) { - assertThat(uE).hasMessageThat() - .isEqualTo("Proof generation is not available for the current solver."); - Class contextClass = context.getClass(); - boolean isExpected = contextClass.equals(CVC4SolverContext.class) - || contextClass.equals(PrincessSolverContext.class) - || contextClass.equals(OpenSmtSolverContext.class) - || contextClass.equals(BoolectorSolverContext.class) - || contextClass.equals(BitwuzlaSolverContext.class) - || contextClass.equals(Yices2SolverContext.class); - assertThat(isExpected).isTrue(); - } + requireProofGeneration(); // Ensures proofs are supported + BooleanFormula q1 = bmgr.makeVariable("q1"); + BooleanFormula q2 = bmgr.makeVariable("q2"); + + try (ProverEnvironment prover = context.newProverEnvironment(ProverOptions.GENERATE_PROOFS)) { + prover.addConstraint(bmgr.or(bmgr.not(q1), q2)); + prover.addConstraint(q1); + prover.addConstraint(bmgr.not(q2)); + + assertThat(prover.isUnsat()).isTrue(); + + // Test getProof() + ProofNode proof = prover.getProof(); + assertThat(proof).isNotNull(); + + // Test getRule() + assertThat(proof.getRule()).isNotNull(); + assertThat(proof.getRule()).isInstanceOf(ProofRule.class); + + // Test getFormula(), the root should always be false + assertThat(proof.getFormula()).isEqualTo(bmgr.makeFalse()); + + // Test getChildren() + assertThat(proof.getChildren()).isNotNull(); + assertThat(proof.getChildren()).isNotEmpty(); + + // Test getId() + assertThat(proof.getId()).isNotNull(); + assertThat(proof.getId()).isNotEqualTo(proof.getChildren().get(0).getId()); + + // Test isLeaf() + assertThat(proof.isLeaf()).isFalse(); + ProofNode leaf = findanyProofLeaf(proof); + assertThat(leaf).isNotNull(); + assertThat(leaf.isLeaf()).isTrue(); + + } catch (UnsupportedOperationException uE) { + assertThat(uE) + .hasMessageThat() + .isEqualTo("Proof generation is not available for the current solver."); + Class contextClass = context.getClass(); + boolean isExpected = + contextClass.equals(CVC4SolverContext.class) + || contextClass.equals(PrincessSolverContext.class) + || contextClass.equals(OpenSmtSolverContext.class) + || contextClass.equals(BoolectorSolverContext.class) + || contextClass.equals(BitwuzlaSolverContext.class) + || contextClass.equals(Yices2SolverContext.class); + assertThat(isExpected).isTrue(); + } } private ProofNode findanyProofLeaf(ProofNode pn) { if (pn.isLeaf()) { return pn; } - return findanyProofLeaf(pn.getChildren().get(0)); - + return findanyProofLeaf(pn.getChildren().get(0)); } } diff --git a/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java b/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java index 266410ccd1..90639af5b4 100644 --- a/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java +++ b/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java @@ -382,8 +382,8 @@ protected void requireUserPropagators() { protected void requireProofGeneration() { assume() - .withMessage("Current version of solver %s does not support proof generation", - solverToUse()) + .withMessage( + "Current version of solver %s does not support proof generation", solverToUse()) .that(solverToUse()) .isNoneOf(Solvers.BOOLECTOR, Solvers.BITWUZLA, Solvers.YICES2, Solvers.CVC4); } From 16c9aa823906bda84146fdded1e52d433bb7b75d Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 2 May 2025 14:07:10 +0200 Subject: [PATCH 083/132] 'setFormula' deleted --- .../sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java index 14bbed29a4..6c020aae3b 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java @@ -177,10 +177,6 @@ private static Formula generateFormula( return formula; } - void setFormula(Formula formula) { - this.formula = formula; - } - String asString() { return asString(0); } From e4f52c2d03396eb7ad1cc4c8db9747e4a47b7046 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 2 May 2025 14:07:46 +0200 Subject: [PATCH 084/132] First steps towards implementing 'getProof' --- .../solvers/princess/PrincessAbstractProver.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/org/sosy_lab/java_smt/solvers/princess/PrincessAbstractProver.java b/src/org/sosy_lab/java_smt/solvers/princess/PrincessAbstractProver.java index a816ed5c7e..134179685f 100644 --- a/src/org/sosy_lab/java_smt/solvers/princess/PrincessAbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/princess/PrincessAbstractProver.java @@ -18,6 +18,7 @@ import ap.parser.IFormula; import ap.parser.IFunction; import ap.parser.ITerm; +import ap.proof.certificates.Certificate; import com.google.common.base.Preconditions; import com.google.errorprone.annotations.CanIgnoreReturnValue; import java.util.ArrayDeque; @@ -38,6 +39,7 @@ import org.sosy_lab.java_smt.api.Model; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; +import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.AbstractProverWithAllSat; import org.sosy_lab.java_smt.basicimpl.CachingModel; import scala.Enumeration.Value; @@ -278,4 +280,14 @@ public String toString() { return String.format("{%s, %s, %s}", booleanSymbols, theorySymbols, functionSymbols); } } + + //@Override + //public ProofNode getProof() { + // api.getCertificate(); + // return null; + // } + + // protected Certificate getCertificate() { + // return api.getCertificate(); + //} } From 5cef715b6336b5672b5a05378327d2519270e62f Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 2 May 2025 14:08:40 +0200 Subject: [PATCH 085/132] SMTInterpol: proof generation support now implemented. --- .../smtinterpol/SmtInteprolProofDAG.java | 308 +++++++++++++++ .../SmtInterpolAbstractProver.java | 292 ++++++++++++++- .../SmtInterpolProofNodeCreator.java | 353 ------------------ .../smtinterpol/SmtInterpolProofsTest.java | 20 +- 4 files changed, 604 insertions(+), 369 deletions(-) create mode 100644 src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInteprolProofDAG.java delete mode 100644 src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInteprolProofDAG.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInteprolProofDAG.java new file mode 100644 index 0000000000..196c9d1687 --- /dev/null +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInteprolProofDAG.java @@ -0,0 +1,308 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.solvers.smtinterpol; + +import de.uni_freiburg.informatik.ultimate.logic.AnnotatedTerm; +import de.uni_freiburg.informatik.ultimate.logic.Annotation; +import de.uni_freiburg.informatik.ultimate.logic.ApplicationTerm; +import de.uni_freiburg.informatik.ultimate.logic.Sort; +import de.uni_freiburg.informatik.ultimate.logic.Term; +import de.uni_freiburg.informatik.ultimate.logic.Util; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Deque; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.sosy_lab.java_smt.ResProofRule; +import org.sosy_lab.java_smt.ResProofRule.ResAxiom; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.proofs.ProofRule; +import org.sosy_lab.java_smt.basicimpl.AbstractProofDAG; + +/** + * This class represents a SMTInterpol proof DAG in the JavaSMT proof interface. Many formulas that + * are not in the leafs or are pivots for resolution are null, as SMTInterpol does not provide them. + * Every resolution node has 3 chilren: sub-proof, pivot, sub-proof. There exists the RUP sub-proof, + * these means that the stored formula was proven by applying RUP to the child of the node. The + * PIVOT and RUP proof rules have been added to the proof format from SMTInterpol for the sake of + * offering a proof rule at every step of the proof as well as allowing to display the pivots for + * resolution steps. + */ +class SmtInteprolProofDAG extends AbstractProofDAG { + protected enum Rules implements ProofRule { + RUP, + PIVOT; + + @Override + public String getName() { + return name().toLowerCase(); + } + } + + protected static class SmtInterpolProofNode extends AbstractProofNode { + SmtInterpolProofNode(ProofRule pRule, Formula pFormula) { + super(pRule, pFormula); + } + } + + static class SmtInterpolProofNodeCreator { + private final SmtInterpolFormulaCreator creator; + private final SmtInterpolAbstractProver prover; + + SmtInterpolProofNodeCreator( + SmtInterpolFormulaCreator pCreator, SmtInterpolAbstractProver pProver) { + creator = pCreator; + prover = pProver; + } + + SmtInterpolProofNode createProof(ProvitionalProofNode pProofNode) { + Deque stack = new ArrayDeque<>(); + Map computed = new HashMap<>(); + + stack.push(pProofNode); + + while (!stack.isEmpty()) { + ProvitionalProofNode proofNode = stack.peek(); + + if (!proofNode.isVisited) { + proofNode.isVisited = true; + + if (proofNode.proofRule.equals(ResAxiom.RESOLUTION)) { + ProvitionalProofNode pivot = new ProvitionalProofNode(); + pivot.proofRule = Rules.PIVOT; + pivot.formulas.add(proofNode.pivot); + proofNode.children.add(1, pivot); + for (ProvitionalProofNode child : proofNode.children) { + stack.push(child); + } + } else { + for (ProvitionalProofNode child : proofNode.children) { + stack.push(child); + } + } + } else { + stack.pop(); + Formula formula = null; + if (proofNode.formulas.size() > 1) { + Term or = Util.or(creator.getEnv(), proofNode.formulas.toArray(new Term[0])); + formula = creator.encapsulate(creator.getFormulaType(or), or); + } else if (!proofNode.formulas.isEmpty()) { + Term t = proofNode.formulas.get(0); + formula = creator.encapsulate(creator.getFormulaType(t), t); + } + SmtInterpolProofNode pn = new SmtInterpolProofNode(proofNode.proofRule, formula); + for (int i = 0; i < proofNode.children.size(); i++) { + ProvitionalProofNode child = proofNode.children.get(i); + if (computed.containsKey(child)) { + pn.addChild(computed.get(child)); + } + } + computed.put(proofNode, pn); + } + } + return computed.get(pProofNode); + } + + ProvitionalProofNode createPPNDag(Term proof) { + return new ProvitionalProofNode(proof); + } + + class ProvitionalProofNode { + Term pivot; + ProofRule proofRule; + List formulas = new ArrayList<>(); + boolean axiom; + List children = new ArrayList<>(); + Term unprocessedTerm; + boolean isVisited = false; + + ProvitionalProofNode() {} + + protected ProvitionalProofNode(Term pParameter) { + this.unprocessedTerm = pParameter; + processTerm(pParameter); + } + + protected void processTerm(Term pParameter) { + if (pParameter instanceof ApplicationTerm) { + processApplication((ApplicationTerm) pParameter); + } else if (pParameter instanceof AnnotatedTerm) { + processAnnotated((AnnotatedTerm) pParameter); + } + } + + void processApplication(ApplicationTerm term) { + Term[] parameters = term.getParameters(); + if (parameters.length == 3) { + this.proofRule = ResAxiom.RESOLUTION; + // This should be a resolution rule + Term first = parameters[0]; + if (first instanceof AnnotatedTerm) { + pivot = ((AnnotatedTerm) first).getSubterm(); + } else if (first instanceof ApplicationTerm) { + pivot = first; + } + + for (int i = 1; i < parameters.length; i++) { + Sort sort = term.getSort(); + if (sort.toString().equals("..Proof")) { + children.add(new ProvitionalProofNode(parameters[i])); + } + } + } + + if (term.getFunction().toString().contains("..assume")) { + // This should be the assume axiom + this.axiom = true; + this.proofRule = ResAxiom.ASSUME; + if (parameters[0] instanceof AnnotatedTerm) { + this.formulas.add(((AnnotatedTerm) parameters[0]).getSubterm()); + } else { + this.formulas.add(parameters[0]); + } + } + } + + private void processAnnotated(AnnotatedTerm term) { + + boolean rup = false; + + if (term.getSort().toString().equals("Bool")) { + if (this.axiom) { + this.pivot = term.getSubterm(); + } else { + this.formulas.add(term.getSubterm()); + } + } + + for (Annotation annotation : term.getAnnotations()) { + ResAxiom rule; + String key = annotation.getKey().substring(1); + + if (term.getSubterm().toString().equals("..axiom")) { + this.axiom = true; + // Annotation key should contain axiom name and value should contain an array with some + // of its objects being Terms and the index before each one of those contains the + // polarity. + key = key.startsWith(":") ? key.substring(1) : key; + + rule = ResProofRule.getFromName(key); + + this.proofRule = rule; + // This Annotation's value should have an array with the polarities and Terms that are + // proven. This is the clause proven the ApplicationTerm. The array is empty for the + // very first Term. + // Now we need to go through the array and find the Term objects and their polarity. + // This is the same for proves. + if (annotation.getValue() instanceof Object[]) { + Object[] values = (Object[]) annotation.getValue(); + addTermsFromAnnotationValue(values, false); + } else if (annotation.getValue() instanceof AnnotatedTerm) { + processAnnotated((AnnotatedTerm) annotation.getValue()); + } else if (annotation.getValue() instanceof ApplicationTerm) { + formulas.add((Term) annotation.getValue()); + } + } + + if (key.equals("rup")) { + this.proofRule = Rules.RUP; + this.children.add(new ProvitionalProofNode(term.getSubterm())); + rup = true; + } + + if (key.equals("proves")) { + Object[] values = (Object[]) annotation.getValue(); + addTermsFromAnnotationValue(values, true); + } + } + if (!rup) { + processTerm(term.getSubterm()); + } + } + + void addTermsFromAnnotationValue(Object[] values, boolean isProves) { + for (int i = 0; values.length > i; i++) { + if (values[i] instanceof Term) { + // We found a Term and the index before it should contain the polarity, but only if + // this is the value of the proves Annotation. + if (isProves) { + assert values[i - 1].getClass() == String.class; + if (((String) values[i - 1]).contains("+")) { + this.formulas.add((Term) values[i]); + } else { + // We try to create the negative polarity Term + this.formulas.add(Util.not(creator.getEnv(), (Term) values[i])); + } + } else { + this.formulas.add((Term) values[i]); + } + } + } + } + + // Just for testing purposes + protected String asString() { + return asString(0); + } + + String asString(int indentLevel) { + StringBuilder sb = new StringBuilder(); + String indent = " ".repeat(indentLevel); + + // Node header + sb.append(indent).append("ProofNode {\n"); + + // Node properties + sb.append(indent).append(" pivot: ").append(pivot != null ? pivot : "null").append("\n"); + sb.append(indent) + .append(" proofRule: ") + .append(proofRule != null ? proofRule.getName() : "null") + .append("\n"); + sb.append(indent).append(" axiom: ").append(axiom).append("\n"); + + // Formulas + sb.append(indent).append(" formulas: [\n"); + if (formulas.isEmpty()) { + sb.append(indent).append(" empty\n"); + } else { + for (Term formula : formulas) { + sb.append(indent) + .append(" ") + .append(formula != null ? formula : "null") + .append("\n"); + } + } + sb.append(indent).append(" ]\n"); + + // Children nodes + sb.append(indent).append(" children: [\n"); + if (children.isEmpty()) { + sb.append(indent).append(" empty\n"); + } else { + for (ProvitionalProofNode child : children) { + if (child != null) { + sb.append(child.asString(indentLevel + 2)); + } else { + sb.append(indent).append(" null\n"); + } + } + } + sb.append(indent).append(" ]\n"); + + // Close node + sb.append(indent).append("}\n"); + + return sb.toString(); + } + } + } +} diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java index 18844df8ef..2f518a2867 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java @@ -25,27 +25,39 @@ import de.uni_freiburg.informatik.ultimate.logic.Sort; import de.uni_freiburg.informatik.ultimate.logic.Term; import java.util.ArrayDeque; +import java.util.ArrayList; import java.util.Collection; import java.util.Deque; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.Stack; import org.sosy_lab.common.ShutdownNotifier; import org.sosy_lab.common.UniqueIdGenerator; import org.sosy_lab.common.collect.Collections3; import org.sosy_lab.common.collect.PathCopyingPersistentTreeMap; import org.sosy_lab.common.collect.PersistentMap; +import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.api.BasicProverEnvironment; import org.sosy_lab.java_smt.api.BooleanFormula; +import org.sosy_lab.java_smt.api.BooleanFormulaManager; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.FunctionDeclaration; +import org.sosy_lab.java_smt.api.QuantifiedFormulaManager.Quantifier; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; -import org.sosy_lab.java_smt.api.proofs.ProofDAG; import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.visitors.BooleanFormulaVisitor; +import org.sosy_lab.java_smt.api.visitors.TraversalProcess; import org.sosy_lab.java_smt.basicimpl.AbstractProver; import org.sosy_lab.java_smt.basicimpl.CachingModel; import org.sosy_lab.java_smt.basicimpl.FormulaCreator; +import org.sosy_lab.java_smt.solvers.smtinterpol.SmtInteprolProofDAG.SmtInterpolProofNode; +import org.sosy_lab.java_smt.solvers.smtinterpol.SmtInteprolProofDAG.SmtInterpolProofNodeCreator; +import org.sosy_lab.java_smt.solvers.smtinterpol.SmtInteprolProofDAG.SmtInterpolProofNodeCreator.ProvitionalProofNode; @SuppressWarnings("ClassTypeParameterName") abstract class SmtInterpolAbstractProver extends AbstractProver { @@ -215,17 +227,14 @@ public ImmutableMap getStatistics() { return builder.buildOrThrow(); } - @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) @Override public ProofNode getProof() { checkState(!closed); checkGenerateProofs(); - final Term proof; - final ProofDAG proofDAG; + final Term tProof; try { - proof = env.getProof(); - // proofDAG = ResolutionProofDAG.fromTerm(proof, mgr, annotatedTerms.peek()); + tProof = env.getProof(); } catch (SMTLIBException e) { if (e.getMessage().contains("Context is inconsistent")) { throw new IllegalStateException("Cannot get proof from satisfiable environment", e); @@ -234,8 +243,15 @@ public ProofNode getProof() { } } - // ResolutionProofDAG proofDag = fromSmtInterpol(proof, creator, getAssertedFormulas()); - return null; + SmtInterpolProofNodeCreator pc = + new SmtInterpolProofNodeCreator((SmtInterpolFormulaCreator) this.creator, this); + ProvitionalProofNode ppn = pc.createPPNDag(tProof); + ProofNode proof = pc.createProof(ppn); + // Before being able to perfom resolution, we need to calculate the formulas resulting from + // applying the axioms, as it stands, just the input for the axiom is stored. + // clausifyResChain(proof, mgr.getBooleanFormulaManager()); + + return proof; } // TODO: Delete this method @@ -280,4 +296,264 @@ public R allSat(AllSatCallback callback, List important) } return callback.getResult(); } + + // update all RES_CHAIN nodes in the proof DAG by computing resolution + // formulas and return the updated root node with formulas attached. + private void clausifyResChain(ProofNode root, BooleanFormulaManager bfmgr) { + Map visited = new HashMap<>(); // Track visited nodes + Stack stack = new Stack<>(); + Stack processStack = + new Stack<>(); // Stack to hold nodes for post-processing after children + + stack.push(root); // Start with the root node + visited.put(root, Boolean.FALSE); // Mark root as unvisited + + while (!stack.isEmpty()) { + ProofNode node = stack.peek(); // Look at the top node, but don't pop yet + + if (visited.get(node) == Boolean.FALSE) { + // First time visiting this node + visited.put(node, Boolean.TRUE); // Mark node as visited + + // Push all children onto stack + List children = node.getChildren(); + for (int i = children.size() - 1; i >= 0; i--) { + ProofNode child = children.get(i); + if (!visited.containsKey(child)) { + stack.push(child); // Only push unvisited children + visited.put(child, Boolean.FALSE); // Mark child as unvisited + } + } + } else { + // All children have been visited, now process the node + stack.pop(); // Pop the current node as we are done processing its children + + // Check if this node is a RES_CHAIN, process if true + if (node.getRule().equals(ResAxiom.RESOLUTION)) { + processResChain(node, bfmgr); // Process RES_CHAIN node + } + } + } + } + + // process proof nodes and compute formulas for res-chain nodes + private void processResChain(ProofNode node, BooleanFormulaManager bfmgr) { + List children = node.getChildren(); + + // If the current node is a RES_CHAIN, compute the resolved formula + if (node.getRule().equals(ResAxiom.RESOLUTION)) { + // Sanity check: res-chain nodes must have an odd number of children (clause, pivot, clause, + // ..., clause) + if (children.size() < 3 || children.size() % 2 == 0) { + throw new IllegalArgumentException("Invalid res-chain structure: must be odd and >= 3"); + } + + // Begin resolution chain: start with the first clause + BooleanFormula current = (BooleanFormula) children.get(0).getFormula(); + + // Apply resolution iteratively using pivot, clause pairs + for (int i = 1; i < children.size() - 1; i += 2) { + BooleanFormula pivot = (BooleanFormula) children.get(i).getFormula(); + BooleanFormula nextClause = (BooleanFormula) children.get(i + 1).getFormula(); + current = resolve(current, nextClause, pivot, bfmgr); // Perform resolution step + } + + // Store the resolved formula in the current node + ((SmtInterpolProofNode) node).setFormula(current); + } + } + + // Perform resolution between two clauses using a given pivot + private BooleanFormula resolve( + BooleanFormula clause1, + BooleanFormula clause2, + BooleanFormula pivot, + BooleanFormulaManager bfmgr) { + List literals1 = flattenLiterals(clause1, bfmgr); + List literals2 = flattenLiterals(clause2, bfmgr); + List combined = new ArrayList<>(); + + boolean removed = false; + + for (BooleanFormula lit : literals1) { + if (!isComplement(lit, pivot, bfmgr)) { + combined.add(lit); + } + } + + List temp = new ArrayList<>(); + boolean removed2 = false; + for (BooleanFormula lit : literals2) { + if (!isComplement(lit, pivot, bfmgr)) { + temp.add(lit); + } + } + + combined.addAll(temp); + + if (combined.isEmpty()) { + return bfmgr.makeFalse(); + } else if (combined.size() == 1) { + return combined.get(0); + } else { + return bfmgr.or(combined); + } + } + + // Helper method to flatten an OR/AND-formula into a list of disjunctive literals + private List flattenLiterals( + BooleanFormula formula, BooleanFormulaManager bfmgr) { + List result = new ArrayList<>(); + + bfmgr.visit( + formula, + new BooleanFormulaVisitor<>() { + @Override + public TraversalProcess visitOr(List operands) { + for (BooleanFormula op : operands) { + result.addAll(flattenLiterals(op, bfmgr)); + } + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitAnd(List operands) { + for (BooleanFormula op : operands) { + result.addAll(flattenLiterals(op, bfmgr)); + } + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitNot(BooleanFormula operand) { + result.add(formula); // add original NOT node + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitAtom( + BooleanFormula atom, FunctionDeclaration decl) { + result.add(formula); // add original atom + return TraversalProcess.SKIP; + } + + // others unchanged... + @Override + public TraversalProcess visitXor(BooleanFormula a, BooleanFormula b) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitEquivalence(BooleanFormula a, BooleanFormula b) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitImplication(BooleanFormula a, BooleanFormula b) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitIfThenElse( + BooleanFormula c, BooleanFormula t, BooleanFormula e) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitQuantifier( + Quantifier q, BooleanFormula qBody, List vars, BooleanFormula body) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitConstant(boolean value) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitBoundVar(BooleanFormula var, int index) { + return TraversalProcess.SKIP; + } + }); + + return result; + } + + // Check whether two formulas are logical complements + private boolean isComplement(BooleanFormula a, BooleanFormula b, BooleanFormulaManager bfmgr) { + // Define the visitor to check for complement relation + final boolean[] isComplement = {false}; + + bfmgr.visitRecursively( + a, + new BooleanFormulaVisitor<>() { + @Override + public TraversalProcess visitNot(BooleanFormula operand) { + // Check if the negation of 'operand' equals 'b' + if (operand.equals(b)) { + isComplement[0] = true; + } + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitAtom( + BooleanFormula atom, FunctionDeclaration decl) { + if (atom.equals(b)) { + isComplement[0] = true; + } + return TraversalProcess.SKIP; + } + + // Default implementation for other nodes, such as OR, AND, etc. + @Override + public TraversalProcess visitOr(List operands) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitAnd(List operands) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitXor(BooleanFormula a, BooleanFormula b) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitEquivalence(BooleanFormula a, BooleanFormula b) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitImplication(BooleanFormula a, BooleanFormula b) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitIfThenElse( + BooleanFormula c, BooleanFormula t, BooleanFormula e) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitQuantifier( + Quantifier q, BooleanFormula qBody, List vars, BooleanFormula body) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitConstant(boolean value) { + return TraversalProcess.SKIP; + } + + @Override + public TraversalProcess visitBoundVar(BooleanFormula var, int index) { + return TraversalProcess.SKIP; + } + }); + + return isComplement[0]; + } } diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java deleted file mode 100644 index 88364c2f3c..0000000000 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofNodeCreator.java +++ /dev/null @@ -1,353 +0,0 @@ -/* - * This file is part of JavaSMT, - * an API wrapper for a collection of SMT solvers: - * https://github.com/sosy-lab/java-smt - * - * SPDX-FileCopyrightText: 2024 Dirk Beyer - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.sosy_lab.java_smt.solvers.smtinterpol; - -import de.uni_freiburg.informatik.ultimate.logic.AnnotatedTerm; -import de.uni_freiburg.informatik.ultimate.logic.Annotation; -import de.uni_freiburg.informatik.ultimate.logic.ApplicationTerm; -import de.uni_freiburg.informatik.ultimate.logic.Sort; -import de.uni_freiburg.informatik.ultimate.logic.Term; -import de.uni_freiburg.informatik.ultimate.logic.Util; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Deque; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import org.sosy_lab.java_smt.ResProofRule; -import org.sosy_lab.java_smt.ResProofRule.ResAxiom; -import org.sosy_lab.java_smt.api.proofs.ProofFrame; -import org.sosy_lab.java_smt.api.proofs.ProofNode; -import org.sosy_lab.java_smt.api.proofs.ProofRule; - -// SMTInterpol gives back a Term (apparently) only of instance ApplicationTerm or AnnotatedTerm, -// so the other instances are not needed. - -@SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access", "ModifiedButNotUsed"}) -class SmtInterpolProofNodeCreator { - private final SmtInterpolFormulaCreator creator; - private final SmtInterpolTheoremProver prover; - private Map computed = new ConcurrentHashMap<>(); - private Deque stack = new ArrayDeque<>(); - - SmtInterpolProofNodeCreator( - SmtInterpolFormulaCreator pCreator, SmtInterpolTheoremProver pProver) { - creator = pCreator; - prover = pProver; - } - - private enum Rup implements ProofRule { - RUP; - - @Override - public String getName() { - return "rup"; - } - } - - private static class SmtTermFrame extends ProofFrame { - List children = new ArrayList<>(); - - public SmtTermFrame(Term term) { - super(term); - } - } - - ProofNode fromTerm(Term rootProof) { - - Deque stack = new ArrayDeque<>(); - - Map computed = new HashMap<>(); - - stack.push(new ProvitionalProofNode(rootProof)); - - while (!stack.isEmpty()) { - ProvitionalProofNode frame = stack.peek(); - - if (!frame.isVisited) { - - frame.isVisited = true; - // numChildren - 1 iterations - for (int i = 10 - 1; i >= 0; i--) { - // Proof child = rootProof.getChildren()[i]; - // !Computed.containsKey(child) - if (true) { - // stack.push(new Frame(child)); - } - } - } else { - - stack.pop(); - int numChildren = frame.children.size(); - - // ProofRule proofRule = - // new source node or resolution node - for (int i = 0; i < numChildren - 1; i++) { - // Proof child = frame.getProof().getChildren()[i]; - - // if (computed.containsKey(child)) { - if (true) { - // pn.addChild(computed.get(child)); - } - } - // computed.put(frame.proof, pn); - } - } - return null; - } - - ProvitionalProofNode createPPNDag(Term proof) { - try { - ProvitionalProofNode root = new ProvitionalProofNode(proof); - root.buildDag(proof); - return root; - } finally { - stack.clear(); - computed.clear(); - } - } - - class ProvitionalProofNode { - Term pivot; - ProofRule proofRule; - List formulas = new ArrayList<>(); - boolean axiom; - List children = new ArrayList<>(); - Term unprocessedTerm; - boolean isVisited = false; - - public ProvitionalProofNode(Term pParameter) { - this.unprocessedTerm = pParameter; - // processTerm(pParameter); - } - - void buildDag(Term term) { - - stack.push(new SmtTermFrame(term)); - - while (!stack.isEmpty()) { - SmtTermFrame frame = stack.peek(); - - if (!frame.isVisited()) { - frame.setAsVisited(true); - processTerm(frame); - } else { - - stack.pop(); - - for (int i = 0; i < frame.children.size(); i++) { - Term child = frame.children.get(i).getProof(); - ProvitionalProofNode childNode = computed.get(child); - this.children.add(childNode); - } - } - } - } - - void processTerm(SmtTermFrame frame) { - Term pParameter = frame.getProof(); - - if (pParameter instanceof ApplicationTerm) { - processApplication(frame); - } else if (pParameter instanceof AnnotatedTerm) { - processAnnotated(frame); - } - } - - void processApplication(SmtTermFrame frame) { - ApplicationTerm term = (ApplicationTerm) frame.getProof(); - Term[] parameters = term.getParameters(); - if (parameters.length == 3) { - this.proofRule = ResAxiom.RESOLUTION; - // This should be a resolution rule - Term first = parameters[0]; - if (first instanceof AnnotatedTerm) { - pivot = ((AnnotatedTerm) first).getSubterm(); - } else if (first instanceof ApplicationTerm) { - pivot = first; - } - - for (int i = parameters.length - 1; i > 0; i--) { - Sort sort = term.getSort(); - if (sort.toString().equals("..Proof")) { - // children.add(new ProvitionalProofNode(parameters[i])); - frame.setNumArgs(parameters.length - 1); - if (!computed.containsKey(parameters[i])) { - SmtTermFrame childFrame = new SmtTermFrame(parameters[i]); - stack.push(childFrame); - frame.children.add(childFrame); - // children.add(new ProvitionalProofNode(parameters[i])); - computed.put(parameters[i], new ProvitionalProofNode(parameters[i])); - } - } - } - } - - if (term.getFunction().toString().contains("..assume")) { - // This should be the assume axiom - this.axiom = true; - this.proofRule = ResAxiom.ASSUME; - if (parameters[0] instanceof AnnotatedTerm) { - this.formulas.add(((AnnotatedTerm) parameters[0]).getSubterm()); - } else { - this.formulas.add(parameters[0]); - } - } - } - - private void processAnnotated(SmtTermFrame frame) { - AnnotatedTerm term = (AnnotatedTerm) frame.getProof(); - boolean rup = false; - - if (term.getSort().toString().equals("Bool")) { - if (this.axiom) { - this.pivot = term.getSubterm(); - } else { - this.formulas.add(term.getSubterm()); - } - } - - for (Annotation annotation : term.getAnnotations()) { - ResAxiom rule; - String key = annotation.getKey().substring(1); - - if (term.getSubterm().toString().equals("..axiom")) { - this.axiom = true; - // Annotation key should contain axiom name and value should contain an array with some - // of its objects being Terms and the index before each one of those contains the - // polarity. - key = key.startsWith(":") ? key.substring(1) : key; - - rule = ResProofRule.getFromName(key); - - this.proofRule = rule; - // This Annotation's value should have an array with the polarities and Terms that are - // proven. This is the clause proven the ApplicationTerm. The array is empty for the - // very first Term. - // Now we need to go through the array and find the Term objects and their polarity. - // This is the same for proves. - if (annotation.getValue() instanceof Object[]) { - Object[] values = (Object[]) annotation.getValue(); - addTermsFromAnnotationValue(values, false); - } else if (annotation.getValue() instanceof AnnotatedTerm) { - frame.setProof((AnnotatedTerm) annotation.getValue()); - processAnnotated(frame); - } else if (annotation.getValue() instanceof ApplicationTerm) { - formulas.add((Term) annotation.getValue()); - } - } - - if (key.equals("rup")) { - this.proofRule = Rup.RUP; - // this.children.add(new ProvitionalProofNode(term.getSubterm())); - frame.setNumArgs(1); - if (!computed.containsKey(term.getSubterm())) { - SmtTermFrame childFrame = new SmtTermFrame(term.getSubterm()); - stack.push(childFrame); - frame.children.add(childFrame); - // children.add(new ProvitionalProofNode(term.getSubterm())); - // computed.put(term, this); - computed.put(term.getSubterm(), new ProvitionalProofNode(term.getSubterm())); - } - rup = true; - } - - if (key.equals("proves")) { - Object[] values = (Object[]) annotation.getValue(); - addTermsFromAnnotationValue(values, true); - } - } - if (!rup) { - frame.setProof(term.getSubterm()); - processTerm(frame); - } - } - - void addTermsFromAnnotationValue(Object[] values, boolean isProves) { - for (int i = 0; values.length > i; i++) { - if (values[i] instanceof Term) { - // We found a Term and the index before it should contain the polarity, but only if - // this is the value of the proves Annotation. - if (isProves) { - assert values[i - 1].getClass() == String.class; - if (((String) values[i - 1]).contains("+")) { - this.formulas.add((Term) values[i]); - } else { - // We try to create the negative polarity Term - this.formulas.add(Util.not(creator.getEnv(), (Term) values[i])); - } - } else { - this.formulas.add((Term) values[i]); - } - } - } - } - - public String asString() { - return asString(0); - } - - String asString(int indentLevel) { - StringBuilder sb = new StringBuilder(); - String indent = " ".repeat(indentLevel); - - // Node header - sb.append(indent).append("ProofNode {\n"); - - // Node properties - sb.append(indent).append(" pivot: ").append(pivot != null ? pivot : "null").append("\n"); - sb.append(indent) - .append(" proofRule: ") - .append(proofRule != null ? proofRule.getName() : "null") - .append("\n"); - sb.append(indent).append(" axiom: ").append(axiom).append("\n"); - sb.append(indent).append(" isVisited: ").append(isVisited).append("\n"); - - // Formulas - sb.append(indent).append(" formulas: [\n"); - if (formulas.isEmpty()) { - sb.append(indent).append(" empty\n"); - } else { - for (Term formula : formulas) { - sb.append(indent).append(" ").append(formula != null ? formula : "null").append("\n"); - } - } - sb.append(indent).append(" ]\n"); - - // Unprocessed term - sb.append(indent) - .append(" unprocessedTerm: ") - .append(unprocessedTerm != null ? unprocessedTerm : "null") - .append("\n"); - - // Children nodes - sb.append(indent).append(" children: [\n"); - if (children.isEmpty()) { - sb.append(indent).append(" empty\n"); - } else { - for (ProvitionalProofNode child : children) { - if (child != null) { - sb.append(child.asString(indentLevel + 2)); - } else { - sb.append(indent).append(" null\n"); - } - } - } - sb.append(indent).append(" ]\n"); - - // Close node - sb.append(indent).append("}\n"); - - return sb.toString(); - } - } -} diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java index fd3474f096..eff0e591fb 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java @@ -31,9 +31,11 @@ import org.sosy_lab.common.configuration.InvalidConfigurationException; import org.sosy_lab.common.log.BasicLogManager; import org.sosy_lab.common.log.LogManager; +import org.sosy_lab.java_smt.ProofPrettyPrinter; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; +import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.AbstractNumeralFormulaManager.NonLinearArithmetic; @SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) @@ -92,13 +94,13 @@ public void testGetProofTerm() throws SolverException, InterruptedException { prover.addConstraint(q2False); assertThat(prover.isUnsat()).isTrue(); - Term proof = prover.smtInterpolGetProof(); + ProofNode proof = prover.getProof(); assertThat(proof).isNotNull(); - // String proofStr = proof.toString(); - // System.out.println(proofStr); + ProofPrettyPrinter pp = new ProofPrettyPrinter(); + + pp.prettyPrint(proof); - processTerm(proof); } finally { prover.close(); } @@ -289,11 +291,13 @@ public void testPPN() { // String proofStr = proof.toString(); // System.out.println(proofStr); - SmtInterpolProofNodeCreator pc = - new SmtInterpolProofNodeCreator( + NonRecursiveSmtInterpolCreator pc = + new NonRecursiveSmtInterpolCreator( (SmtInterpolFormulaCreator) prover.mgr.getFormulaCreator(), prover); - - assertThat(pc.createPPNDag(proof)).isNotNull(); + // SmtInterpolProofNodeCreator pc = + // new SmtInterpolProofNodeCreator((SmtInterpolFormulaCreator) prover.mgr + // .getFormulaCreator(), prover); + // assertThat(pc.createPPNDag(proof)).isNotNull(); System.out.println(pc.createPPNDag(proof).asString()); From fa3cfb4a47b72014e3e73003817ce90701e5a4f9 Mon Sep 17 00:00:00 2001 From: gcarpio21 Date: Fri, 2 May 2025 14:14:04 +0200 Subject: [PATCH 086/132] Delete src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java Deleted a class that was not needed --- .../smtinterpol/SmtInterpolProofsTest.java | 310 ------------------ 1 file changed, 310 deletions(-) delete mode 100644 src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java deleted file mode 100644 index eff0e591fb..0000000000 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProofsTest.java +++ /dev/null @@ -1,310 +0,0 @@ -/* - * This file is part of JavaSMT, - * an API wrapper for a collection of SMT solvers: - * https://github.com/sosy-lab/java-smt - * - * SPDX-FileCopyrightText: 2024 Dirk Beyer - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.sosy_lab.java_smt.solvers.smtinterpol; - -import static com.google.common.truth.Truth.assertThat; - -import de.uni_freiburg.informatik.ultimate.logic.AnnotatedTerm; -import de.uni_freiburg.informatik.ultimate.logic.ApplicationTerm; -import de.uni_freiburg.informatik.ultimate.logic.ConstantTerm; -import de.uni_freiburg.informatik.ultimate.logic.LambdaTerm; -import de.uni_freiburg.informatik.ultimate.logic.LetTerm; -import de.uni_freiburg.informatik.ultimate.logic.MatchTerm; -import de.uni_freiburg.informatik.ultimate.logic.QuantifiedFormula; -import de.uni_freiburg.informatik.ultimate.logic.Term; -import de.uni_freiburg.informatik.ultimate.logic.TermVariable; -import java.util.Set; -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.sosy_lab.common.ShutdownManager; -import org.sosy_lab.common.configuration.Configuration; -import org.sosy_lab.common.configuration.InvalidConfigurationException; -import org.sosy_lab.common.log.BasicLogManager; -import org.sosy_lab.common.log.LogManager; -import org.sosy_lab.java_smt.ProofPrettyPrinter; -import org.sosy_lab.java_smt.api.BooleanFormula; -import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; -import org.sosy_lab.java_smt.api.SolverException; -import org.sosy_lab.java_smt.api.proofs.ProofNode; -import org.sosy_lab.java_smt.basicimpl.AbstractNumeralFormulaManager.NonLinearArithmetic; - -@SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) -@Ignore("prevent this class being executed as testcase by ant") -public class SmtInterpolProofsTest { - - private SmtInterpolSolverContext context; - private SmtInterpolFormulaManager mgr; - private SmtInterpolBooleanFormulaManager bmgr; - private SmtInterpolIntegerFormulaManager imgr; - - @Before - public void setupSolver() throws InvalidConfigurationException { - Configuration config = Configuration.defaultConfiguration(); - LogManager logger = BasicLogManager.create(config); - ShutdownManager shutdown = ShutdownManager.create(); - - // Create new context with SMTInterpol - context = - SmtInterpolSolverContext.create( - config, - logger, - shutdown.getNotifier(), - null, // no logfile - 42, // randomSeed - NonLinearArithmetic.USE); - - // Get managers for creating formulas - mgr = (SmtInterpolFormulaManager) context.getFormulaManager(); - bmgr = (SmtInterpolBooleanFormulaManager) mgr.getBooleanFormulaManager(); - imgr = (SmtInterpolIntegerFormulaManager) mgr.getIntegerFormulaManager(); - } - - @After - public void closeSolver() { - if (context != null) { - context.close(); - } - } - - @Test - public void testGetProofTerm() throws SolverException, InterruptedException { - // example from the 2022 paper - BooleanFormula q1 = bmgr.makeVariable("q1"); - BooleanFormula q2 = bmgr.makeVariable("q2"); - BooleanFormula notQ1OrQ2 = bmgr.or(bmgr.not(q1), q2); - BooleanFormula q1True = bmgr.equivalence(q1, bmgr.makeTrue()); - BooleanFormula q2False = bmgr.equivalence(q2, bmgr.makeFalse()); - - SmtInterpolTheoremProver prover = - (SmtInterpolTheoremProver) - context.newProverEnvironment0(Set.of(ProverOptions.GENERATE_PROOFS)); - try { - prover.addConstraint(notQ1OrQ2); - prover.addConstraint(q1True); - prover.addConstraint(q2False); - assertThat(prover.isUnsat()).isTrue(); - - ProofNode proof = prover.getProof(); - assertThat(proof).isNotNull(); - - ProofPrettyPrinter pp = new ProofPrettyPrinter(); - - pp.prettyPrint(proof); - - } finally { - prover.close(); - } - } - - private int indentLevel = 0; - - private void printIndented(String message) { - System.out.println(" ".repeat(indentLevel * 2) + message); - } - - void processTerm(Term term) { - printIndented("Processing term: " + term.getClass().getSimpleName()); - if (term instanceof ApplicationTerm) { - processAppTerm((ApplicationTerm) term); - } else if (term instanceof AnnotatedTerm) { - processAnnotatedTerm((AnnotatedTerm) term); - } else if (term instanceof LetTerm) { - processLetTerm((LetTerm) term); - } else if (term instanceof ConstantTerm) { - processConstTerm((ConstantTerm) term); - } else if (term instanceof LambdaTerm) { - processLambdaTerm((LambdaTerm) term); - } else if (term instanceof MatchTerm) { - processMatchTerm((MatchTerm) term); - } else if (term instanceof QuantifiedFormula) { - processQuantifiedFormula((QuantifiedFormula) term); - } else if (term instanceof TermVariable) { - processTermVariable((TermVariable) term); - } else { - printIndented("Unknown term type: " + term.getClass()); - } - } - - private void processTermVariable(TermVariable term) { - printIndented("TermVariable: " + term.toString()); - indentLevel++; - printIndented("Sort: " + term.getSort().toString()); - printIndented("Declared Sort: " + term.getDeclaredSort().toString()); - printIndented("Name: " + term.getName()); - indentLevel--; - } - - private void processQuantifiedFormula(QuantifiedFormula term) { - printIndented("QuantifiedFormula: " + term.toString()); - indentLevel++; - printIndented("Sort: " + term.getSort().toString()); - printIndented("Quantifier: " + term.getQuantifier()); - printIndented("Subformula: " + term.getSubformula().toString()); - for (int i = 0; i < term.getVariables().length; i++) { - printIndented("Variable " + i + ": " + term.getVariables()[i]); - processTerm(term.getVariables()[i]); - } - indentLevel--; - } - - private void processMatchTerm(MatchTerm term) { - printIndented("MatchTerm: " + term.toString()); - indentLevel++; - printIndented("Sort: " + term.getSort().toString()); - printIndented("DataTerm: " + term.getDataTerm().toString()); - for (int i = 0; i < term.getVariables().length; i++) { - for (int j = 0; j < term.getVariables()[i].length; j++) { - printIndented("Variable " + i + " " + j + ": " + term.getVariables()[i][j]); - processTerm(term.getVariables()[i][j]); - } - } - for (int i = 0; i < term.getCases().length; i++) { - printIndented("Case " + i + ": " + term.getCases()[i]); - processTerm(term.getCases()[i]); - } - for (int i = 0; i < term.getConstructors().length; i++) { - printIndented("Constructor " + i + ": " + term.getConstructors()[i].toString()); - } - indentLevel--; - } - - private void processLambdaTerm(LambdaTerm term) { - printIndented("LambdaTerm: " + term.toString()); - indentLevel++; - printIndented("Sort: " + term.getSort().toString()); - printIndented("Subterm: " + term.getSubterm().toString()); - for (int i = 0; i < term.getVariables().length; i++) { - printIndented("Variable " + i + ": " + term.getVariables()[i]); - processTerm(term.getVariables()[i]); - } - printIndented("Subterm will be processed"); - processTerm(term.getSubterm()); - indentLevel--; - } - - private void processConstTerm(ConstantTerm term) { - printIndented("ConstantTerm: " + term.toString()); - indentLevel++; - printIndented("Sort: " + term.getSort().toString()); - printIndented("Value: " + term.getValue()); - if (term.getValue() instanceof Term) { - printIndented("Value is a term"); - processTerm((Term) term.getValue()); - } - indentLevel--; - } - - private void processLetTerm(LetTerm term) { - printIndented("LetTerm: " + term.toString()); - indentLevel++; - printIndented("Sort: " + term.getSort().toString()); - printIndented("Subterm: " + term.getSubTerm().toString()); - for (int i = 0; i < term.getValues().length; i++) { - printIndented("value " + i + ": " + term.getValues()[i]); - processTerm(term.getValues()[i]); - } - for (int i = 0; i < term.getVariables().length; i++) { - printIndented("variable " + i + ": " + term.getVariables()[i]); - processTerm(term.getVariables()[i]); - } - printIndented("Subterm will be processed"); - processTerm(term.getSubTerm()); - indentLevel--; - } - - private void processAnnotatedTerm(AnnotatedTerm term) { - printIndented("AnnotatedTerm: " + term.toString()); - indentLevel++; - printIndented("Sort: " + term.getSort().toString()); - printIndented("Subterm: " + term.getSubterm().toString()); - for (int i = 0; i < term.getFreeVars().length; i++) { - printIndented("Free Variable " + i + ": " + term.getFreeVars()[i]); - processTerm(term.getFreeVars()[i]); - } - for (int i = 0; i < term.getAnnotations().length; i++) { - printIndented("Annotation " + i + ": " + term.getAnnotations()[i]); - printIndented("Key: " + term.getAnnotations()[i].getKey()); - Object value = term.getAnnotations()[i].getValue(); - if (value != null) { - printIndented("Value: " + value); - printIndented("value class: " + value.getClass()); - if (value instanceof Object[]) { - Object[] valueArray = (Object[]) value; - for (Object element : valueArray) { - // Process each element in the array - printIndented("Array element: " + element); - printIndented("element class: " + element.getClass()); - } - } - } - } - printIndented("Subterm will be processed"); - processTerm(term.getSubterm()); - indentLevel--; - } - - private void processAppTerm(ApplicationTerm term) { - printIndented("ApplicationTerm: " + term.toString()); - indentLevel++; - printIndented("Function Symbol: " + term.getFunction().toString()); - Term[] parameters = term.getParameters(); - printIndented("Sort: " + term.getSort().toString()); - printIndented("Parameters: " + parameters.length); - for (int i = 0; i < parameters.length; i++) { - printIndented("Parameter " + i + ": " + parameters[i]); - processTerm(parameters[i]); - } - indentLevel--; - } - - @Test - public void testPPN() { - // example from the 2022 paper - BooleanFormula q1 = bmgr.makeVariable("q1"); - BooleanFormula q2 = bmgr.makeVariable("q2"); - BooleanFormula notQ1OrQ2 = bmgr.or(bmgr.not(q1), q2); - BooleanFormula q1True = bmgr.equivalence(q1, bmgr.makeTrue()); - BooleanFormula q2False = bmgr.equivalence(q2, bmgr.makeFalse()); - - SmtInterpolTheoremProver prover = - (SmtInterpolTheoremProver) - context.newProverEnvironment0(Set.of(ProverOptions.GENERATE_PROOFS)); - try { - prover.addConstraint(notQ1OrQ2); - prover.addConstraint(q1True); - prover.addConstraint(q2False); - assertThat(prover.isUnsat()).isTrue(); - - Term proof = prover.smtInterpolGetProof(); - assertThat(proof).isNotNull(); - - // String proofStr = proof.toString(); - // System.out.println(proofStr); - - NonRecursiveSmtInterpolCreator pc = - new NonRecursiveSmtInterpolCreator( - (SmtInterpolFormulaCreator) prover.mgr.getFormulaCreator(), prover); - // SmtInterpolProofNodeCreator pc = - // new SmtInterpolProofNodeCreator((SmtInterpolFormulaCreator) prover.mgr - // .getFormulaCreator(), prover); - // assertThat(pc.createPPNDag(proof)).isNotNull(); - - System.out.println(pc.createPPNDag(proof).asString()); - - } catch (InterruptedException pE) { - throw new RuntimeException(pE); - } finally { - prover.close(); - } - } -} From 5375cf4a1d52b09c36545323e27f4cf745e24b1e Mon Sep 17 00:00:00 2001 From: gcarpio21 Date: Fri, 2 May 2025 14:29:50 +0200 Subject: [PATCH 087/132] Delete src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java Delete class that is not needed --- .../java_smt/solvers/z3/Z3ProofsTest.java | 129 ------------------ 1 file changed, 129 deletions(-) delete mode 100644 src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java deleted file mode 100644 index cb6a447c8d..0000000000 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofsTest.java +++ /dev/null @@ -1,129 +0,0 @@ -package org.sosy_lab.java_smt.solvers.z3; - -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertTrue; - -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.sosy_lab.common.ShutdownManager; -import org.sosy_lab.common.configuration.Configuration; -import org.sosy_lab.common.log.BasicLogManager; -import org.sosy_lab.common.log.LogManager; -import org.sosy_lab.java_smt.SolverContextFactory; -import org.sosy_lab.java_smt.api.BooleanFormula; -import org.sosy_lab.java_smt.api.ProverEnvironment; -import org.sosy_lab.java_smt.api.SolverContext; -import org.sosy_lab.java_smt.api.SolverException; -import org.sosy_lab.java_smt.api.proofs.ProofNode; - -@SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) -@Ignore("prevent this class being executed as testcase by ant") -public class Z3ProofsTest { - - private SolverContext context; - private Z3FormulaManager mgr; - private Z3BooleanFormulaManager bmgr; - private ProverEnvironment q1q2prover; - - @Before - public void setUpSolverContext() throws Exception { - // Z3 requires to enable proof generation in the configuration of the context - Configuration config = - Configuration.builder().setOption("solver.z3.requireProofs", "true").build(); - LogManager logger = BasicLogManager.create(config); - ShutdownManager shutdown = ShutdownManager.create(); - - context = - SolverContextFactory.createSolverContext( - config, logger, shutdown.getNotifier(), SolverContextFactory.Solvers.Z3); - - mgr = (Z3FormulaManager) context.getFormulaManager(); - bmgr = (Z3BooleanFormulaManager) mgr.getBooleanFormulaManager(); - } - - @Before - public void setUpQ1Q2Prover() throws InterruptedException { - // (declare-fun q1 () Bool) - // (declare-fun q2 () Bool) - // (assert (or (not q1) q2)) - // (assert q1) - // (assert (not q2)) - // (check-sat) - // (get-proof) - // This problem is from the paper found in - // https://ultimate.informatik.uni-freiburg.de/smtinterpol/proofs.html - BooleanFormula q1 = bmgr.makeVariable("q1"); - BooleanFormula q2 = bmgr.makeVariable("q2"); - - q1q2prover = context.newProverEnvironment(); - - try { - q1q2prover.addConstraint(bmgr.or(bmgr.not(q1), q2)); - q1q2prover.addConstraint(q1); - q1q2prover.addConstraint(bmgr.not(q2)); - assertTrue(q1q2prover.isUnsat()); - - } catch (SolverException pE) { - throw new RuntimeException(pE); - } - } - - @After - public void closeSolver() { - if (context != null) { - context.close(); - } - } - - @Test - public void getProofTest() throws InterruptedException, SolverException { - ProofNode proof = q1q2prover.getProof(); - assertThat(proof).isNotNull(); - } - - @Test - public void getChildrenTest() throws SolverException, InterruptedException { - ProofNode proof = q1q2prover.getProof(); - assertThat(proof).isNotNull(); - assertThat(proof.getChildren()).isNotEmpty(); - assertThat(proof.getChildren().get(0)).isNotNull(); - } - - @Test - public void getProofRuleTest() throws SolverException, InterruptedException { - ProofNode proof = q1q2prover.getProof(); - assertThat(proof).isNotNull(); - assertThat(proof.getRule()).isNotNull(); - assertThat(proof.getRule()).isEqualTo(Z3ProofRule.UNIT_RESOLUTION); - } - - @Test - public void getFormulaTest() throws SolverException, InterruptedException { - ProofNode proof = q1q2prover.getProof(); - assertThat(proof).isNotNull(); - assertThat(proof.getFormula()).isNotNull(); - assertThat(proof.getFormula()).isEqualTo(bmgr.makeFalse()); - } - - @Test - public void Z3handleTransitivityTest() { - BooleanFormula f1 = bmgr.makeVariable("f1"); - BooleanFormula f2 = bmgr.makeVariable("f2"); - BooleanFormula f3 = bmgr.makeVariable("f3"); - BooleanFormula equiv1 = bmgr.equivalence(f1, f2); - BooleanFormula equiv2 = bmgr.equivalence(f2, f3); - BooleanFormula equiv3 = bmgr.equivalence(f1, f3); - - Z3ProofDAG.Z3ProofNode pn = new Z3ProofDAG.Z3ProofNode(equiv3, Z3ProofRule.TRANSITIVITY); - pn.addChild(new Z3ProofDAG.Z3ProofNode(equiv1, Z3ProofRule.ASSERTED)); - pn.addChild(new Z3ProofDAG.Z3ProofNode(equiv2, Z3ProofRule.ASSERTED)); - - Z3ToResolutionProofConverter pc = new Z3ToResolutionProofConverter(mgr); - - ProofNode res = pc.handleTransitivity(pn); - - assertThat(res).isNotNull(); - } -} From 24f4ddff11c63e2b1dfc147438fb31de45532308 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 2 May 2025 17:53:01 +0200 Subject: [PATCH 088/132] Corrected multiple warnings to be able to build. --- src/org/sosy_lab/java_smt/ResProofRule.java | 5 +- .../java_smt/api/BasicProverEnvironment.java | 5 +- .../java_smt/api/proofs/ProofDAG.java | 10 +-- .../java_smt/basicimpl/AbstractProver.java | 8 +++ .../solvers/mathsat5/Mathsat5ProofNode.java | 6 +- .../mathsat5/Mathsat5TheoremProver.java | 25 +++---- .../princess/PrincessAbstractProver.java | 16 ++--- .../smtinterpol/SmtInteprolProofDAG.java | 8 +-- .../SmtInterpolAbstractProver.java | 26 +++---- .../java_smt/solvers/z3/Z3ProofDAG.java | 10 +-- .../z3/Z3ToResolutionProofConverter.java | 72 +++++++++---------- .../java_smt/test/ProverEnvironmentTest.java | 1 - 12 files changed, 95 insertions(+), 97 deletions(-) diff --git a/src/org/sosy_lab/java_smt/ResProofRule.java b/src/org/sosy_lab/java_smt/ResProofRule.java index ab4d00a3ad..5218f3bff0 100644 --- a/src/org/sosy_lab/java_smt/ResProofRule.java +++ b/src/org/sosy_lab/java_smt/ResProofRule.java @@ -11,6 +11,7 @@ package org.sosy_lab.java_smt; import java.util.HashMap; +import java.util.Locale; import java.util.Map; import org.sosy_lab.java_smt.api.proofs.ProofRule; @@ -29,7 +30,7 @@ public class ResProofRule { static { for (ResAxiom rule : ResAxiom.values()) { - RULE_MAP.put(rule.getName().toLowerCase(), rule); + RULE_MAP.put(rule.getName().toLowerCase(Locale.ROOT), rule); } } @@ -146,7 +147,7 @@ public String getFormula() { */ public static ResAxiom getFromName(String name) { - ResAxiom rule = RULE_MAP.get(name.toLowerCase()); + ResAxiom rule = RULE_MAP.get(name.toLowerCase(Locale.ROOT)); if (rule == null) { throw new IllegalArgumentException("Rule not found or not specified: " + name); } diff --git a/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java b/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java index a2915f40fd..a327d0df50 100644 --- a/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java @@ -154,10 +154,7 @@ default ImmutableMap getStatistics() { * Get proof of unsatisfiability of the conjuction of the current satck of all formulas. Should * only be called after {@link #isUnsat()} returned true. */ - default ProofNode getProof() throws SolverException, InterruptedException { - throw new UnsupportedOperationException( - "Proof generation is not available for the current solver."); - } + ProofNode getProof() throws SolverException, InterruptedException; /** * Closes the prover environment. The object should be discarded, and should not be used after diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java b/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java index 76fd4df922..b0ba85b4dd 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java @@ -22,23 +22,23 @@ public interface ProofDAG { /** * Add a node to the DAG. * - * @param node + * @param node The node to be added to the DAG. */ void addNode(ProofNode node); /** * Get a node from the DAG. * - * @param nodeId - * @return + * @param nodeId The ID of the node. + * @return A {@link ProofNode} based on its ID. */ ProofNode getNode(int nodeId); /** * Add an edge to the DAG. * - * @param parentNodeId - * @param childNodeId + * @param parentNodeId Predecessor + * @param childNodeId Successor */ void addEdge(int parentNodeId, int childNodeId); diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java index baa7dc07d1..ebc0f4f9c2 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java @@ -26,6 +26,8 @@ import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.Evaluator; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; +import org.sosy_lab.java_smt.api.SolverException; +import org.sosy_lab.java_smt.api.proofs.ProofNode; public abstract class AbstractProver implements BasicProverEnvironment { @@ -164,4 +166,10 @@ public void close() { closeAllEvaluators(); closed = true; } + + @Override + public ProofNode getProof() throws InterruptedException, SolverException { + throw new UnsupportedOperationException( + "Proof generation is not available for the current solver."); + } } diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java index 6c020aae3b..4b8b71fe10 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java @@ -21,6 +21,7 @@ import java.util.ArrayDeque; import java.util.Deque; import java.util.HashMap; +import java.util.Locale; import java.util.Map; import javax.annotation.Nullable; import org.sosy_lab.java_smt.api.Formula; @@ -106,7 +107,10 @@ public static Mathsat5ProofNode fromMsatProof(ProverEnvironment pProver, long ro // If the theory-lemma rule includes a last argument that is not a term, it means it has // a proof attached to it. Not all rules are known beforehand so they are not in the enum. try { - proofRule = rule == null ? Rule.NULL : Rule.valueOf(rule.toUpperCase().replace("-", "_")); + proofRule = + rule == null + ? Rule.NULL + : Rule.valueOf(rule.toUpperCase(Locale.ROOT).replace("-", "_")); } catch (IllegalArgumentException e) { proofRule = new Mathsat5ProofRule(rule); } diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java index 435329935f..4db022c707 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java @@ -15,12 +15,13 @@ import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_get_proof_manager; import com.google.common.base.Preconditions; +import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Deque; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.Stack; import org.checkerframework.checker.nullness.qual.Nullable; import org.sosy_lab.common.ShutdownNotifier; import org.sosy_lab.java_smt.api.BooleanFormula; @@ -70,7 +71,6 @@ public ProofNode getProof() throws SolverException, InterruptedException { long pm = msat_get_proof_manager(curEnv); long proof = msat_get_proof(pm); pn = Mathsat5ProofNode.fromMsatProof(this, proof); - context.getFormulaManager().getBooleanFormulaManager(); clausifyResChain(pn, context.getFormulaManager().getBooleanFormulaManager()); msat_destroy_proof_manager(pm); @@ -83,9 +83,7 @@ public ProofNode getProof() throws SolverException, InterruptedException { // formulas and return the updated root node with formulas attached. private void clausifyResChain(ProofNode root, BooleanFormulaManager bfmgr) { Map visited = new HashMap<>(); // Track visited nodes - Stack stack = new Stack<>(); - Stack processStack = - new Stack<>(); // Stack to hold nodes for post-processing after children + Deque stack = new ArrayDeque<>(); stack.push(root); // Start with the root node visited.put(root, Boolean.FALSE); // Mark root as unvisited @@ -93,7 +91,7 @@ private void clausifyResChain(ProofNode root, BooleanFormulaManager bfmgr) { while (!stack.isEmpty()) { ProofNode node = stack.peek(); // Look at the top node, but don't pop yet - if (visited.get(node) == Boolean.FALSE) { + if (visited.get(node).equals(Boolean.FALSE)) { // First time visiting this node visited.put(node, Boolean.TRUE); // Mark node as visited @@ -155,8 +153,6 @@ private BooleanFormula resolve( List literals2 = flattenLiterals(clause2, bfmgr); List combined = new ArrayList<>(); - boolean removed = false; - for (BooleanFormula lit : literals1) { if (!isComplement(lit, pivot, bfmgr)) { combined.add(lit); @@ -164,7 +160,6 @@ private BooleanFormula resolve( } List temp = new ArrayList<>(); - boolean removed2 = false; for (BooleanFormula lit : literals2) { if (!isComplement(lit, pivot, bfmgr)) { temp.add(lit); @@ -221,17 +216,17 @@ public TraversalProcess visitAtom( // others unchanged... @Override - public TraversalProcess visitXor(BooleanFormula a, BooleanFormula b) { + public TraversalProcess visitXor(BooleanFormula first, BooleanFormula second) { return TraversalProcess.SKIP; } @Override - public TraversalProcess visitEquivalence(BooleanFormula a, BooleanFormula b) { + public TraversalProcess visitEquivalence(BooleanFormula first, BooleanFormula second) { return TraversalProcess.SKIP; } @Override - public TraversalProcess visitImplication(BooleanFormula a, BooleanFormula b) { + public TraversalProcess visitImplication(BooleanFormula first, BooleanFormula second) { return TraversalProcess.SKIP; } @@ -299,17 +294,17 @@ public TraversalProcess visitAnd(List operands) { } @Override - public TraversalProcess visitXor(BooleanFormula a, BooleanFormula b) { + public TraversalProcess visitXor(BooleanFormula first, BooleanFormula second) { return TraversalProcess.SKIP; } @Override - public TraversalProcess visitEquivalence(BooleanFormula a, BooleanFormula b) { + public TraversalProcess visitEquivalence(BooleanFormula first, BooleanFormula second) { return TraversalProcess.SKIP; } @Override - public TraversalProcess visitImplication(BooleanFormula a, BooleanFormula b) { + public TraversalProcess visitImplication(BooleanFormula first, BooleanFormula second) { return TraversalProcess.SKIP; } diff --git a/src/org/sosy_lab/java_smt/solvers/princess/PrincessAbstractProver.java b/src/org/sosy_lab/java_smt/solvers/princess/PrincessAbstractProver.java index 134179685f..bc2a137756 100644 --- a/src/org/sosy_lab/java_smt/solvers/princess/PrincessAbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/princess/PrincessAbstractProver.java @@ -18,7 +18,7 @@ import ap.parser.IFormula; import ap.parser.IFunction; import ap.parser.ITerm; -import ap.proof.certificates.Certificate; +// import ap.proof.certificates.Certificate; import com.google.common.base.Preconditions; import com.google.errorprone.annotations.CanIgnoreReturnValue; import java.util.ArrayDeque; @@ -39,7 +39,7 @@ import org.sosy_lab.java_smt.api.Model; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; -import org.sosy_lab.java_smt.api.proofs.ProofNode; +// import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.AbstractProverWithAllSat; import org.sosy_lab.java_smt.basicimpl.CachingModel; import scala.Enumeration.Value; @@ -281,13 +281,13 @@ public String toString() { } } - //@Override - //public ProofNode getProof() { + // @Override + // public ProofNode getProof() { // api.getCertificate(); // return null; - // } + // } - // protected Certificate getCertificate() { - // return api.getCertificate(); - //} + // protected Certificate getCertificate() { + // return api.getCertificate(); + // } } diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInteprolProofDAG.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInteprolProofDAG.java index 196c9d1687..8845fdc29c 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInteprolProofDAG.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInteprolProofDAG.java @@ -21,6 +21,7 @@ import java.util.Deque; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import org.sosy_lab.java_smt.ResProofRule; import org.sosy_lab.java_smt.ResProofRule.ResAxiom; @@ -44,7 +45,7 @@ protected enum Rules implements ProofRule { @Override public String getName() { - return name().toLowerCase(); + return name().toLowerCase(Locale.ROOT); } } @@ -56,12 +57,9 @@ protected static class SmtInterpolProofNode extends AbstractProofNode { static class SmtInterpolProofNodeCreator { private final SmtInterpolFormulaCreator creator; - private final SmtInterpolAbstractProver prover; - SmtInterpolProofNodeCreator( - SmtInterpolFormulaCreator pCreator, SmtInterpolAbstractProver pProver) { + SmtInterpolProofNodeCreator(SmtInterpolFormulaCreator pCreator) { creator = pCreator; - prover = pProver; } SmtInterpolProofNode createProof(ProvitionalProofNode pProofNode) { diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java index 2f518a2867..bf314eee48 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java @@ -34,7 +34,6 @@ import java.util.Map; import java.util.Optional; import java.util.Set; -import java.util.Stack; import org.sosy_lab.common.ShutdownNotifier; import org.sosy_lab.common.UniqueIdGenerator; import org.sosy_lab.common.collect.Collections3; @@ -244,7 +243,7 @@ public ProofNode getProof() { } SmtInterpolProofNodeCreator pc = - new SmtInterpolProofNodeCreator((SmtInterpolFormulaCreator) this.creator, this); + new SmtInterpolProofNodeCreator((SmtInterpolFormulaCreator) this.creator); ProvitionalProofNode ppn = pc.createPPNDag(tProof); ProofNode proof = pc.createProof(ppn); // Before being able to perfom resolution, we need to calculate the formulas resulting from @@ -299,11 +298,10 @@ public R allSat(AllSatCallback callback, List important) // update all RES_CHAIN nodes in the proof DAG by computing resolution // formulas and return the updated root node with formulas attached. + @SuppressWarnings("unused") private void clausifyResChain(ProofNode root, BooleanFormulaManager bfmgr) { Map visited = new HashMap<>(); // Track visited nodes - Stack stack = new Stack<>(); - Stack processStack = - new Stack<>(); // Stack to hold nodes for post-processing after children + ArrayDeque stack = new ArrayDeque<>(); stack.push(root); // Start with the root node visited.put(root, Boolean.FALSE); // Mark root as unvisited @@ -311,7 +309,7 @@ private void clausifyResChain(ProofNode root, BooleanFormulaManager bfmgr) { while (!stack.isEmpty()) { ProofNode node = stack.peek(); // Look at the top node, but don't pop yet - if (visited.get(node) == Boolean.FALSE) { + if (visited.get(node).equals(Boolean.FALSE)) { // First time visiting this node visited.put(node, Boolean.TRUE); // Mark node as visited @@ -373,8 +371,6 @@ private BooleanFormula resolve( List literals2 = flattenLiterals(clause2, bfmgr); List combined = new ArrayList<>(); - boolean removed = false; - for (BooleanFormula lit : literals1) { if (!isComplement(lit, pivot, bfmgr)) { combined.add(lit); @@ -382,7 +378,7 @@ private BooleanFormula resolve( } List temp = new ArrayList<>(); - boolean removed2 = false; + for (BooleanFormula lit : literals2) { if (!isComplement(lit, pivot, bfmgr)) { temp.add(lit); @@ -439,17 +435,17 @@ public TraversalProcess visitAtom( // others unchanged... @Override - public TraversalProcess visitXor(BooleanFormula a, BooleanFormula b) { + public TraversalProcess visitXor(BooleanFormula one, BooleanFormula two) { return TraversalProcess.SKIP; } @Override - public TraversalProcess visitEquivalence(BooleanFormula a, BooleanFormula b) { + public TraversalProcess visitEquivalence(BooleanFormula one, BooleanFormula two) { return TraversalProcess.SKIP; } @Override - public TraversalProcess visitImplication(BooleanFormula a, BooleanFormula b) { + public TraversalProcess visitImplication(BooleanFormula one, BooleanFormula two) { return TraversalProcess.SKIP; } @@ -517,17 +513,17 @@ public TraversalProcess visitAnd(List operands) { } @Override - public TraversalProcess visitXor(BooleanFormula a, BooleanFormula b) { + public TraversalProcess visitXor(BooleanFormula var1, BooleanFormula var2) { return TraversalProcess.SKIP; } @Override - public TraversalProcess visitEquivalence(BooleanFormula a, BooleanFormula b) { + public TraversalProcess visitEquivalence(BooleanFormula var1, BooleanFormula var2) { return TraversalProcess.SKIP; } @Override - public TraversalProcess visitImplication(BooleanFormula a, BooleanFormula b) { + public TraversalProcess visitImplication(BooleanFormula var1, BooleanFormula var2) { return TraversalProcess.SKIP; } diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDAG.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDAG.java index ee3b3381af..b8775a76be 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDAG.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDAG.java @@ -44,12 +44,12 @@ public static class Z3ProofNode extends AbstractProofNode { * that is a whole subtree from Z3 composed of the asseertion, the OR operation and the * operands. * - * @param rootProof - * @param formulaCreator - * @return + * @param rootProof The root of proof DAG to be converted + * @param formulaCreator The {@link FormulaCreator} to be able to produce the {@link Formula}s + * @return The root of converted proof DAG as {@link Z3ProofNode} */ - static Z3ProofNode fromZ3Proof(long rootProof, FormulaCreator formulaCreator) { - long z3context = (long) formulaCreator.getEnv(); + static Z3ProofNode fromZ3Proof(long rootProof, Z3FormulaCreator formulaCreator) { + long z3context = formulaCreator.getEnv(); // proof ast to be processed wrapped inside a frame Deque stack = new ArrayDeque<>(); diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java index bf763c85a7..a204312f67 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java @@ -62,7 +62,7 @@ public class Z3ToResolutionProofConverter { // This class is inclompete and curr /** * This method converts a set of Z3ProofNodes into a {@link ResolutionProofDAG}. * - * @param z3ProofNodes + * @param z3ProofNodes the nodes to be converted. * @return {@link ResolutionProofDAG} */ static ResolutionProofDAG convertToResolutionProofDag(Z3ProofDAG.Z3ProofNode[] z3ProofNodes) { @@ -401,143 +401,143 @@ ProofNode handleTransitivityStar(Z3ProofDAG.Z3ProofNode node) { } ProofNode handleMonotonicity(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleQuantIntro(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleBind(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleDistributivity(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleAndElim(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleNotOrElim(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleRewrite(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleRewriteStar(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handlePullQuant(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleElimUnusedVars(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handlePushQuant(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleDer(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleQuantInst(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleHypothesis(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleLemma(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleUnitResolution(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleIffTrue(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleIffFalse(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleCommutativity(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleDefAxiom(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleAssumptionAdd(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleLemmaAdd(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleRedundantDel(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleClauseTrail(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleDefIntro(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleApplyDef(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleIffOeq(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleNnfPos(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleNnfNeg(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleSkolemize(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleModusPonensOeq(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleThLemma(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleHyperResolve(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleOperation(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } ProofNode handleDefault(Z3ProofDAG.Z3ProofNode node) { - return null; + throw new UnsupportedOperationException(); } // This is for debugging purposes. diff --git a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java index 30b5ed9d04..12fa1d3a30 100644 --- a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java +++ b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java @@ -225,7 +225,6 @@ public void testProof() throws InterruptedException, SolverException { assertThat(proof.getChildren()).isNotEmpty(); // Test getId() - assertThat(proof.getId()).isNotNull(); assertThat(proof.getId()).isNotEqualTo(proof.getChildren().get(0).getId()); // Test isLeaf() From 59bcd5e75ce2af2dc8237ef41852aea93153e095 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 2 May 2025 19:01:59 +0200 Subject: [PATCH 089/132] Deleted class that is not needed. Made changes to pass unit tests and checkstyle. --- src/org/sosy_lab/java_smt/ResProofRule.java | 4 + .../java_smt/api/proofs/ProofDAG.java | 4 + .../java_smt/api/proofs/ProofFrame.java | 4 +- .../visitors/ProofTraversalVisitor.java | 4 +- .../java_smt/basicimpl/AbstractProofDAG.java | 2 +- .../java_smt/basicimpl/ProofFactory.java | 7 +- .../solvers/cvc5/CVC5AbstractProver.java | 4 +- .../solvers/mathsat5/Mathsat5ProofNode.java | 3 +- .../solvers/mathsat5/Mathsat5ProofRule.java | 3 +- .../princess/PrincessAbstractProver.java | 2 - .../solvers/smtinterpol/ProofTermParser.java | 196 ------------------ .../java_smt/solvers/z3/Z3SolverContext.java | 6 +- .../z3/Z3ToResolutionProofConverter.java | 4 +- .../java_smt/test/ProverEnvironmentTest.java | 7 +- 14 files changed, 35 insertions(+), 215 deletions(-) delete mode 100644 src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java diff --git a/src/org/sosy_lab/java_smt/ResProofRule.java b/src/org/sosy_lab/java_smt/ResProofRule.java index 5218f3bff0..7fd8f1def8 100644 --- a/src/org/sosy_lab/java_smt/ResProofRule.java +++ b/src/org/sosy_lab/java_smt/ResProofRule.java @@ -28,6 +28,10 @@ public class ResProofRule { private static final Map RULE_MAP = new HashMap<>(); + private ResProofRule() { + //prevent instantiation + } + static { for (ResAxiom rule : ResAxiom.values()) { RULE_MAP.put(rule.getName().toLowerCase(Locale.ROOT), rule); diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java b/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java index b0ba85b4dd..d78a1927f9 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java @@ -8,6 +8,10 @@ * SPDX-License-Identifier: Apache-2.0 */ +/** + * This package is meant to provide abstract classes and interfaces that are inherited and used + * all over to process proofs from the solvers. + */ package org.sosy_lab.java_smt.api.proofs; import java.util.Collection; diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java b/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java index b4683b3fe3..706adef136 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java @@ -42,8 +42,8 @@ public boolean isVisited() { } /** Set the frame as visited. */ - public void setAsVisited(boolean visited) { - this.visited = visited; + public void setAsVisited(boolean isVisited) { + this.visited = isVisited; } /** Set the number of arguments the proof object has. */ diff --git a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java index ea4edb0f4b..a8f27cf484 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java +++ b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java @@ -7,7 +7,9 @@ * * SPDX-License-Identifier: Apache-2.0 */ - +/** + * These package is meant to provide the visitor classes used for proof handling. + */ package org.sosy_lab.java_smt.api.proofs.visitors; import java.util.HashSet; diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java index 59b15cf7a4..5d9b431f11 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java @@ -16,7 +16,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import org.sosy_lab.common.UniqueIdGenerator; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.ProofDAG; diff --git a/src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java b/src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java index be85cba931..5f1e4dbe7f 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java +++ b/src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java @@ -45,7 +45,12 @@ enum Solvers { } protected ProofFactory(ProverEnvironment pProver, String pSolver) { - // formulaCreator = pCreator; + if (pProver == null) { + throw new NullPointerException("ProverEnvironment must not be null"); + } + if (pSolver == null) { + throw new NullPointerException("Solver name must not be null"); + } prover = pProver; solver = Solvers.valueOf(pSolver); } diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java index 486fa90e83..3a9b3f7e4c 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java @@ -260,8 +260,8 @@ public ProofNode getProof() { // CVC5ProofProcessor pp = new CVC5ProofProcessor(creator); try { return CVC5ProofNode.fromCVC5Proof(proofs[0], creator); - } catch (CVC5ApiException pE) { - throw new RuntimeException(pE); + } catch (CVC5ApiException e) { + throw new RuntimeException(e); } } diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java index 4b8b71fe10..7e0699e571 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java @@ -23,7 +23,7 @@ import java.util.HashMap; import java.util.Locale; import java.util.Map; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.proofs.ProofFrame; @@ -128,7 +128,6 @@ public static Mathsat5ProofNode fromMsatProof(ProverEnvironment pProver, long ro i < msat_proof_get_arity(frame.getProof()); i++) { - // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA long child = msat_proof_get_child(frame.getProof(), i); Mathsat5ProofNode childNode = computed.get(child); diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java index 1b42cd78ae..4f0d5eacb9 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java @@ -25,9 +25,8 @@ enum Rule implements ProofRule { // v" CLAUSE_HYP(), // " which are the clauses of the (CNF conversion of the) input problem. They have // a list of terms as children" - NULL() // We introduce this rule because Term Nodes in MathSAT5 do not have a rule associated + NULL(); // We introduce this rule because Term Nodes in MathSAT5 do not have a rule associated // with them. - ; @Override public String getName() { diff --git a/src/org/sosy_lab/java_smt/solvers/princess/PrincessAbstractProver.java b/src/org/sosy_lab/java_smt/solvers/princess/PrincessAbstractProver.java index bc2a137756..ab6feadd21 100644 --- a/src/org/sosy_lab/java_smt/solvers/princess/PrincessAbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/princess/PrincessAbstractProver.java @@ -18,7 +18,6 @@ import ap.parser.IFormula; import ap.parser.IFunction; import ap.parser.ITerm; -// import ap.proof.certificates.Certificate; import com.google.common.base.Preconditions; import com.google.errorprone.annotations.CanIgnoreReturnValue; import java.util.ArrayDeque; @@ -39,7 +38,6 @@ import org.sosy_lab.java_smt.api.Model; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; -// import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.basicimpl.AbstractProverWithAllSat; import org.sosy_lab.java_smt.basicimpl.CachingModel; import scala.Enumeration.Value; diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java deleted file mode 100644 index 71a45d23dd..0000000000 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/ProofTermParser.java +++ /dev/null @@ -1,196 +0,0 @@ -package org.sosy_lab.java_smt.solvers.smtinterpol; - -import de.uni_freiburg.informatik.ultimate.logic.AnnotatedTerm; -import de.uni_freiburg.informatik.ultimate.logic.Annotation; -import de.uni_freiburg.informatik.ultimate.logic.ApplicationTerm; -import de.uni_freiburg.informatik.ultimate.logic.LetTerm; -import de.uni_freiburg.informatik.ultimate.logic.Term; -import de.uni_freiburg.informatik.ultimate.logic.TermVariable; -import java.util.HashMap; -import java.util.Map; -import org.sosy_lab.java_smt.ResProofRule.ResAxiom; -import org.sosy_lab.java_smt.ResolutionProofDAG; -import org.sosy_lab.java_smt.ResolutionProofDAG.AxiomProofNode; -import org.sosy_lab.java_smt.api.BooleanFormula; -import org.sosy_lab.java_smt.api.FormulaManager; -import org.sosy_lab.java_smt.api.proofs.ProofNode; - -// TODO: Correct parsing of the proof terms is missing, i.e. creation of nodes in the DAG and -// parsing annotations. Add relevant javadocs -@SuppressWarnings({"unchecked", "rawtypes", "unused", "static-access"}) -public class ProofTermParser { - - private final ResolutionProofDAG proofDag; - private final Map annotatedTerms; - private final Map letBindings = new HashMap<>(); - private final Map termToNode = new HashMap<>(); - private final FormulaManager mgr; - - public ProofTermParser(Map pAnnotatedTerms, FormulaManager pMgr) { - annotatedTerms = pAnnotatedTerms; - mgr = pMgr; - proofDag = new ResolutionProofDAG(); - } - - public static ResolutionProofDAG convert( - Term proof, FormulaManager pManager, Map pAnnotatedTerms) { - ProofTermParser parser = new ProofTermParser(pAnnotatedTerms, pManager); - ProofNode rootNode = parser.parseProofTerm(proof); - if (rootNode != null) { - parser.proofDag.addNode(rootNode); - } - return parser.proofDag; - } - - public ProofNode parseProofTerm(Term term) { - if (termToNode.containsKey(term)) { - return termToNode.get(term); - } - - ProofNode node = null; - - if (term instanceof AnnotatedTerm) { - node = parseAnnotatedTerm((AnnotatedTerm) term); - } else if (term instanceof ApplicationTerm) { - node = parseApplicationTerm((ApplicationTerm) term); - } else if (term instanceof LetTerm) { - node = parseLetTerm((LetTerm) term); - } - - if (node != null) { - termToNode.put(term, node); - } - - return node; - } - - private ProofNode parseAnnotatedTerm(AnnotatedTerm term) { - for (Annotation annotation : term.getAnnotations()) { - if (annotation.getKey().equals(":proves") - || annotation.getKey().equals(":rup") - || annotation.getKey().equals(":input")) { - Term formulaTerm = extractFormulaFromAnnotation(annotation); - BooleanFormula formula = getBooleanFormulaFromTerm(formulaTerm); - ProofNode node = createSourceNode(ResAxiom.RESOLUTION, formula); - return node; - } - } - return parseProofTerm(term.getSubterm()); - } - - private ProofNode parseApplicationTerm(ApplicationTerm term) { - String funcName = term.getFunction().getName(); - Term[] params = term.getParameters(); - - if (funcName.equals("..res") && params.length >= 3) { - Term clauseTerm = params[0]; - BooleanFormula formula = getBooleanFormulaFromTerm(clauseTerm); - ProofNode resNode = createSourceNode(ResAxiom.RESOLUTION, formula); - - for (int i = 1; i < params.length; i++) { - ProofNode childNode = parseProofTerm(params[i]); - if (childNode != null) { - proofDag.addEdge(resNode.getId(), childNode.getId()); - } - } - return resNode; - } else if (funcName.equals("..assume") && params.length > 0) { - Term assumedFormula = params[0]; - BooleanFormula formula = getBooleanFormulaFromTerm(assumedFormula); - return createSourceNode(ResAxiom.ASSUME, formula); - } else if (funcName.equals("..axiom") && params.length > 0) { - Term axiomFormula = params[0]; - BooleanFormula formula = getBooleanFormulaFromTerm(axiomFormula); - ResAxiom axiomType = inferAxiomType(funcName, params); - return createSourceNode(axiomType, formula); - } else if (funcName.startsWith("@")) { - String lemmaType = funcName.substring(1); - ResAxiom axiomType = mapTheoryLemmaToAxiom(lemmaType); - - if (params.length > 0) { - Term lemmaFormula = params[0]; - BooleanFormula formula = getBooleanFormulaFromTerm(lemmaFormula); - return createSourceNode(axiomType, formula); - } - } - - ProofNode lastNode = null; - for (Term param : params) { - lastNode = parseProofTerm(param); - } - - return lastNode; - } - - private ProofNode parseLetTerm(LetTerm term) { - Map oldBindings = new HashMap<>(letBindings); - TermVariable[] vars = term.getVariables(); - Term[] values = term.getValues(); - - for (int i = 0; i < vars.length; i++) { - letBindings.put(vars[i].getName(), values[i]); - } - - ProofNode result = parseProofTerm(term.getSubTerm()); - letBindings.clear(); - letBindings.putAll(oldBindings); - - return result; - } - - private Term extractFormulaFromAnnotation(Annotation annotation) { - Object value = annotation.getValue(); - if (value instanceof Term) { - return (Term) value; - } - return null; - } - - private String extractName(Term term) { - if (term instanceof AnnotatedTerm) { - for (Annotation annot : ((AnnotatedTerm) term).getAnnotations()) { - if (":named".equals(annot.getKey())) { - return annot.getValue().toString(); - } - } - } - return null; - } - - private BooleanFormula getBooleanFormulaFromTerm(Term term) { - String name = extractName(term); - if (name != null && annotatedTerms.containsKey(name)) { - return annotatedTerms.get(name); - } - return ((SmtInterpolFormulaManager) mgr).encapsulateBooleanFormula(term); - } - - private ProofNode createSourceNode(ResAxiom rule, BooleanFormula formula) { - ProofNode node = new AxiomProofNode(rule, formula); - proofDag.addNode(node); - return node; - } - - private ResAxiom inferAxiomType(String funcName, Term[] params) { - return ResAxiom.RESOLUTION; - } - - private ResAxiom mapTheoryLemmaToAxiom(String lemmaType) { - switch (lemmaType) { - case "equalsTransitive": - return ResAxiom.TRANSITIVITY; - case "equalsSymmetric": - return ResAxiom.SYMMETRY; - case "equalsReflexive": - return ResAxiom.REFLEXIVITY; - case "distinctNegation": - return ResAxiom.DISTINCT_NEGATIVE; - case "store": - return ResAxiom.SELECTSTORE1; - case "select": - return ResAxiom.SELECTSTORE2; - default: - return ResAxiom.RESOLUTION; - } - } -} diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java index 3e93d032f1..b182ebb116 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java @@ -50,7 +50,7 @@ public final class Z3SolverContext extends AbstractSolverContext { private static final String OPT_ENGINE_CONFIG_KEY = "optsmt_engine"; private static final String OPT_PRIORITY_CONFIG_KEY = "priority"; - private static boolean GENERATE_PROOFS = false; + private static boolean generateProofs = false; //for debugging @Options(prefix = "solver.z3") private static class ExtraOptions { @@ -147,7 +147,7 @@ public static synchronized Z3SolverContext create( long cfg = Native.mkConfig(); if (extraOptions.requireProofs) { Native.setParamValue(cfg, "PROOF", "true"); - GENERATE_PROOFS = true; + generateProofs = true; } Native.globalParamSet("smt.random_seed", String.valueOf(randomSeed)); Native.globalParamSet("model.compact", "false"); @@ -286,7 +286,7 @@ public void close() { // Method exlcusively used for testing boolean getGenerateProofs() { - return GENERATE_PROOFS; + return generateProofs; } @Override diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java index a204312f67..68d22d49a0 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java @@ -70,7 +70,7 @@ static ResolutionProofDAG convertToResolutionProofDag(Z3ProofDAG.Z3ProofNode[] z for (Z3ProofDAG.Z3ProofNode z3Node : z3ProofNodes) { if (z3Node.getRule() == MODUS_PONENS) { - + continue; //process mp continue here to avoid empty if block } else { Formula formula = z3Node.getFormula(); // ResAxiom resAxiom = mapRule(z3Node.getRule()); @@ -83,7 +83,7 @@ static ResolutionProofDAG convertToResolutionProofDag(Z3ProofDAG.Z3ProofNode[] z } // This should help extract parts of a formula to better transform proof rules. - private static class ExtractorVisitor implements BooleanFormulaVisitor { + private final static class ExtractorVisitor implements BooleanFormulaVisitor { private final List equivalenceOperands = new ArrayList<>(); public List getEquivalenceOperands() { diff --git a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java index 12fa1d3a30..6b597e8f8a 100644 --- a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java +++ b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java @@ -16,6 +16,7 @@ import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.MATHSAT5; import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.OPENSMT; import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.PRINCESS; +import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.SMTINTERPOL; import static org.sosy_lab.java_smt.api.SolverContext.ProverOptions.GENERATE_UNSAT_CORE; import static org.sosy_lab.java_smt.api.SolverContext.ProverOptions.GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS; import static org.sosy_lab.java_smt.test.ProverEnvironmentSubject.assertThat; @@ -218,7 +219,11 @@ public void testProof() throws InterruptedException, SolverException { assertThat(proof.getRule()).isInstanceOf(ProofRule.class); // Test getFormula(), the root should always be false - assertThat(proof.getFormula()).isEqualTo(bmgr.makeFalse()); + if(solverToUse().equals(SMTINTERPOL)){ + assertThat(proof.getFormula()).isNull(); + }else { + assertThat(proof.getFormula()).isEqualTo(bmgr.makeFalse()); + } // Test getChildren() assertThat(proof.getChildren()).isNotNull(); From 1f805df6b4dc44e013065a68fcb24ccf0ae32a7f Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 2 May 2025 20:30:43 +0200 Subject: [PATCH 090/132] Made changes to pass unit tests and checkstyle. --- src/org/sosy_lab/java_smt/ResProofRule.java | 4 ++-- src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java | 4 ---- .../{basicimpl => api/proofs}/ProofFactory.java | 3 +-- .../sosy_lab/java_smt/api/proofs/package-info.java | 14 ++++++++++++++ .../api/proofs/visitors/ProofTraversalVisitor.java | 3 --- .../java_smt/api/proofs/visitors/package-info.java | 11 +++++++++++ .../solvers/mathsat5/Mathsat5ProofRule.java | 3 ++- .../solvers/mathsat5/Mathsat5TheoremProver.java | 2 +- .../java_smt/solvers/z3/Z3SolverContext.java | 2 +- .../solvers/z3/Z3ToResolutionProofConverter.java | 4 ++-- .../java_smt/test/ProverEnvironmentTest.java | 8 ++++---- 11 files changed, 38 insertions(+), 20 deletions(-) rename src/org/sosy_lab/java_smt/{basicimpl => api/proofs}/ProofFactory.java (95%) create mode 100644 src/org/sosy_lab/java_smt/api/proofs/package-info.java create mode 100644 src/org/sosy_lab/java_smt/api/proofs/visitors/package-info.java diff --git a/src/org/sosy_lab/java_smt/ResProofRule.java b/src/org/sosy_lab/java_smt/ResProofRule.java index 7fd8f1def8..4489d416ab 100644 --- a/src/org/sosy_lab/java_smt/ResProofRule.java +++ b/src/org/sosy_lab/java_smt/ResProofRule.java @@ -24,12 +24,12 @@ * * @author Gabriel Carpio */ -public class ResProofRule { +public final class ResProofRule { private static final Map RULE_MAP = new HashMap<>(); private ResProofRule() { - //prevent instantiation + // prevent instantiation } static { diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java b/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java index d78a1927f9..b0ba85b4dd 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java @@ -8,10 +8,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -/** - * This package is meant to provide abstract classes and interfaces that are inherited and used - * all over to process proofs from the solvers. - */ package org.sosy_lab.java_smt.api.proofs; import java.util.Collection; diff --git a/src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java similarity index 95% rename from src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java rename to src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java index 5f1e4dbe7f..1516e5ae13 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/ProofFactory.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java @@ -8,14 +8,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -package org.sosy_lab.java_smt.basicimpl; +package org.sosy_lab.java_smt.api.proofs; import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.ResolutionProofDAG.AxiomProofNode; import org.sosy_lab.java_smt.ResolutionProofDAG.ResolutionProofNode; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.ProverEnvironment; -import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5ProofNode; /** diff --git a/src/org/sosy_lab/java_smt/api/proofs/package-info.java b/src/org/sosy_lab/java_smt/api/proofs/package-info.java new file mode 100644 index 0000000000..1d2d7f8a4b --- /dev/null +++ b/src/org/sosy_lab/java_smt/api/proofs/package-info.java @@ -0,0 +1,14 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * This package is meant to provide abstract classes and interfaces that are inherited and used all + * over to process proofs from the solvers. + */ +package org.sosy_lab.java_smt.api.proofs; diff --git a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java index a8f27cf484..af5e2a97dc 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java +++ b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java @@ -7,9 +7,6 @@ * * SPDX-License-Identifier: Apache-2.0 */ -/** - * These package is meant to provide the visitor classes used for proof handling. - */ package org.sosy_lab.java_smt.api.proofs.visitors; import java.util.HashSet; diff --git a/src/org/sosy_lab/java_smt/api/proofs/visitors/package-info.java b/src/org/sosy_lab/java_smt/api/proofs/visitors/package-info.java new file mode 100644 index 0000000000..e242c9ee7b --- /dev/null +++ b/src/org/sosy_lab/java_smt/api/proofs/visitors/package-info.java @@ -0,0 +1,11 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ +/** These package is meant to provide the visitor classes used for proof handling. */ +package org.sosy_lab.java_smt.api.proofs.visitors; diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java index 4f0d5eacb9..8d02a4be5c 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java @@ -26,7 +26,8 @@ enum Rule implements ProofRule { CLAUSE_HYP(), // " which are the clauses of the (CNF conversion of the) input problem. They have // a list of terms as children" NULL(); // We introduce this rule because Term Nodes in MathSAT5 do not have a rule associated - // with them. + + // with them. @Override public String getName() { diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java index 4db022c707..d8ca9952c8 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java @@ -32,10 +32,10 @@ import org.sosy_lab.java_smt.api.QuantifiedFormulaManager.Quantifier; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; +import org.sosy_lab.java_smt.api.proofs.ProofFactory; import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.api.visitors.BooleanFormulaVisitor; import org.sosy_lab.java_smt.api.visitors.TraversalProcess; -import org.sosy_lab.java_smt.basicimpl.ProofFactory; import org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5ProofRule.Rule; class Mathsat5TheoremProver extends Mathsat5AbstractProver implements ProverEnvironment { diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java index b182ebb116..51de53ea95 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java @@ -50,7 +50,7 @@ public final class Z3SolverContext extends AbstractSolverContext { private static final String OPT_ENGINE_CONFIG_KEY = "optsmt_engine"; private static final String OPT_PRIORITY_CONFIG_KEY = "priority"; - private static boolean generateProofs = false; //for debugging + private static boolean generateProofs = false; // for debugging @Options(prefix = "solver.z3") private static class ExtraOptions { diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java index 68d22d49a0..da1ef798e1 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java @@ -70,7 +70,7 @@ static ResolutionProofDAG convertToResolutionProofDag(Z3ProofDAG.Z3ProofNode[] z for (Z3ProofDAG.Z3ProofNode z3Node : z3ProofNodes) { if (z3Node.getRule() == MODUS_PONENS) { - continue; //process mp continue here to avoid empty if block + continue; // process mp continue here to avoid empty if block } else { Formula formula = z3Node.getFormula(); // ResAxiom resAxiom = mapRule(z3Node.getRule()); @@ -83,7 +83,7 @@ static ResolutionProofDAG convertToResolutionProofDag(Z3ProofDAG.Z3ProofNode[] z } // This should help extract parts of a formula to better transform proof rules. - private final static class ExtractorVisitor implements BooleanFormulaVisitor { + private final class ExtractorVisitor implements BooleanFormulaVisitor { private final List equivalenceOperands = new ArrayList<>(); public List getEquivalenceOperands() { diff --git a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java index 6b597e8f8a..c2cdd002f6 100644 --- a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java +++ b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java @@ -219,9 +219,9 @@ public void testProof() throws InterruptedException, SolverException { assertThat(proof.getRule()).isInstanceOf(ProofRule.class); // Test getFormula(), the root should always be false - if(solverToUse().equals(SMTINTERPOL)){ + if (solverToUse().equals(SMTINTERPOL)) { assertThat(proof.getFormula()).isNull(); - }else { + } else { assertThat(proof.getFormula()).isEqualTo(bmgr.makeFalse()); } @@ -238,8 +238,8 @@ public void testProof() throws InterruptedException, SolverException { assertThat(leaf).isNotNull(); assertThat(leaf.isLeaf()).isTrue(); - } catch (UnsupportedOperationException uE) { - assertThat(uE) + } catch (UnsupportedOperationException e) { + assertThat(e) .hasMessageThat() .isEqualTo("Proof generation is not available for the current solver."); Class contextClass = context.getClass(); From 4b89e384781b0609dce8597c980de4d1b4bc42e9 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sat, 3 May 2025 09:56:56 +0200 Subject: [PATCH 091/132] Corrected warnings --- .../java_smt/solvers/z3/Z3ToResolutionProofConverter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java index da1ef798e1..55b0f08ab6 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java @@ -83,7 +83,7 @@ static ResolutionProofDAG convertToResolutionProofDag(Z3ProofDAG.Z3ProofNode[] z } // This should help extract parts of a formula to better transform proof rules. - private final class ExtractorVisitor implements BooleanFormulaVisitor { + private static final class ExtractorVisitor implements BooleanFormulaVisitor { private final List equivalenceOperands = new ArrayList<>(); public List getEquivalenceOperands() { From 31198739a0e46c32a24faa101605751bd291e702 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Wed, 7 May 2025 15:41:17 +0200 Subject: [PATCH 092/132] Deleted unsued variable --- .../sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java index 7e0699e571..6407a508d1 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java @@ -42,8 +42,6 @@ protected static class MsatProofFrame extends ProofFrame { MsatProofFrame(Long proof) { super(proof); } - - boolean skip = false; } /** From e814fa2d9be1a384b4c514e1d0f99f3292813f32 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Wed, 7 May 2025 15:41:29 +0200 Subject: [PATCH 093/132] Deleted unused methods --- .../sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java index 9d6467403c..d75f5d6334 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java @@ -161,16 +161,6 @@ public ProofNode getProof() throws SolverException, InterruptedException { return Z3ProofNode.fromZ3Proof(proofAst, creator); } - // This method is used to get the Z3 proof as a long for testing exclusively - long getZ3Proof() { - return Native.solverGetProof(z3context, z3solver); - } - - // This method is used to get the Z3 solver object for testing exclusively - long getZ3solver() { - return z3solver; - } - @Override public int size() { Preconditions.checkState(!closed); From e59a15fb2567548af011a83d0b2ad73971942273 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Wed, 7 May 2025 15:41:57 +0200 Subject: [PATCH 094/132] Z3 now has proof production always enabled --- src/org/sosy_lab/java_smt/SolverContextFactory.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/SolverContextFactory.java b/src/org/sosy_lab/java_smt/SolverContextFactory.java index 576285424d..21822c2b6f 100644 --- a/src/org/sosy_lab/java_smt/SolverContextFactory.java +++ b/src/org/sosy_lab/java_smt/SolverContextFactory.java @@ -282,7 +282,8 @@ private SolverContext generateContext0(Solvers solverToCreate) case Z3: return Z3SolverContext.create( logger, - config, + Configuration.builder().copyFrom(config) + .setOption("solver.z3.requireProofs", "true").build(), shutdownNotifier, logfile, randomSeed, From d26157df550c01ad0b2310c1d67eb54f815d0d24 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 12 May 2025 11:11:06 +0200 Subject: [PATCH 095/132] MathSAT5: Changed proof rule in the enum Rule from Rule.NULL to Rule.EMPTY --- .../java_smt/solvers/mathsat5/Mathsat5ProofNode.java | 6 +++--- .../java_smt/solvers/mathsat5/Mathsat5ProofRule.java | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java index 6407a508d1..95f52183ab 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java @@ -107,7 +107,7 @@ public static Mathsat5ProofNode fromMsatProof(ProverEnvironment pProver, long ro try { proofRule = rule == null - ? Rule.NULL + ? Rule.EMPTY : Rule.valueOf(rule.toUpperCase(Locale.ROOT).replace("-", "_")); } catch (IllegalArgumentException e) { proofRule = new Mathsat5ProofRule(rule); @@ -146,8 +146,8 @@ private static Formula generateFormula( Formula formula = null; long proof = frame.getProof(); int children = msat_proof_get_arity(proof); - // If rule is NULL the proof should be a term and we encapsulate directly - if (rule.equals(Rule.NULL)) { + // If rule is EMPTY the proof should be a term and we encapsulate directly + if (rule.equals(Rule.EMPTY)) { formula = formulaCreator.encapsulate( formulaCreator.getFormulaType(msat_proof_get_term(proof)), diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java index 8d02a4be5c..9458655b7b 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java @@ -25,9 +25,10 @@ enum Rule implements ProofRule { // v" CLAUSE_HYP(), // " which are the clauses of the (CNF conversion of the) input problem. They have // a list of terms as children" - NULL(); // We introduce this rule because Term Nodes in MathSAT5 do not have a rule associated - // with them. + EMPTY(); //We introduce this rule for term nodes that do not have a proof rule attached, even + // if they are pivots. In the future it might be good to a PIVOT rule so that those can have + // that instead. @Override public String getName() { From 136f1fe213522cfc1d981e6b6a5f5c78481603c4 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 12 May 2025 17:04:06 +0200 Subject: [PATCH 096/132] SMTInterpol: Reverted changes to SmtInterpolFormulaCreator from commit e2268bae13f7 --- .../solvers/smtinterpol/SmtInterpolFormulaCreator.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolFormulaCreator.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolFormulaCreator.java index fe083eb844..757b2a61ba 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolFormulaCreator.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolFormulaCreator.java @@ -101,7 +101,12 @@ private FunctionSymbol declareFun(String fun, Sort[] paramSorts, Sort resultSort FunctionSymbol fsym = environment.getTheory().getFunction(fun, paramSorts); if (fsym == null) { - environment.declareFun(fun, paramSorts, resultSort); + try { + environment.declareFun(fun, paramSorts, resultSort); + } catch (SMTLIBException e) { + // can fail, if function is already declared with a different sort + throw new IllegalArgumentException("Cannot declare function '" + fun + "'", e); + } return environment.getTheory().getFunction(fun, paramSorts); } else { if (!fsym.getReturnSort().equals(resultSort)) { From 9303114e0109a14408b100bcb5757f8177ad18c0 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Tue, 13 May 2025 18:27:47 +0200 Subject: [PATCH 097/132] Changed the parameter of 'toLowerCase' from Locale.ROOT to Locale.ENGLISH in classes from the proof interface using this. Method 'getFromName' in 'ResAxiom' now uses 'Preconditions.checkNotNull' --- src/org/sosy_lab/java_smt/ResProofRule.java | 11 ++++------- .../java_smt/solvers/mathsat5/Mathsat5ProofNode.java | 2 +- .../solvers/smtinterpol/SmtInteprolProofDAG.java | 2 +- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/org/sosy_lab/java_smt/ResProofRule.java b/src/org/sosy_lab/java_smt/ResProofRule.java index 4489d416ab..6291097762 100644 --- a/src/org/sosy_lab/java_smt/ResProofRule.java +++ b/src/org/sosy_lab/java_smt/ResProofRule.java @@ -10,6 +10,7 @@ package org.sosy_lab.java_smt; +import com.google.common.base.Preconditions; import java.util.HashMap; import java.util.Locale; import java.util.Map; @@ -34,7 +35,7 @@ private ResProofRule() { static { for (ResAxiom rule : ResAxiom.values()) { - RULE_MAP.put(rule.getName().toLowerCase(Locale.ROOT), rule); + RULE_MAP.put(rule.getName().toLowerCase(Locale.ENGLISH), rule); } } @@ -150,12 +151,8 @@ public String getFormula() { * @throws IllegalArgumentException if the name does not match any rule. */ public static ResAxiom getFromName(String name) { - - ResAxiom rule = RULE_MAP.get(name.toLowerCase(Locale.ROOT)); - if (rule == null) { - throw new IllegalArgumentException("Rule not found or not specified: " + name); - } - + ResAxiom rule = RULE_MAP.get(name.toLowerCase(Locale.ENGLISH)); + Preconditions.checkNotNull(rule); return rule; } } diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java index 95f52183ab..4e9230d3ee 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java @@ -108,7 +108,7 @@ public static Mathsat5ProofNode fromMsatProof(ProverEnvironment pProver, long ro proofRule = rule == null ? Rule.EMPTY - : Rule.valueOf(rule.toUpperCase(Locale.ROOT).replace("-", "_")); + : Rule.valueOf(rule.toUpperCase(Locale.ENGLISH).replace("-", "_")); } catch (IllegalArgumentException e) { proofRule = new Mathsat5ProofRule(rule); } diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInteprolProofDAG.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInteprolProofDAG.java index 8845fdc29c..56afb25a14 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInteprolProofDAG.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInteprolProofDAG.java @@ -45,7 +45,7 @@ protected enum Rules implements ProofRule { @Override public String getName() { - return name().toLowerCase(Locale.ROOT); + return name().toLowerCase(Locale.ENGLISH); } } From ca7e1eb2d0b735b774533de0c6762a42904d4b6c Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Thu, 15 May 2025 18:04:57 +0200 Subject: [PATCH 098/132] Renamed classes and added methods 'proofAsString' and 'getDAG'. Added edges field as a map of nodes to a list of nodes. Renamed many methods. Children of nodes no longer stored in the node but obtained through the edges field of the DAG. --- .../java_smt/basicimpl/AbstractProof.java | 129 ++++++++++++++++++ .../java_smt/basicimpl/AbstractProofDAG.java | 117 ---------------- 2 files changed, 129 insertions(+), 117 deletions(-) create mode 100644 src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java delete mode 100644 src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java new file mode 100644 index 0000000000..1809fe686e --- /dev/null +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java @@ -0,0 +1,129 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.basicimpl; + +import com.google.common.base.Preconditions; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.proofs.Proof; +import org.sosy_lab.java_smt.api.proofs.ProofRule; +import org.sosy_lab.java_smt.solvers.z3.Z3Proof.Z3Subproof; + +/** + * A proof DAG of a proof. + * + * @author Gabriel Carpio + */ +public abstract class AbstractProof implements Proof { + + //protected abstract class Transformation { + // protected Transformation( + // FormulaCreator formulaCreator, T proof) {} + +// protected abstract Proof generateProof(); + //} + + protected final Map> edges = new HashMap<>(); + + protected void addEdge(Subproof source, Subproof target) { + Preconditions.checkNotNull(source); + Preconditions.checkNotNull(target); + edges.putIfAbsent(source, new ArrayList<>()); + edges.get(source).add(target); + } + + @Override + public Collection getSubproofs() { + return edges.keySet(); + } + + protected abstract static class AbstractSubproof implements Subproof { + private final AbstractProof proof; + private ProofRule rule; + @Nullable protected Formula formula; + + protected AbstractSubproof(ProofRule rule, Formula formula, AbstractProof proof) { + this.rule = rule; + this.formula = formula; + this.proof = proof; + } + + @Override + public Formula getFormula() { + return formula; + } + + @Override + public List getArguments() { + return this.proof.edges.get(this); + } + + protected void addChild(Subproof child) { + this.proof.addEdge(this, child); + } + + @Override + public ProofRule getRule() { + return rule; + } + + @Override + public boolean isLeaf() { + return getArguments() == null; + } + + // void setRule(ProofRule rule) { + // this.rule = rule; + // } + + public void setFormula(Formula pFormula) { + formula = pFormula; + } + + public Proof getDAG() { + return proof; + } + + // use this for debugging + protected String proofAsString() { + return proofAsString(0); + } + + protected String proofAsString(int indentLevel) { + StringBuilder proof = new StringBuilder(); + String indent = " ".repeat(indentLevel); + + proof.append(indent).append("Formula: ").append(getFormula().toString()).append("\n"); + proof.append(indent).append("Rule: ").append(getRule().getName()).append("\n"); + proof + .append(indent) + .append("No. Children: ") + .append(this.isLeaf() ? 0 : getArguments().size()) + .append("\n"); + proof.append(indent).append("leaf: ").append(isLeaf()).append("\n"); + + int i = 0; + if (!isLeaf()) { + for (Subproof child : getArguments()) { + proof.append(indent).append("Child ").append(++i).append(":\n"); + proof.append(((Z3Subproof) child).proofAsString(indentLevel + 1)); + } + } + + return proof.toString(); + } + } +} diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java deleted file mode 100644 index 5d9b431f11..0000000000 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProofDAG.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * This file is part of JavaSMT, - * an API wrapper for a collection of SMT solvers: - * https://github.com/sosy-lab/java-smt - * - * SPDX-FileCopyrightText: 2024 Dirk Beyer - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.sosy_lab.java_smt.basicimpl; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.sosy_lab.common.UniqueIdGenerator; -import org.sosy_lab.java_smt.api.Formula; -import org.sosy_lab.java_smt.api.proofs.ProofDAG; -import org.sosy_lab.java_smt.api.proofs.ProofNode; -import org.sosy_lab.java_smt.api.proofs.ProofRule; -import org.sosy_lab.java_smt.api.proofs.visitors.ProofVisitor; - -/** - * A proof DAG in the proof DAG of a proof. - * - * @author Gabriel Carpio - */ -public abstract class AbstractProofDAG implements ProofDAG { - private final Map nodes = new HashMap<>(); - private int nodeIdCounter = 0; - - @Override - public void addNode(ProofNode node) { - nodes.put(nodeIdCounter++, node); - } - - @Override - public ProofNode getNode(int nodeId) { - return nodes.get(nodeId); - } - - @Override - public void addEdge(int parentNodeId, int childNodeId) { - ProofNode parent = nodes.get(parentNodeId); - ProofNode child = nodes.get(childNodeId); - if (parent != null && child != null) { - parent.addChild(child); - } - } - - @Override - public Collection getNodes() { - return nodes.values(); - } - - @Override - public void accept(ProofVisitor visitor) { - visitor.visitDAG(this); - } - - public abstract static class AbstractProofNode implements ProofNode { - private final List children; - private ProofRule rule; - @Nullable protected Formula formula; - private static final UniqueIdGenerator idGenerator = new UniqueIdGenerator(); - private final int id; - - protected AbstractProofNode(ProofRule rule, Formula formula) { - this.rule = rule; - this.formula = formula; - children = new ArrayList<>(); - id = idGenerator.getFreshId(); - } - - @Override - public Formula getFormula() { - return formula; - } - - @Override - public List getChildren() { - return Collections.unmodifiableList(children); - } - - @Override - public void addChild(ProofNode child) { - children.add(child); - } - - @Override - public ProofRule getRule() { - return rule; - } - - @Override - public boolean isLeaf() { - return children.isEmpty(); - } - - @Override - public int getId() { - return id; - } - - void setRule(ProofRule rule) { - this.rule = rule; - } - - public void setFormula(Formula pFormula) { - formula = pFormula; - } - } -} From a761fcaa2697d24f0257f3b69420f50c830e14c8 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Thu, 15 May 2025 18:06:27 +0200 Subject: [PATCH 099/132] Renamed class ProofNode to Subproof --- src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java | 4 ++-- src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java | 4 ++-- .../BasicProverWithAssumptionsWrapper.java | 4 ++-- .../java_smt/solvers/cvc5/CVC5AbstractProver.java | 8 ++++---- .../sosy_lab/java_smt/solvers/cvc5/CVC5NativeAPITest.java | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java b/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java index a327d0df50..2a012eea9b 100644 --- a/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java @@ -16,7 +16,7 @@ import java.util.Optional; import org.checkerframework.checker.nullness.qual.Nullable; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; -import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.Proof.Subproof; /** * Super interface for {@link ProverEnvironment} and {@link InterpolatingProverEnvironment} that @@ -154,7 +154,7 @@ default ImmutableMap getStatistics() { * Get proof of unsatisfiability of the conjuction of the current satck of all formulas. Should * only be called after {@link #isUnsat()} returned true. */ - ProofNode getProof() throws SolverException, InterruptedException; + Subproof getProof() throws SolverException, InterruptedException; /** * Closes the prover environment. The object should be discarded, and should not be used after diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java index ebc0f4f9c2..63ec7c7188 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java @@ -27,7 +27,7 @@ import org.sosy_lab.java_smt.api.Evaluator; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; -import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.Proof.Subproof; public abstract class AbstractProver implements BasicProverEnvironment { @@ -168,7 +168,7 @@ public void close() { } @Override - public ProofNode getProof() throws InterruptedException, SolverException { + public Subproof getProof() throws InterruptedException, SolverException { throw new UnsupportedOperationException( "Proof generation is not available for the current solver."); } diff --git a/src/org/sosy_lab/java_smt/basicimpl/withAssumptionsWrapper/BasicProverWithAssumptionsWrapper.java b/src/org/sosy_lab/java_smt/basicimpl/withAssumptionsWrapper/BasicProverWithAssumptionsWrapper.java index 0cb2e64571..33a8617218 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/withAssumptionsWrapper/BasicProverWithAssumptionsWrapper.java +++ b/src/org/sosy_lab/java_smt/basicimpl/withAssumptionsWrapper/BasicProverWithAssumptionsWrapper.java @@ -18,7 +18,7 @@ import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.Model; import org.sosy_lab.java_smt.api.SolverException; -import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.Proof.Subproof; public class BasicProverWithAssumptionsWrapper> implements BasicProverEnvironment { @@ -131,7 +131,7 @@ public R allSat(AllSatCallback pCallback, List pImportant } @Override - public ProofNode getProof() throws SolverException, InterruptedException { + public Subproof getProof() throws SolverException, InterruptedException { return delegate.getProof(); } } diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java index 3a9b3f7e4c..6604bcc021 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java @@ -38,9 +38,8 @@ import org.sosy_lab.java_smt.api.Model.ValueAssignment; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; -import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.Proof.Subproof; import org.sosy_lab.java_smt.basicimpl.AbstractProverWithAllSat; -import org.sosy_lab.java_smt.solvers.cvc5.CVC5ProofDAG.CVC5ProofNode; abstract class CVC5AbstractProver extends AbstractProverWithAllSat { @@ -250,7 +249,7 @@ public Optional> unsatCoreOverAssumptions( } @Override - public ProofNode getProof() { + public Subproof getProof() { Proof[] proofs = solver.getProof(); if (proofs == null || proofs.length == 0) { @@ -259,7 +258,8 @@ public ProofNode getProof() { // CVC5ProofProcessor pp = new CVC5ProofProcessor(creator); try { - return CVC5ProofNode.fromCVC5Proof(proofs[0], creator); + CVC5Proof proof = new CVC5Proof(); + return proof.generateProofImpl(proofs[0], creator); } catch (CVC5ApiException e) { throw new RuntimeException(e); } diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5NativeAPITest.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5NativeAPITest.java index 535c12599f..fed20bfe0e 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5NativeAPITest.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5NativeAPITest.java @@ -1411,7 +1411,7 @@ public void testProofMethods() throws CVC5ApiException { assertThat(proof.getRule()).isEqualTo(ProofRule.SCOPE); - // Test getChildren + // Test getArguments assertThat(proof.getChildren()).isNotNull(); assertThat(proof.getChildren()[0]).isNotNull(); From 28390a22617dff342d94744a7b6d2c80d7cc70ff Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Thu, 15 May 2025 18:07:15 +0200 Subject: [PATCH 100/132] Methods that should not be public no longer in 'Proof' interface moved 'Subproof' into 'Proof' --- .../sosy_lab/java_smt/api/proofs/Proof.java | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/org/sosy_lab/java_smt/api/proofs/Proof.java diff --git a/src/org/sosy_lab/java_smt/api/proofs/Proof.java b/src/org/sosy_lab/java_smt/api/proofs/Proof.java new file mode 100644 index 0000000000..c6aa51769d --- /dev/null +++ b/src/org/sosy_lab/java_smt/api/proofs/Proof.java @@ -0,0 +1,49 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.api.proofs; + +import java.util.Collection; +import java.util.List; +import org.sosy_lab.java_smt.api.Formula; + +/** + * A DAG representing a proof. Each node in the DAG is a {@link Subproof} and each edge is a + * directed edge from a parent node to a child node. + */ +public interface Proof { + + /** Get all proof steps in the proof. */ + Collection getSubproofs(); + + /** + * A proof node in the proof DAG of a proof. + * + * @author Gabriel Carpio + */ + interface Subproof { + + /** Get the children of the proof node. */ + List getArguments(); + + boolean isLeaf(); + + /** + * Get the formula of the proof node. + * + * @return The formula of the proof node. + */ + Formula getFormula(); + + ProofRule getRule(); + + Proof getDAG(); + } +} From 5096139aabb3cc46ad329c14770434023e24a337 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Thu, 15 May 2025 18:07:40 +0200 Subject: [PATCH 101/132] Moved classes, removed not needed ones --- .../java_smt/api/proofs/ProofDAG.java | 49 ------------ .../java_smt/api/proofs/ProofFactory.java | 80 ------------------- .../java_smt/api/proofs/ProofNode.java | 45 ----------- .../visitors/ProofTraversalVisitor.java | 37 --------- .../api/proofs/visitors/ProofVisitor.java | 20 ----- .../api/proofs/visitors/package-info.java | 11 --- 6 files changed, 242 deletions(-) delete mode 100644 src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java delete mode 100644 src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java delete mode 100644 src/org/sosy_lab/java_smt/api/proofs/ProofNode.java delete mode 100644 src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java delete mode 100644 src/org/sosy_lab/java_smt/api/proofs/visitors/ProofVisitor.java delete mode 100644 src/org/sosy_lab/java_smt/api/proofs/visitors/package-info.java diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java b/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java deleted file mode 100644 index b0ba85b4dd..0000000000 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofDAG.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * This file is part of JavaSMT, - * an API wrapper for a collection of SMT solvers: - * https://github.com/sosy-lab/java-smt - * - * SPDX-FileCopyrightText: 2024 Dirk Beyer - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.sosy_lab.java_smt.api.proofs; - -import java.util.Collection; -import org.sosy_lab.java_smt.api.proofs.visitors.ProofVisitor; - -/** - * A DAG representing a proof. Each node in the DAG is a {@link ProofNode} and each edge is a - * directed edge from a parent node to a child node. - */ -public interface ProofDAG { - - /** - * Add a node to the DAG. - * - * @param node The node to be added to the DAG. - */ - void addNode(ProofNode node); - - /** - * Get a node from the DAG. - * - * @param nodeId The ID of the node. - * @return A {@link ProofNode} based on its ID. - */ - ProofNode getNode(int nodeId); - - /** - * Add an edge to the DAG. - * - * @param parentNodeId Predecessor - * @param childNodeId Successor - */ - void addEdge(int parentNodeId, int childNodeId); - - /** Get all nodes in the DAG. */ - Collection getNodes(); - - void accept(ProofVisitor visitor); // To allow traversal of the entire DAG -} diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java b/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java deleted file mode 100644 index 1516e5ae13..0000000000 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofFactory.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * This file is part of JavaSMT, - * an API wrapper for a collection of SMT solvers: - * https://github.com/sosy-lab/java-smt - * - * SPDX-FileCopyrightText: 2024 Dirk Beyer - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.sosy_lab.java_smt.api.proofs; - -import org.sosy_lab.java_smt.ResProofRule.ResAxiom; -import org.sosy_lab.java_smt.ResolutionProofDAG.AxiomProofNode; -import org.sosy_lab.java_smt.ResolutionProofDAG.ResolutionProofNode; -import org.sosy_lab.java_smt.api.Formula; -import org.sosy_lab.java_smt.api.ProverEnvironment; -import org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5ProofNode; - -/** - * A factory for creating proof nodes. The methods of this class are to be used in the ProofNode - * implementations of each solver to be able to convert the proof object given back by the solver to - * a proof in JavaSMT. - * - * @param The type of the proof object. - */ -public class ProofFactory { - - // private final FormulaCreator formulaCreator; - private final ProverEnvironment prover; - private final Solvers solver; - - enum Solvers { - OPENSMT, - MATHSAT5, - SMTINTERPOL, - Z3, - PRINCESS, - BOOLECTOR, - CVC4, - CVC5, - YICES2, - BITWUZLA - } - - protected ProofFactory(ProverEnvironment pProver, String pSolver) { - if (pProver == null) { - throw new NullPointerException("ProverEnvironment must not be null"); - } - if (pSolver == null) { - throw new NullPointerException("Solver name must not be null"); - } - prover = pProver; - solver = Solvers.valueOf(pSolver); - } - - protected ProofNode createProofNode(T proof) { - return createProofNode0(proof); - } - - protected ProofNode createProofNode0(T proof) { - - switch (solver) { - case MATHSAT5: - return Mathsat5ProofNode.fromMsatProof(prover, (long) proof); - case CVC5: - return null; - default: - throw new UnsupportedOperationException("Unsupported solver: " + solver); - } - } - - protected static ProofNode createSourceNode(ResAxiom rule, Formula formula) { - return new AxiomProofNode(rule, formula); - } - - protected static ProofNode createResolutionNode(Formula formula, Formula pivot) { - return new ResolutionProofNode(formula, pivot); - } -} diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java b/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java deleted file mode 100644 index 8eb324fa2e..0000000000 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofNode.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is part of JavaSMT, - * an API wrapper for a collection of SMT solvers: - * https://github.com/sosy-lab/java-smt - * - * SPDX-FileCopyrightText: 2024 Dirk Beyer - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.sosy_lab.java_smt.api.proofs; - -import java.util.List; -import org.sosy_lab.java_smt.api.Formula; - -/** - * A proof node in the proof DAG of a proof. - * - * @author Gabriel Carpio - */ -public interface ProofNode { - - /** Get the children of the proof node. */ - List getChildren(); - - void addChild(ProofNode child); - - boolean isLeaf(); - - /** - * Get the formula of the proof node. - * - * @return The formula of the proof node. - */ - Formula getFormula(); - - /** - * Get the id of the proof node. - * - * @return The id of the proof node. - */ - int getId(); - - ProofRule getRule(); -} diff --git a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java deleted file mode 100644 index af5e2a97dc..0000000000 --- a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofTraversalVisitor.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * This file is part of JavaSMT, - * an API wrapper for a collection of SMT solvers: - * https://github.com/sosy-lab/java-smt - * - * SPDX-FileCopyrightText: 2024 Dirk Beyer - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.sosy_lab.java_smt.api.proofs.visitors; - -import java.util.HashSet; -import java.util.Set; -import org.sosy_lab.java_smt.api.proofs.ProofDAG; -import org.sosy_lab.java_smt.api.proofs.ProofNode; - -public class ProofTraversalVisitor implements ProofVisitor { - private final Set visited = new HashSet<>(); - - @Override - public void visitNode(ProofNode node) { - if (visited.add(node)) { - for (ProofNode child : node.getChildren()) { - visitNode(child); - } - } - } - - @Override - public void visitDAG(ProofDAG dag) { - for (ProofNode node : dag.getNodes()) { - if (!visited.contains(node)) { - visitNode(node); - } - } - } -} diff --git a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofVisitor.java b/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofVisitor.java deleted file mode 100644 index 68dd15d6a8..0000000000 --- a/src/org/sosy_lab/java_smt/api/proofs/visitors/ProofVisitor.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * This file is part of JavaSMT, - * an API wrapper for a collection of SMT solvers: - * https://github.com/sosy-lab/java-smt - * - * SPDX-FileCopyrightText: 2024 Dirk Beyer - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.sosy_lab.java_smt.api.proofs.visitors; - -import org.sosy_lab.java_smt.api.proofs.ProofDAG; -import org.sosy_lab.java_smt.api.proofs.ProofNode; - -public interface ProofVisitor { - void visitNode(ProofNode node); - - void visitDAG(ProofDAG dag); -} diff --git a/src/org/sosy_lab/java_smt/api/proofs/visitors/package-info.java b/src/org/sosy_lab/java_smt/api/proofs/visitors/package-info.java deleted file mode 100644 index e242c9ee7b..0000000000 --- a/src/org/sosy_lab/java_smt/api/proofs/visitors/package-info.java +++ /dev/null @@ -1,11 +0,0 @@ -/* - * This file is part of JavaSMT, - * an API wrapper for a collection of SMT solvers: - * https://github.com/sosy-lab/java-smt - * - * SPDX-FileCopyrightText: 2024 Dirk Beyer - * - * SPDX-License-Identifier: Apache-2.0 - */ -/** These package is meant to provide the visitor classes used for proof handling. */ -package org.sosy_lab.java_smt.api.proofs.visitors; From 85d89a11917a9cd1c8ff65dcead852362077aa3f Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Thu, 15 May 2025 18:10:20 +0200 Subject: [PATCH 102/132] Renaming of classes, methods and adjusting constructors. 'Subproof' now needs a parameter 'Proof' for instantiating. --- ...tionProofDAG.java => ResolutionProof.java} | 31 +-- .../DebuggingBasicProverEnvironment.java | 4 +- .../StatisticsBasicProverEnvironment.java | 4 +- .../SynchronizedBasicProverEnvironment.java | 4 +- ...izedBasicProverEnvironmentWithContext.java | 4 +- .../java_smt/solvers/cvc5/CVC5Proof.java | 113 +++++++++++ .../java_smt/solvers/cvc5/CVC5ProofDAG.java | 122 ------------ ...hsat5ProofNode.java => Mathsat5Proof.java} | 57 +++--- .../solvers/mathsat5/Mathsat5ProofRule.java | 3 +- .../mathsat5/Mathsat5TheoremProver.java | 59 +++--- .../SmtInterpolAbstractProver.java | 38 ++-- ...rolProofDAG.java => SmtInterpolProof.java} | 39 ++-- .../sosy_lab/java_smt/solvers/z3/Z3Proof.java | 135 +++++++++++++ .../java_smt/solvers/z3/Z3ProofDAG.java | 150 --------------- .../java_smt/solvers/z3/Z3TheoremProver.java | 8 +- .../z3/Z3ToResolutionProofConverter.java | 181 +++++++++--------- .../java_smt/test/ProverEnvironmentTest.java | 19 +- 17 files changed, 474 insertions(+), 497 deletions(-) rename src/org/sosy_lab/java_smt/{ResolutionProofDAG.java => ResolutionProof.java} (61%) create mode 100644 src/org/sosy_lab/java_smt/solvers/cvc5/CVC5Proof.java delete mode 100644 src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofDAG.java rename src/org/sosy_lab/java_smt/solvers/mathsat5/{Mathsat5ProofNode.java => Mathsat5Proof.java} (82%) rename src/org/sosy_lab/java_smt/solvers/smtinterpol/{SmtInteprolProofDAG.java => SmtInterpolProof.java} (90%) create mode 100644 src/org/sosy_lab/java_smt/solvers/z3/Z3Proof.java delete mode 100644 src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDAG.java diff --git a/src/org/sosy_lab/java_smt/ResolutionProofDAG.java b/src/org/sosy_lab/java_smt/ResolutionProof.java similarity index 61% rename from src/org/sosy_lab/java_smt/ResolutionProofDAG.java rename to src/org/sosy_lab/java_smt/ResolutionProof.java index f62da7a4fb..5230a20976 100644 --- a/src/org/sosy_lab/java_smt/ResolutionProofDAG.java +++ b/src/org/sosy_lab/java_smt/ResolutionProof.java @@ -13,28 +13,31 @@ import java.util.Objects; import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.api.Formula; -import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.api.proofs.ProofRule; -import org.sosy_lab.java_smt.basicimpl.AbstractProofDAG; +import org.sosy_lab.java_smt.basicimpl.AbstractProof; /** * This class represents a resolution proof DAG. Its nodes might be of the type {@link - * AxiomProofNode} or {@link ResolutionProofNode}. It is used to represent proofs based on the + * AxiomSubproof} or {@link ResolutionSubproof}. It is used to represent proofs based on the * RESOLUTE proof format from SMTInterpol. * * @see ResProofRule */ -@SuppressWarnings("all") -public class ResolutionProofDAG extends AbstractProofDAG { +public class ResolutionProof extends AbstractProof { // Work in progress. The functionality of producing just nodes should be provided first. // The idea is to provide extended functionality (by providng a set of edges for example). - public static class ResolutionProofNode extends AbstractProofNode implements ProofNode { + public static class ResolutionSubproof extends AbstractSubproof implements Subproof { private final Formula pivot; - public ResolutionProofNode(Formula formula, Formula pivot) { - super(ResAxiom.RESOLUTION, Objects.requireNonNull(formula, "Formula must not be null")); + @Override + public void addChild(Subproof pSubproof) { + super.addChild(pSubproof); + } + + public ResolutionSubproof(Formula formula, Formula pivot, AbstractProof p) { + super(ResAxiom.RESOLUTION, Objects.requireNonNull(formula, "Formula must not be null"), p); this.pivot = Objects.requireNonNull(pivot, "Pivot must not be null"); } @@ -48,12 +51,18 @@ public ProofRule getRule() { } } - public static class AxiomProofNode extends AbstractProofNode implements ProofNode { + public static class AxiomSubproof extends AbstractSubproof implements Subproof { - public AxiomProofNode(ResAxiom rule, Formula formula) { + public AxiomSubproof(ResAxiom rule, Formula formula, AbstractProof proof) { super( Objects.requireNonNull(rule, "Rule must not be null"), - Objects.requireNonNull(formula, "Formula must not be null")); + Objects.requireNonNull(formula, "Formula must not be null"), + proof); + } + + @Override + protected void addChild(Subproof pSubproof) { + super.addChild(pSubproof); } } } diff --git a/src/org/sosy_lab/java_smt/delegate/debugging/DebuggingBasicProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/debugging/DebuggingBasicProverEnvironment.java index e4ae1227bd..597bbd36e4 100644 --- a/src/org/sosy_lab/java_smt/delegate/debugging/DebuggingBasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/delegate/debugging/DebuggingBasicProverEnvironment.java @@ -18,7 +18,7 @@ import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.Model; import org.sosy_lab.java_smt.api.SolverException; -import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.Proof.Subproof; class DebuggingBasicProverEnvironment implements BasicProverEnvironment { private final BasicProverEnvironment delegate; @@ -95,7 +95,7 @@ public Optional> unsatCoreOverAssumptions( } @Override - public ProofNode getProof() throws SolverException, InterruptedException { + public Subproof getProof() throws SolverException, InterruptedException { return delegate.getProof(); } diff --git a/src/org/sosy_lab/java_smt/delegate/statistics/StatisticsBasicProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/statistics/StatisticsBasicProverEnvironment.java index 70b6ccf74d..ca6fd52e35 100644 --- a/src/org/sosy_lab/java_smt/delegate/statistics/StatisticsBasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/delegate/statistics/StatisticsBasicProverEnvironment.java @@ -18,7 +18,7 @@ import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.Model; import org.sosy_lab.java_smt.api.SolverException; -import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.Proof.Subproof; import org.sosy_lab.java_smt.delegate.statistics.TimerPool.TimerWrapper; class StatisticsBasicProverEnvironment implements BasicProverEnvironment { @@ -101,7 +101,7 @@ public Optional> unsatCoreOverAssumptions( } @Override - public ProofNode getProof() throws SolverException, InterruptedException { + public Subproof getProof() throws SolverException, InterruptedException { return delegate.getProof(); } diff --git a/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedBasicProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedBasicProverEnvironment.java index b258c71b36..3c041b1145 100644 --- a/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedBasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedBasicProverEnvironment.java @@ -20,7 +20,7 @@ import org.sosy_lab.java_smt.api.Model; import org.sosy_lab.java_smt.api.SolverContext; import org.sosy_lab.java_smt.api.SolverException; -import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.Proof.Subproof; class SynchronizedBasicProverEnvironment implements BasicProverEnvironment { @@ -106,7 +106,7 @@ public ImmutableMap getStatistics() { } @Override - public ProofNode getProof() throws SolverException, InterruptedException { + public Subproof getProof() throws SolverException, InterruptedException { return delegate.getProof(); } diff --git a/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedBasicProverEnvironmentWithContext.java b/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedBasicProverEnvironmentWithContext.java index 364e37af49..347d898e68 100644 --- a/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedBasicProverEnvironmentWithContext.java +++ b/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedBasicProverEnvironmentWithContext.java @@ -22,7 +22,7 @@ import org.sosy_lab.java_smt.api.Model; import org.sosy_lab.java_smt.api.SolverContext; import org.sosy_lab.java_smt.api.SolverException; -import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.Proof.Subproof; class SynchronizedBasicProverEnvironmentWithContext implements BasicProverEnvironment { @@ -123,7 +123,7 @@ public ImmutableMap getStatistics() { } @Override - public ProofNode getProof() throws SolverException, InterruptedException { + public Subproof getProof() throws SolverException, InterruptedException { return delegate.getProof(); } diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5Proof.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5Proof.java new file mode 100644 index 0000000000..2253f9fc16 --- /dev/null +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5Proof.java @@ -0,0 +1,113 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.solvers.cvc5; + +import io.github.cvc5.CVC5ApiException; +import io.github.cvc5.Proof; +import io.github.cvc5.Term; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.proofs.ProofFrame; +import org.sosy_lab.java_smt.api.proofs.ProofRule; +import org.sosy_lab.java_smt.basicimpl.AbstractProof; + +public class CVC5Proof extends AbstractProof { + + CVC5Subproof generateProofImpl(Proof pProof, CVC5FormulaCreator formulaCreator) + throws CVC5ApiException { + + // boolean skippedScope = false; + + Deque stack = new ArrayDeque<>(); + + Map computed = new HashMap<>(); + + stack.push(new CVC5Frame(pProof)); + + while (!stack.isEmpty()) { + CVC5Frame frame = stack.peek(); + + if (!frame.isVisited()) { + + frame.setNumArgs(frame.getProof().getChildren().length); + frame.setAsVisited(true); + + for (int i = frame.getNumArgs() - 1; i >= 0; i--) { + Proof child = frame.getProof().getChildren()[i]; + if (!computed.containsKey(child)) { + stack.push(new CVC5Frame(child)); + } + } + } else { + stack.pop(); + int numChildren = frame.getNumArgs(); + + // if (frame.getProof().getRule().getValue() == 1 && !skippedScope) { + // Skip processing the frame if its rule is "SCOPE" + // This rule seems to just help the processing by CVC5 + // pProof = changeRoot(frame.getProof()); + // skippedScope = true; + // continue; + // } + + CVC5ProofRule proofRule = + Enum.valueOf(CVC5ProofRule.class, frame.getProof().getRule().toString()); + // ProofRule.fromName( + // CVC5ProofRule.class, frame.getProof().getRule().toString().toLowerCase()); + + // Generate formula + Term term = frame.getProof().getResult(); + Formula pFormula = formulaCreator.encapsulate(formulaCreator.getFormulaType(term), term); + CVC5Subproof pn = new CVC5Subproof(proofRule, pFormula, this); + for (int i = 0; i < numChildren; i++) { + Proof child = frame.getProof().getChildren()[i]; + + if (computed.containsKey(child)) { + pn.addChild(computed.get(child)); + } + } + computed.put(frame.getProof(), pn); + } + } + return computed.get(pProof); + } + + private static class CVC5Frame extends ProofFrame { + CVC5Frame(Proof proof) { + super(proof); + } + } + + public static class CVC5Subproof extends AbstractSubproof { + + public CVC5Subproof(ProofRule pProofRule, Formula formula, AbstractProof proof) { + + super(pProofRule, formula, proof); + } + + @Override + protected void addChild(Subproof pSubproof) { + super.addChild(pSubproof); + } + + // private static Proof changeRoot(Proof root) { + // return root.getArguments()[0]; + // } + + @Override + protected String proofAsString() { + return super.proofAsString(); + } + } +} diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofDAG.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofDAG.java deleted file mode 100644 index a1bd57f2c3..0000000000 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5ProofDAG.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * This file is part of JavaSMT, - * an API wrapper for a collection of SMT solvers: - * https://github.com/sosy-lab/java-smt - * - * SPDX-FileCopyrightText: 2024 Dirk Beyer - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.sosy_lab.java_smt.solvers.cvc5; - -import io.github.cvc5.CVC5ApiException; -import io.github.cvc5.Proof; -import io.github.cvc5.Term; -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.HashMap; -import java.util.Map; -import org.sosy_lab.java_smt.api.Formula; -import org.sosy_lab.java_smt.api.proofs.ProofFrame; -import org.sosy_lab.java_smt.api.proofs.ProofNode; -import org.sosy_lab.java_smt.api.proofs.ProofRule; -import org.sosy_lab.java_smt.basicimpl.AbstractProofDAG; - -public class CVC5ProofDAG extends AbstractProofDAG { - private static class CVC5Frame extends ProofFrame { - CVC5Frame(Proof proof) { - super(proof); - } - } - - public static class CVC5ProofNode extends AbstractProofNode { - - public CVC5ProofNode(ProofRule pProofRule, Formula formula) { - - super(pProofRule, formula); - } - - static CVC5ProofNode fromCVC5Proof(Proof pProof, CVC5FormulaCreator formulaCreator) - throws CVC5ApiException { - - boolean skippedScope = false; - - Deque stack = new ArrayDeque<>(); - - Map computed = new HashMap<>(); - - stack.push(new CVC5Frame(pProof)); - - while (!stack.isEmpty()) { - CVC5Frame frame = stack.peek(); - - if (!frame.isVisited()) { - - frame.setNumArgs(frame.getProof().getChildren().length); - frame.setAsVisited(true); - - for (int i = frame.getNumArgs() - 1; i >= 0; i--) { - Proof child = frame.getProof().getChildren()[i]; - if (!computed.containsKey(child)) { - stack.push(new CVC5Frame(child)); - } - } - } else { - stack.pop(); - int numChildren = frame.getNumArgs(); - - if (frame.getProof().getRule().getValue() == 1 && !skippedScope) { - // Skip processing the frame if its rule is "SCOPE" - // This rule seems to just help the processing by CVC5 - pProof = changeRoot(frame.getProof()); - skippedScope = true; - continue; - } - - CVC5ProofRule proofRule = - Enum.valueOf(CVC5ProofRule.class, frame.getProof().getRule().toString()); - // ProofRule.fromName( - // CVC5ProofRule.class, frame.getProof().getRule().toString().toLowerCase()); - - // Generate formula - Term term = frame.getProof().getResult(); - Formula pFormula = formulaCreator.encapsulate(formulaCreator.getFormulaType(term), term); - CVC5ProofNode pn = new CVC5ProofNode(proofRule, pFormula); - for (int i = 0; i < numChildren; i++) { - Proof child = frame.getProof().getChildren()[i]; - - if (computed.containsKey(child)) { - pn.addChild(computed.get(child)); - } - } - computed.put(frame.getProof(), pn); - } - } - return computed.get(pProof); - } - - private static Proof changeRoot(Proof root) { - return root.getChildren()[0]; - } - - String asString(int indentLevel) { - StringBuilder proof = new StringBuilder(); - String indent = " ".repeat(indentLevel); - - proof.append(indent).append("Formula: ").append(getFormula().toString()).append("\n"); - proof.append(indent).append("Rule: ").append(getRule().getName()).append("\n"); - proof.append(indent).append("No. Children: ").append(getChildren().size()).append("\n"); - proof.append(indent).append("ID: ").append(getId()).append("\n"); - proof.append(indent).append("leaf: ").append(isLeaf()).append("\n"); - - int i = 0; - for (ProofNode child : getChildren()) { - proof.append(indent).append("Child ").append(++i).append(":\n"); - proof.append(((CVC5ProofNode) child).asString(indentLevel + 1)); - } - - return proof.toString(); - } - } -} diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5Proof.java similarity index 82% rename from src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java rename to src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5Proof.java index 4e9230d3ee..ad39f34ef3 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofNode.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5Proof.java @@ -27,22 +27,11 @@ import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.proofs.ProofFrame; -import org.sosy_lab.java_smt.api.proofs.ProofNode; import org.sosy_lab.java_smt.api.proofs.ProofRule; -import org.sosy_lab.java_smt.basicimpl.AbstractProofDAG.AbstractProofNode; +import org.sosy_lab.java_smt.basicimpl.AbstractProof; import org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5ProofRule.Rule; -public class Mathsat5ProofNode extends AbstractProofNode { - - protected Mathsat5ProofNode(@Nullable ProofRule rule, Formula formula) { - super(rule, formula); - } - - protected static class MsatProofFrame extends ProofFrame { - MsatProofFrame(Long proof) { - super(proof); - } - } +class Mathsat5Proof extends AbstractProof { /** * Creates a proof node from a MathSAT5 proof object. @@ -55,10 +44,10 @@ protected static class MsatProofFrame extends ProofFrame { * @param rootProof The root proof object. * @return The proof node. */ - public static Mathsat5ProofNode fromMsatProof(ProverEnvironment pProver, long rootProof) { + public Mathsat5Subproof fromMsatProof(ProverEnvironment pProver, long rootProof) { Deque stack = new ArrayDeque<>(); - Map computed = new HashMap<>(); + Map computed = new HashMap<>(); stack.push(new MsatProofFrame(rootProof)); @@ -113,11 +102,11 @@ public static Mathsat5ProofNode fromMsatProof(ProverEnvironment pProver, long ro proofRule = new Mathsat5ProofRule(rule); } - Mathsat5ProofNode node; + Mathsat5Subproof node; Mathsat5TheoremProver prover = (Mathsat5TheoremProver) pProver; Formula formula = generateFormula(frame, prover, proofRule); - node = new Mathsat5ProofNode(proofRule, formula); + node = new Mathsat5Subproof(proofRule, formula, this); // Retrieve computed child nodes and attach them. In this case the subtraction is due to // the processing of the theory-lemma rule. @@ -128,7 +117,7 @@ public static Mathsat5ProofNode fromMsatProof(ProverEnvironment pProver, long ro long child = msat_proof_get_child(frame.getProof(), i); - Mathsat5ProofNode childNode = computed.get(child); + Mathsat5Subproof childNode = computed.get(child); if (childNode != null) { node.addChild(childNode); } @@ -140,7 +129,7 @@ public static Mathsat5ProofNode fromMsatProof(ProverEnvironment pProver, long ro } @Nullable - private static Formula generateFormula( + private Formula generateFormula( MsatProofFrame frame, Mathsat5TheoremProver prover, ProofRule rule) { Mathsat5FormulaCreator formulaCreator = prover.creator; Formula formula = null; @@ -178,24 +167,26 @@ private static Formula generateFormula( return formula; } - String asString() { - return asString(0); + protected static class MsatProofFrame extends ProofFrame { + MsatProofFrame(Long proof) { + super(proof); + } } - private String asString(int indentLevel) { - StringBuilder proof = new StringBuilder(); - String indent = " ".repeat(indentLevel); - if (getFormula() != null) { - proof.append(indent).append("Formula: ").append(getFormula().toString()).append("\n"); + class Mathsat5Subproof extends AbstractSubproof { + + protected Mathsat5Subproof(@Nullable ProofRule rule, Formula formula, Mathsat5Proof proof) { + super(rule, formula, proof); + } + + @Override + protected void addChild(Subproof subproof) { + super.addChild(subproof); } - proof.append(indent).append("Rule: ").append(getRule().getName()).append("\n"); - proof.append(indent).append("No. Children: ").append(getChildren().size()).append("\n"); - int i = 0; - for (ProofNode child : getChildren()) { - proof.append(indent).append("Child ").append(++i).append(":\n"); - proof.append(((Mathsat5ProofNode) child).asString(indentLevel + 1)); + @Override + protected String proofAsString() { + return super.proofAsString(); } - return proof.toString(); } } diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java index 9458655b7b..6eb1cc1129 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5ProofRule.java @@ -26,7 +26,8 @@ enum Rule implements ProofRule { CLAUSE_HYP(), // " which are the clauses of the (CNF conversion of the) input problem. They have // a list of terms as children" - EMPTY(); //We introduce this rule for term nodes that do not have a proof rule attached, even + EMPTY(); // We introduce this rule for term nodes that do not have a proof rule attached, even + // if they are pivots. In the future it might be good to a PIVOT rule so that those can have // that instead. diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java index d8ca9952c8..4727582a1d 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java @@ -32,10 +32,10 @@ import org.sosy_lab.java_smt.api.QuantifiedFormulaManager.Quantifier; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; -import org.sosy_lab.java_smt.api.proofs.ProofFactory; -import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.Proof.Subproof; import org.sosy_lab.java_smt.api.visitors.BooleanFormulaVisitor; import org.sosy_lab.java_smt.api.visitors.TraversalProcess; +import org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5Proof.Mathsat5Subproof; import org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5ProofRule.Rule; class Mathsat5TheoremProver extends Mathsat5AbstractProver implements ProverEnvironment { @@ -63,45 +63,48 @@ protected Void addConstraintImpl(BooleanFormula constraint) throws InterruptedEx } @Override - public ProofNode getProof() throws SolverException, InterruptedException { + public Subproof getProof() throws SolverException, InterruptedException { Preconditions.checkState(!closed); Preconditions.checkState(this.isUnsat()); - ProofNode pn; + Mathsat5Proof proof = new Mathsat5Proof(); + long pm = msat_get_proof_manager(curEnv); - long proof = msat_get_proof(pm); - pn = Mathsat5ProofNode.fromMsatProof(this, proof); - clausifyResChain(pn, context.getFormulaManager().getBooleanFormulaManager()); + long msatProof = msat_get_proof(pm); + Mathsat5Subproof root = proof.fromMsatProof(this, msatProof); + clausifyResChain(root, context.getFormulaManager().getBooleanFormulaManager()); msat_destroy_proof_manager(pm); - return pn; + return root; // return getProof0(); } // update all RES_CHAIN nodes in the proof DAG by computing resolution // formulas and return the updated root node with formulas attached. - private void clausifyResChain(ProofNode root, BooleanFormulaManager bfmgr) { - Map visited = new HashMap<>(); // Track visited nodes - Deque stack = new ArrayDeque<>(); + private void clausifyResChain(Subproof root, BooleanFormulaManager bfmgr) { + Map visited = new HashMap<>(); // Track visited nodes + Deque stack = new ArrayDeque<>(); stack.push(root); // Start with the root node visited.put(root, Boolean.FALSE); // Mark root as unvisited while (!stack.isEmpty()) { - ProofNode node = stack.peek(); // Look at the top node, but don't pop yet + Subproof node = stack.peek(); // Look at the top node, but don't pop yet if (visited.get(node).equals(Boolean.FALSE)) { // First time visiting this node visited.put(node, Boolean.TRUE); // Mark node as visited // Push all children onto stack - List children = node.getChildren(); - for (int i = children.size() - 1; i >= 0; i--) { - ProofNode child = children.get(i); - if (!visited.containsKey(child)) { - stack.push(child); // Only push unvisited children - visited.put(child, Boolean.FALSE); // Mark child as unvisited + if (!node.isLeaf()) { + List children = node.getArguments(); + for (int i = children.size() - 1; i >= 0; i--) { + Subproof child = children.get(i); + if (!visited.containsKey(child)) { + stack.push(child); // Only push unvisited children + visited.put(child, Boolean.FALSE); // Mark child as unvisited + } } } } else { @@ -117,8 +120,8 @@ private void clausifyResChain(ProofNode root, BooleanFormulaManager bfmgr) { } // process proof nodes and compute formulas for res-chain nodes - private void processResChain(ProofNode node, BooleanFormulaManager bfmgr) { - List children = node.getChildren(); + private void processResChain(Subproof node, BooleanFormulaManager bfmgr) { + List children = node.getArguments(); // If the current node is a RES_CHAIN, compute the resolved formula if (node.getRule().equals(Rule.RES_CHAIN)) { @@ -139,7 +142,7 @@ private void processResChain(ProofNode node, BooleanFormulaManager bfmgr) { } // Store the resolved formula in the current node - ((Mathsat5ProofNode) node).setFormula(current); + ((Mathsat5Subproof) node).setFormula(current); } } @@ -333,18 +336,4 @@ public TraversalProcess visitBoundVar(BooleanFormula var, int index) { return isComplement[0]; } - - protected ProofNode getProof0() { - var proofFactory = - new ProofFactory(this, "MATHSAT5") { - public ProofNode createProofWrapper(long pProof) { - return this.createProofNode(pProof); - } - }; - long pm = msat_get_proof_manager(curEnv); - long proof = msat_get_proof(pm); - ProofNode pn = proofFactory.createProofWrapper(proof); - msat_destroy_proof_manager(pm); - return pn; - } } diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java index bf314eee48..20ba7cfb69 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java @@ -48,15 +48,15 @@ import org.sosy_lab.java_smt.api.QuantifiedFormulaManager.Quantifier; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; -import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.Proof.Subproof; import org.sosy_lab.java_smt.api.visitors.BooleanFormulaVisitor; import org.sosy_lab.java_smt.api.visitors.TraversalProcess; import org.sosy_lab.java_smt.basicimpl.AbstractProver; import org.sosy_lab.java_smt.basicimpl.CachingModel; import org.sosy_lab.java_smt.basicimpl.FormulaCreator; -import org.sosy_lab.java_smt.solvers.smtinterpol.SmtInteprolProofDAG.SmtInterpolProofNode; -import org.sosy_lab.java_smt.solvers.smtinterpol.SmtInteprolProofDAG.SmtInterpolProofNodeCreator; -import org.sosy_lab.java_smt.solvers.smtinterpol.SmtInteprolProofDAG.SmtInterpolProofNodeCreator.ProvitionalProofNode; +import org.sosy_lab.java_smt.solvers.smtinterpol.SmtInterpolProof.SmtInterpolProofNodeCreator; +import org.sosy_lab.java_smt.solvers.smtinterpol.SmtInterpolProof.SmtInterpolProofNodeCreator.ProvitionalProofNode; +import org.sosy_lab.java_smt.solvers.smtinterpol.SmtInterpolProof.SmtInterpolSubproof; @SuppressWarnings("ClassTypeParameterName") abstract class SmtInterpolAbstractProver extends AbstractProver { @@ -227,7 +227,7 @@ public ImmutableMap getStatistics() { } @Override - public ProofNode getProof() { + public Subproof getProof() { checkState(!closed); checkGenerateProofs(); @@ -243,9 +243,10 @@ public ProofNode getProof() { } SmtInterpolProofNodeCreator pc = - new SmtInterpolProofNodeCreator((SmtInterpolFormulaCreator) this.creator); + new SmtInterpolProofNodeCreator( + (SmtInterpolFormulaCreator) this.creator, new SmtInterpolProof()); ProvitionalProofNode ppn = pc.createPPNDag(tProof); - ProofNode proof = pc.createProof(ppn); + Subproof proof = pc.createProof(ppn); // Before being able to perfom resolution, we need to calculate the formulas resulting from // applying the axioms, as it stands, just the input for the axiom is stored. // clausifyResChain(proof, mgr.getBooleanFormulaManager()); @@ -253,11 +254,6 @@ public ProofNode getProof() { return proof; } - // TODO: Delete this method - protected Term smtInterpolGetProof() { - return env.getProof(); - } - @Override public void close() { if (!closed) { @@ -299,24 +295,24 @@ public R allSat(AllSatCallback callback, List important) // update all RES_CHAIN nodes in the proof DAG by computing resolution // formulas and return the updated root node with formulas attached. @SuppressWarnings("unused") - private void clausifyResChain(ProofNode root, BooleanFormulaManager bfmgr) { - Map visited = new HashMap<>(); // Track visited nodes - ArrayDeque stack = new ArrayDeque<>(); + private void clausifyResChain(Subproof root, BooleanFormulaManager bfmgr) { + Map visited = new HashMap<>(); // Track visited nodes + ArrayDeque stack = new ArrayDeque<>(); stack.push(root); // Start with the root node visited.put(root, Boolean.FALSE); // Mark root as unvisited while (!stack.isEmpty()) { - ProofNode node = stack.peek(); // Look at the top node, but don't pop yet + Subproof node = stack.peek(); // Look at the top node, but don't pop yet if (visited.get(node).equals(Boolean.FALSE)) { // First time visiting this node visited.put(node, Boolean.TRUE); // Mark node as visited // Push all children onto stack - List children = node.getChildren(); + List children = node.getArguments(); for (int i = children.size() - 1; i >= 0; i--) { - ProofNode child = children.get(i); + Subproof child = children.get(i); if (!visited.containsKey(child)) { stack.push(child); // Only push unvisited children visited.put(child, Boolean.FALSE); // Mark child as unvisited @@ -335,8 +331,8 @@ private void clausifyResChain(ProofNode root, BooleanFormulaManager bfmgr) { } // process proof nodes and compute formulas for res-chain nodes - private void processResChain(ProofNode node, BooleanFormulaManager bfmgr) { - List children = node.getChildren(); + private void processResChain(Subproof node, BooleanFormulaManager bfmgr) { + List children = node.getArguments(); // If the current node is a RES_CHAIN, compute the resolved formula if (node.getRule().equals(ResAxiom.RESOLUTION)) { @@ -357,7 +353,7 @@ private void processResChain(ProofNode node, BooleanFormulaManager bfmgr) { } // Store the resolved formula in the current node - ((SmtInterpolProofNode) node).setFormula(current); + ((SmtInterpolSubproof) node).setFormula(current); } } diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInteprolProofDAG.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProof.java similarity index 90% rename from src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInteprolProofDAG.java rename to src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProof.java index 56afb25a14..b1bfa50f8d 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInteprolProofDAG.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProof.java @@ -27,7 +27,7 @@ import org.sosy_lab.java_smt.ResProofRule.ResAxiom; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.ProofRule; -import org.sosy_lab.java_smt.basicimpl.AbstractProofDAG; +import org.sosy_lab.java_smt.basicimpl.AbstractProof; /** * This class represents a SMTInterpol proof DAG in the JavaSMT proof interface. Many formulas that @@ -38,7 +38,7 @@ * offering a proof rule at every step of the proof as well as allowing to display the pivots for * resolution steps. */ -class SmtInteprolProofDAG extends AbstractProofDAG { +class SmtInterpolProof extends AbstractProof { protected enum Rules implements ProofRule { RUP, PIVOT; @@ -49,22 +49,34 @@ public String getName() { } } - protected static class SmtInterpolProofNode extends AbstractProofNode { - SmtInterpolProofNode(ProofRule pRule, Formula pFormula) { - super(pRule, pFormula); + protected static class SmtInterpolSubproof extends AbstractSubproof { + SmtInterpolSubproof(ProofRule pRule, Formula pFormula, SmtInterpolProof pProof) { + super(pRule, pFormula, pProof); + } + + @Override + protected void addChild(Subproof pSubproof) { + super.addChild(pSubproof); + } + + @Override + protected String proofAsString() { + return super.proofAsString(); } } static class SmtInterpolProofNodeCreator { + private final SmtInterpolProof proof; private final SmtInterpolFormulaCreator creator; - SmtInterpolProofNodeCreator(SmtInterpolFormulaCreator pCreator) { + SmtInterpolProofNodeCreator(SmtInterpolFormulaCreator pCreator, SmtInterpolProof pProof) { creator = pCreator; + proof = pProof; } - SmtInterpolProofNode createProof(ProvitionalProofNode pProofNode) { + SmtInterpolSubproof createProof(ProvitionalProofNode pProofNode) { Deque stack = new ArrayDeque<>(); - Map computed = new HashMap<>(); + Map computed = new HashMap<>(); stack.push(pProofNode); @@ -97,7 +109,8 @@ SmtInterpolProofNode createProof(ProvitionalProofNode pProofNode) { Term t = proofNode.formulas.get(0); formula = creator.encapsulate(creator.getFormulaType(t), t); } - SmtInterpolProofNode pn = new SmtInterpolProofNode(proofNode.proofRule, formula); + SmtInterpolSubproof pn = + new SmtInterpolSubproof(proofNode.proofRule, formula, this.proof); for (int i = 0; i < proofNode.children.size(); i++) { ProvitionalProofNode child = proofNode.children.get(i); if (computed.containsKey(child)) { @@ -248,11 +261,11 @@ void addTermsFromAnnotationValue(Object[] values, boolean isProves) { } // Just for testing purposes - protected String asString() { - return asString(0); + protected String proofAsString() { + return proofAsString(0); } - String asString(int indentLevel) { + String proofAsString(int indentLevel) { StringBuilder sb = new StringBuilder(); String indent = " ".repeat(indentLevel); @@ -288,7 +301,7 @@ String asString(int indentLevel) { } else { for (ProvitionalProofNode child : children) { if (child != null) { - sb.append(child.asString(indentLevel + 2)); + sb.append(child.proofAsString(indentLevel + 2)); } else { sb.append(indent).append(" null\n"); } diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3Proof.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3Proof.java new file mode 100644 index 0000000000..907090acf5 --- /dev/null +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3Proof.java @@ -0,0 +1,135 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.solvers.z3; + +import com.microsoft.z3.Native; +import com.microsoft.z3.enumerations.Z3_decl_kind; +import com.microsoft.z3.enumerations.Z3_sort_kind; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.proofs.ProofFrame; +import org.sosy_lab.java_smt.api.proofs.ProofRule; +import org.sosy_lab.java_smt.basicimpl.AbstractProof; +import org.sosy_lab.java_smt.basicimpl.FormulaCreator; + +public class Z3Proof extends AbstractProof { + private static class Frame extends ProofFrame { + protected Frame(Long proof) { + super(proof); + } + } + + public static class Z3Subproof extends AbstractSubproof { + + Z3Subproof(Formula pFormula, ProofRule pProofRule, AbstractProof pProof) { + super(pProofRule, pFormula, pProof); + } + + @Override + protected void addChild(Subproof child) { + super.addChild(child); + } + + @Override + protected String proofAsString() { + return super.proofAsString(); + } + } + + /** + * This transformation omits one level of the proofs from Z3, as the leaves in that case are the + * operands of the boolean formulas used as the very first proof steps in the whole proof .E.g., + * when asserting (or (not q2) q1) that produces a single {@link Z3Subproof}, but the input for + * that is a whole subtree from Z3 composed of the asseertion, the OR operation and the operands. + * + * @param rootProof The root of proof DAG to be converted + * @param formulaCreator The {@link FormulaCreator} to be able to produce the {@link Formula}s + * @return The root of converted proof DAG as {@link Z3Subproof} + */ + Z3Subproof generateProofImpl(long rootProof, Z3FormulaCreator formulaCreator) { + long z3context = formulaCreator.getEnv(); + // proof ast to be processed wrapped inside a frame + Deque stack = new ArrayDeque<>(); + + // proof ast has been converted into ProofNode + Map computed = new HashMap<>(); + + stack.push(new Frame(rootProof)); + + while (!stack.isEmpty()) { + Frame frame = stack.peek(); + + // prevent processing the same proof ast multiple times + if (!frame.isVisited()) { + + Native.incRef(z3context, frame.getProof()); + + // The number of children of the proof node + frame.setNumArgs(Native.getAppNumArgs(z3context, frame.getProof())); + frame.setAsVisited(true); + + for (int i = frame.getNumArgs() - 2; i >= 0; i--) { + long arg = Native.getAppArg(z3context, frame.getProof(), i); + + if (!computed.containsKey(arg)) { + stack.push(new Frame(arg)); + } + } + } else { + + stack.pop(); + int numArgs = frame.getNumArgs(); + Formula formula; + + // needed for the sortKind + long sort = Native.getSort(z3context, frame.getProof()); + long sortKind = Native.getSortKind(z3context, sort); + Z3_sort_kind sk = Z3_sort_kind.fromInt((int) sortKind); + if (sk != Z3_sort_kind.Z3_UNKNOWN_SORT) { + // This should be a proof sort, this is not included in the enum class provided by the + // API + formula = + formulaCreator.encapsulate( + formulaCreator.getFormulaType(frame.getProof()), frame.getProof()); + } else { + // Return the i-th argument of the given application. The formula resulting from + // applying the proof rule is the last argument of the proof node. + long z3expr = Native.getAppArg(z3context, frame.getProof(), numArgs - 1); + formula = formulaCreator.encapsulate(formulaCreator.getFormulaType(z3expr), z3expr); + } + int declKind = + Native.getDeclKind(z3context, Native.getAppDecl(z3context, frame.getProof())); + ProofRule proofRule = getPRfromDK(declKind); + Z3Subproof node = new Z3Subproof(formula, proofRule, this); + + for (int i = 0; i < numArgs - 1; i++) { + long arg = Native.getAppArg(z3context, frame.getProof(), i); + if (computed.containsKey(arg)) { + node.addChild(computed.get(arg)); + } + } + computed.put(frame.getProof(), node); + Native.decRef(z3context, frame.getProof()); + } + } + return computed.get(rootProof); + } + + private static ProofRule getPRfromDK(int declKind) { + String rawName = Z3_decl_kind.fromInt(declKind).name(); + String prName = rawName.replaceFirst("Z3_OP_PR_", ""); + // return ProofRule.fromName(Z3ProofRule.class, prName); + return Enum.valueOf(Z3ProofRule.class, prName); + } +} diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDAG.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDAG.java deleted file mode 100644 index b8775a76be..0000000000 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ProofDAG.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * This file is part of JavaSMT, - * an API wrapper for a collection of SMT solvers: - * https://github.com/sosy-lab/java-smt - * - * SPDX-FileCopyrightText: 2024 Dirk Beyer - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.sosy_lab.java_smt.solvers.z3; - -import com.microsoft.z3.Native; -import com.microsoft.z3.enumerations.Z3_decl_kind; -import com.microsoft.z3.enumerations.Z3_sort_kind; -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.HashMap; -import java.util.Map; -import org.sosy_lab.java_smt.api.Formula; -import org.sosy_lab.java_smt.api.proofs.ProofFrame; -import org.sosy_lab.java_smt.api.proofs.ProofNode; -import org.sosy_lab.java_smt.api.proofs.ProofRule; -import org.sosy_lab.java_smt.basicimpl.AbstractProofDAG; -import org.sosy_lab.java_smt.basicimpl.FormulaCreator; - -public class Z3ProofDAG extends AbstractProofDAG { - private static class Frame extends ProofFrame { - protected Frame(Long proof) { - super(proof); - } - } - - public static class Z3ProofNode extends AbstractProofNode { - - Z3ProofNode(Formula pFormula, ProofRule pProofRule) { - super(pProofRule, pFormula); - } - - /** - * This transformation omits one level of the proofs from Z3, as the leaves in that case are the - * operands of the boolean formulas used as the very first proof steps in the whole proof .E.g., - * when asserting (or (not q2) q1) that produces a single {@link Z3ProofNode}, but the input for - * that is a whole subtree from Z3 composed of the asseertion, the OR operation and the - * operands. - * - * @param rootProof The root of proof DAG to be converted - * @param formulaCreator The {@link FormulaCreator} to be able to produce the {@link Formula}s - * @return The root of converted proof DAG as {@link Z3ProofNode} - */ - static Z3ProofNode fromZ3Proof(long rootProof, Z3FormulaCreator formulaCreator) { - long z3context = formulaCreator.getEnv(); - // proof ast to be processed wrapped inside a frame - Deque stack = new ArrayDeque<>(); - - // proof ast has been converted into ProofNode - Map computed = new HashMap<>(); - - stack.push(new Frame(rootProof)); - - while (!stack.isEmpty()) { - Frame frame = stack.peek(); - - // prevent processing the same proof ast multiple times - if (!frame.isVisited()) { - - Native.incRef(z3context, frame.getProof()); - - // The number of children of the proof node - frame.setNumArgs(Native.getAppNumArgs(z3context, frame.getProof())); - frame.setAsVisited(true); - - for (int i = frame.getNumArgs() - 2; i >= 0; i--) { - long arg = Native.getAppArg(z3context, frame.getProof(), i); - - if (!computed.containsKey(arg)) { - stack.push(new Frame(arg)); - } - } - } else { - - stack.pop(); - int numArgs = frame.getNumArgs(); - Formula formula; - - // needed for the sortKind - long sort = Native.getSort(z3context, frame.getProof()); - long sortKind = Native.getSortKind(z3context, sort); - Z3_sort_kind sk = Z3_sort_kind.fromInt((int) sortKind); - if (sk != Z3_sort_kind.Z3_UNKNOWN_SORT) { - // This should be a proof sort, this is not included in the enum class provided by the - // API - formula = - formulaCreator.encapsulate( - formulaCreator.getFormulaType(frame.getProof()), frame.getProof()); - } else { - // Return the i-th argument of the given application. The formula resulting from - // applying the proof rule is the last argument of the proof node. - long z3expr = Native.getAppArg(z3context, frame.getProof(), numArgs - 1); - formula = formulaCreator.encapsulate(formulaCreator.getFormulaType(z3expr), z3expr); - } - int declKind = - Native.getDeclKind(z3context, Native.getAppDecl(z3context, frame.getProof())); - ProofRule proofRule = getPRfromDK(declKind); - Z3ProofDAG.Z3ProofNode node = new Z3ProofDAG.Z3ProofNode(formula, proofRule); - - for (int i = 0; i < numArgs - 1; i++) { - long arg = Native.getAppArg(z3context, frame.getProof(), i); - if (computed.containsKey(arg)) { - node.addChild(computed.get(arg)); - } - } - computed.put(frame.getProof(), node); - Native.decRef(z3context, frame.getProof()); - } - } - return computed.get(rootProof); - } - - private static ProofRule getPRfromDK(int declKind) { - String rawName = Z3_decl_kind.fromInt(declKind).name(); - String prName = rawName.replaceFirst("Z3_OP_PR_", ""); - // return ProofRule.fromName(Z3ProofRule.class, prName); - return Enum.valueOf(Z3ProofRule.class, prName); - } - - String asString() { - return asString(0); - } - - private String asString(int indentLevel) { - StringBuilder proof = new StringBuilder(); - String indent = " ".repeat(indentLevel); - - proof.append(indent).append("Formula: ").append(getFormula().toString()).append("\n"); - proof.append(indent).append("Rule: ").append(getRule().getName()).append("\n"); - proof.append(indent).append("No. Children: ").append(getChildren().size()).append("\n"); - proof.append(indent).append("ID: ").append(getId()).append("\n"); - proof.append(indent).append("leaf: ").append(isLeaf()).append("\n"); - - int i = 0; - for (ProofNode child : getChildren()) { - proof.append(indent).append("Child ").append(++i).append(":\n"); - proof.append(((Z3ProofNode) child).asString(indentLevel + 1)); - } - - return proof.toString(); - } - } -} diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java index d75f5d6334..181873490a 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3TheoremProver.java @@ -25,8 +25,7 @@ import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; import org.sosy_lab.java_smt.api.UserPropagator; -import org.sosy_lab.java_smt.api.proofs.ProofNode; -import org.sosy_lab.java_smt.solvers.z3.Z3ProofDAG.Z3ProofNode; +import org.sosy_lab.java_smt.api.proofs.Proof.Subproof; class Z3TheoremProver extends Z3AbstractProver implements ProverEnvironment { @@ -149,7 +148,7 @@ protected long getZ3Model() { } @Override - public ProofNode getProof() throws SolverException, InterruptedException { + public Subproof getProof() throws SolverException, InterruptedException { Preconditions.checkState(!closed); Preconditions.checkState(this.isUnsat()); long proofAst; @@ -158,7 +157,8 @@ public ProofNode getProof() throws SolverException, InterruptedException { } catch (Z3Exception e) { throw creator.handleZ3Exception(e); } - return Z3ProofNode.fromZ3Proof(proofAst, creator); + Z3Proof proof = new Z3Proof(); + return proof.generateProofImpl(proofAst, creator); } @Override diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java index 55b0f08ab6..d2903e217a 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java @@ -18,17 +18,18 @@ import java.util.List; import java.util.Map; import org.sosy_lab.java_smt.ResProofRule.ResAxiom; -import org.sosy_lab.java_smt.ResolutionProofDAG; -import org.sosy_lab.java_smt.ResolutionProofDAG.AxiomProofNode; -import org.sosy_lab.java_smt.ResolutionProofDAG.ResolutionProofNode; +import org.sosy_lab.java_smt.ResolutionProof; +import org.sosy_lab.java_smt.ResolutionProof.AxiomSubproof; +import org.sosy_lab.java_smt.ResolutionProof.ResolutionSubproof; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.BooleanFormulaManager; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.FunctionDeclaration; import org.sosy_lab.java_smt.api.QuantifiedFormulaManager.Quantifier; -import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.Proof.Subproof; import org.sosy_lab.java_smt.api.visitors.BooleanFormulaVisitor; import org.sosy_lab.java_smt.api.visitors.TraversalProcess; +import org.sosy_lab.java_smt.solvers.z3.Z3Proof.Z3Subproof; /** * Converts a Z3 proof into a format based on the RESOLUTE proof format. @@ -52,23 +53,27 @@ public class Z3ToResolutionProofConverter { // This class is inclompete and curr private final BooleanFormulaManager bfm; + private Z3Proof proof; + Z3ToResolutionProofConverter(Z3FormulaManager creator) { formulaManager = creator; bfm = formulaManager.getBooleanFormulaManager(); + proof = new Z3Proof(); } private static final Map ruleMapping = new HashMap<>(); /** - * This method converts a set of Z3ProofNodes into a {@link ResolutionProofDAG}. + * This method converts a set of Z3ProofNodes into a {@link ResolutionProof}. * * @param z3ProofNodes the nodes to be converted. - * @return {@link ResolutionProofDAG} + * @return {@link ResolutionProof} */ - static ResolutionProofDAG convertToResolutionProofDag(Z3ProofDAG.Z3ProofNode[] z3ProofNodes) { - ResolutionProofDAG dag = new ResolutionProofDAG(); + ResolutionProof convertToResolutionProofDag(Z3Subproof[] z3ProofNodes) { + ResolutionProof dag = new ResolutionProof(); + this.proof = (Z3Proof) z3ProofNodes[0].getDAG(); - for (Z3ProofDAG.Z3ProofNode z3Node : z3ProofNodes) { + for (Z3Subproof z3Node : z3ProofNodes) { if (z3Node.getRule() == MODUS_PONENS) { continue; // process mp continue here to avoid empty if block } else { @@ -161,13 +166,13 @@ public List extractEquivalenceOperands(BooleanFormula formula) { } /** - * Converts a {@link Z3ProofDAG.Z3ProofNode} into either a {@link ResolutionProofNode} or a {@link - * AxiomProofNode}, depending on its rule. + * Converts a {@link Z3Subproof} into either a {@link ResolutionSubproof} or a {@link + * AxiomSubproof}, depending on its rule. * - * @param node the {@link Z3ProofDAG.Z3ProofNode} to convert - * @return the resulting {@link ProofNode} + * @param node the {@link Z3Subproof} to convert + * @return the resulting {@link Subproof} */ - ProofNode handleNode(Z3ProofDAG.Z3ProofNode node) { + Subproof handleNode(Z3Subproof node) { Z3ProofRule rule = (Z3ProofRule) node.getRule(); switch (rule) { @@ -302,49 +307,49 @@ ProofNode handleNode(Z3ProofDAG.Z3ProofNode node) { } } - ProofNode handleTrue(Z3ProofDAG.Z3ProofNode node) { + Subproof handleTrue(Z3Subproof node) { BooleanFormula formula = (BooleanFormula) node.getFormula(); - AxiomProofNode pn = new AxiomProofNode(ResAxiom.TRUE_POSITIVE, formula); + AxiomSubproof pn = new AxiomSubproof(ResAxiom.TRUE_POSITIVE, formula, proof); return pn; } - ProofNode handleAsserted(Z3ProofDAG.Z3ProofNode node) { + Subproof handleAsserted(Z3Subproof node) { BooleanFormula formula = (BooleanFormula) node.getFormula(); - AxiomProofNode pn = new AxiomProofNode(ResAxiom.ASSUME, formula); + AxiomSubproof pn = new AxiomSubproof(ResAxiom.ASSUME, formula, proof); return pn; } - ProofNode handleModusPonens(Z3ProofDAG.Z3ProofNode node) { + Subproof handleModusPonens(Z3Subproof node) { BooleanFormula formula = (BooleanFormula) node.getFormula(); - BooleanFormula pivot = (BooleanFormula) node.getChildren().get(0).getFormula(); - ResolutionProofNode pn = new ResolutionProofNode(formula, pivot); - ProofNode c1 = handleNode((Z3ProofDAG.Z3ProofNode) node.getChildren().get(0)); - ProofNode c2 = handleNode((Z3ProofDAG.Z3ProofNode) node.getChildren().get(1)); + BooleanFormula pivot = (BooleanFormula) node.getArguments().get(0).getFormula(); + ResolutionSubproof pn = new ResolutionSubproof(formula, pivot, proof); + Subproof c1 = handleNode((Z3Subproof) node.getArguments().get(0)); + Subproof c2 = handleNode((Z3Subproof) node.getArguments().get(1)); return pn; } - ProofNode handleReflexivity(Z3ProofDAG.Z3ProofNode node) { + Subproof handleReflexivity(Z3Subproof node) { BooleanFormula formula = (BooleanFormula) node.getFormula(); - AxiomProofNode pn = new AxiomProofNode(ResAxiom.REFLEXIVITY, formula); + AxiomSubproof pn = new AxiomSubproof(ResAxiom.REFLEXIVITY, formula, proof); return pn; } - ProofNode handleSymmetry(Z3ProofDAG.Z3ProofNode node) { + Subproof handleSymmetry(Z3Subproof node) { BooleanFormula formula = (BooleanFormula) node.getFormula(); - BooleanFormula pivot = (BooleanFormula) node.getChildren().get(0).getFormula(); + BooleanFormula pivot = (BooleanFormula) node.getArguments().get(0).getFormula(); BooleanFormula snFormula = bfm.or(bfm.not(pivot), formula); - ResolutionProofNode pn = new ResolutionProofNode(formula, pivot); - AxiomProofNode sn = new AxiomProofNode(ResAxiom.SYMMETRY, snFormula); + ResolutionSubproof pn = new ResolutionSubproof(formula, pivot, proof); + AxiomSubproof sn = new AxiomSubproof(ResAxiom.SYMMETRY, snFormula, proof); pn.addChild(sn); - pn.addChild(handleNode((Z3ProofDAG.Z3ProofNode) node.getChildren().get(0))); + pn.addChild(handleNode((Z3Subproof) node.getArguments().get(0))); return pn; } - ProofNode handleTransitivity(Z3ProofDAG.Z3ProofNode node) { + Subproof handleTransitivity(Z3Subproof node) { - BooleanFormula t1 = (BooleanFormula) node.getChildren().get(0).getFormula(); - BooleanFormula t2 = (BooleanFormula) node.getChildren().get(1).getFormula(); + BooleanFormula t1 = (BooleanFormula) node.getArguments().get(0).getFormula(); + BooleanFormula t2 = (BooleanFormula) node.getArguments().get(1).getFormula(); BooleanFormula formula = (BooleanFormula) node.getFormula(); List equivalenceOperands1 = extractEquivalenceOperands(t1); @@ -355,13 +360,13 @@ ProofNode handleTransitivity(Z3ProofDAG.Z3ProofNode node) { BooleanFormula transRes = formula; BooleanFormula transClause = bfm.or(bfm.not(t1), bfm.not(t2), formula); - AxiomProofNode pn = new AxiomProofNode(ResAxiom.TRANSITIVITY, transClause); + AxiomSubproof pn = new AxiomSubproof(ResAxiom.TRANSITIVITY, transClause, proof); - ResolutionProofNode transResNode = new ResolutionProofNode(transRes, t2); - ResolutionProofNode trnAnte1 = new ResolutionProofNode(t2, t2); + ResolutionSubproof transResNode = new ResolutionSubproof(transRes, t2, proof); + ResolutionSubproof trnAnte1 = new ResolutionSubproof(t2, t2, proof); BooleanFormula trn2Formula = bfm.or(bfm.not(t2), transRes); - ResolutionProofNode trnAnte2 = new ResolutionProofNode(trn2Formula, t1); - ResolutionProofNode trnAnte2Ante = new ResolutionProofNode(t1, t1); + ResolutionSubproof trnAnte2 = new ResolutionSubproof(trn2Formula, t1, proof); + ResolutionSubproof trnAnte2Ante = new ResolutionSubproof(t1, t1, proof); transResNode.addChild(trnAnte1); transResNode.addChild(trnAnte2); @@ -371,26 +376,26 @@ ProofNode handleTransitivity(Z3ProofDAG.Z3ProofNode node) { return transResNode; } - ProofNode handleTransitivityStar(Z3ProofDAG.Z3ProofNode node) { + Subproof handleTransitivityStar(Z3Subproof node) { BooleanFormula resPivot = null; Collection formulas = new ArrayList<>(); List> formulaList = new ArrayList<>(); - int numChildren = node.getChildren().size(); + int numChildren = node.getArguments().size(); for (int i = 0; i < numChildren; i++) { Collection newCollection = new ArrayList<>(); - formulas.add(bfm.not((BooleanFormula) node.getChildren().get(i).getFormula())); + formulas.add(bfm.not((BooleanFormula) node.getArguments().get(i).getFormula())); if (i == numChildren - 1) { - resPivot = (BooleanFormula) node.getChildren().get(i).getFormula(); + resPivot = (BooleanFormula) node.getArguments().get(i).getFormula(); } } assert resPivot != null; - ResolutionProofNode resNode = new ResolutionProofNode(node.getFormula(), resPivot); + ResolutionSubproof resNode = new ResolutionSubproof(node.getFormula(), resPivot, proof); formulas.add((BooleanFormula) node.getFormula()); BooleanFormula transitivityFormula = bfm.or(formulas); - AxiomProofNode sn = new AxiomProofNode(ResAxiom.TRANSITIVITY, transitivityFormula); + AxiomSubproof sn = new AxiomSubproof(ResAxiom.TRANSITIVITY, transitivityFormula, proof); for (int i = 0; i < formulas.size() - 2; i++) { // ResolutionProofNode pn1 = new ResolutionProofNode(transitivityFormula., @@ -400,168 +405,168 @@ ProofNode handleTransitivityStar(Z3ProofDAG.Z3ProofNode node) { return resNode; } - ProofNode handleMonotonicity(Z3ProofDAG.Z3ProofNode node) { + Subproof handleMonotonicity(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleQuantIntro(Z3ProofDAG.Z3ProofNode node) { + Subproof handleQuantIntro(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleBind(Z3ProofDAG.Z3ProofNode node) { + Subproof handleBind(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleDistributivity(Z3ProofDAG.Z3ProofNode node) { + Subproof handleDistributivity(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleAndElim(Z3ProofDAG.Z3ProofNode node) { + Subproof handleAndElim(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleNotOrElim(Z3ProofDAG.Z3ProofNode node) { + Subproof handleNotOrElim(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleRewrite(Z3ProofDAG.Z3ProofNode node) { + Subproof handleRewrite(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleRewriteStar(Z3ProofDAG.Z3ProofNode node) { + Subproof handleRewriteStar(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handlePullQuant(Z3ProofDAG.Z3ProofNode node) { + Subproof handlePullQuant(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleElimUnusedVars(Z3ProofDAG.Z3ProofNode node) { + Subproof handleElimUnusedVars(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handlePushQuant(Z3ProofDAG.Z3ProofNode node) { + Subproof handlePushQuant(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleDer(Z3ProofDAG.Z3ProofNode node) { + Subproof handleDer(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleQuantInst(Z3ProofDAG.Z3ProofNode node) { + Subproof handleQuantInst(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleHypothesis(Z3ProofDAG.Z3ProofNode node) { + Subproof handleHypothesis(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleLemma(Z3ProofDAG.Z3ProofNode node) { + Subproof handleLemma(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleUnitResolution(Z3ProofDAG.Z3ProofNode node) { + Subproof handleUnitResolution(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleIffTrue(Z3ProofDAG.Z3ProofNode node) { + Subproof handleIffTrue(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleIffFalse(Z3ProofDAG.Z3ProofNode node) { + Subproof handleIffFalse(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleCommutativity(Z3ProofDAG.Z3ProofNode node) { + Subproof handleCommutativity(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleDefAxiom(Z3ProofDAG.Z3ProofNode node) { + Subproof handleDefAxiom(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleAssumptionAdd(Z3ProofDAG.Z3ProofNode node) { + Subproof handleAssumptionAdd(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleLemmaAdd(Z3ProofDAG.Z3ProofNode node) { + Subproof handleLemmaAdd(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleRedundantDel(Z3ProofDAG.Z3ProofNode node) { + Subproof handleRedundantDel(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleClauseTrail(Z3ProofDAG.Z3ProofNode node) { + Subproof handleClauseTrail(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleDefIntro(Z3ProofDAG.Z3ProofNode node) { + Subproof handleDefIntro(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleApplyDef(Z3ProofDAG.Z3ProofNode node) { + Subproof handleApplyDef(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleIffOeq(Z3ProofDAG.Z3ProofNode node) { + Subproof handleIffOeq(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleNnfPos(Z3ProofDAG.Z3ProofNode node) { + Subproof handleNnfPos(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleNnfNeg(Z3ProofDAG.Z3ProofNode node) { + Subproof handleNnfNeg(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleSkolemize(Z3ProofDAG.Z3ProofNode node) { + Subproof handleSkolemize(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleModusPonensOeq(Z3ProofDAG.Z3ProofNode node) { + Subproof handleModusPonensOeq(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleThLemma(Z3ProofDAG.Z3ProofNode node) { + Subproof handleThLemma(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleHyperResolve(Z3ProofDAG.Z3ProofNode node) { + Subproof handleHyperResolve(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleOperation(Z3ProofDAG.Z3ProofNode node) { + Subproof handleOperation(Z3Subproof node) { throw new UnsupportedOperationException(); } - ProofNode handleDefault(Z3ProofDAG.Z3ProofNode node) { + Subproof handleDefault(Z3Subproof node) { throw new UnsupportedOperationException(); } // This is for debugging purposes. - void printProof(ProofNode node, int indentLevel) { + void printProof(Subproof node, int indentLevel) { String indent = " ".repeat(indentLevel); - if (node instanceof AxiomProofNode) { - AxiomProofNode sourceNode = (AxiomProofNode) node; + if (node instanceof AxiomSubproof) { + AxiomSubproof sourceNode = (AxiomSubproof) node; System.out.println(indent + "Formula: " + sourceNode.getFormula()); System.out.println(indent + "Rule: " + sourceNode.getRule()); - System.out.println(indent + "No. Children: " + sourceNode.getChildren().size()); + System.out.println(indent + "No. Children: " + sourceNode.getArguments().size()); int i = 0; - for (ProofNode child : sourceNode.getChildren()) { + for (Subproof child : sourceNode.getArguments()) { System.out.println(indent + "Child " + ++i + ":"); printProof(child, indentLevel + 1); } - } else if (node instanceof ResolutionProofNode) { - ResolutionProofNode resolutionNode = (ResolutionProofNode) node; + } else if (node instanceof ResolutionSubproof) { + ResolutionSubproof resolutionNode = (ResolutionSubproof) node; System.out.println(indent + "Formula: " + resolutionNode.getFormula()); System.out.println(indent + "Pivot: " + resolutionNode.getPivot()); System.out.println(indent + "Rule: " + resolutionNode.getRule()); - System.out.println(indent + "No. Children: " + resolutionNode.getChildren().size()); + System.out.println(indent + "No. Children: " + resolutionNode.getArguments().size()); int i = 0; - for (ProofNode child : resolutionNode.getChildren()) { + for (Subproof child : resolutionNode.getArguments()) { System.out.println(indent + "Child " + ++i + ":"); printProof(child, indentLevel + 1); } diff --git a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java index c2cdd002f6..dd3801e78a 100644 --- a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java +++ b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java @@ -31,7 +31,7 @@ import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; -import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.Proof.Subproof; import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.solvers.bitwuzla.BitwuzlaSolverContext; import org.sosy_lab.java_smt.solvers.boolector.BoolectorSolverContext; @@ -211,7 +211,7 @@ public void testProof() throws InterruptedException, SolverException { assertThat(prover.isUnsat()).isTrue(); // Test getProof() - ProofNode proof = prover.getProof(); + Subproof proof = prover.getProof(); assertThat(proof).isNotNull(); // Test getRule() @@ -225,16 +225,13 @@ public void testProof() throws InterruptedException, SolverException { assertThat(proof.getFormula()).isEqualTo(bmgr.makeFalse()); } - // Test getChildren() - assertThat(proof.getChildren()).isNotNull(); - assertThat(proof.getChildren()).isNotEmpty(); - - // Test getId() - assertThat(proof.getId()).isNotEqualTo(proof.getChildren().get(0).getId()); + // Test getArguments() + assertThat(proof.getArguments()).isNotNull(); + assertThat(proof.getArguments()).isNotEmpty(); // Test isLeaf() assertThat(proof.isLeaf()).isFalse(); - ProofNode leaf = findanyProofLeaf(proof); + Subproof leaf = findanyProofLeaf(proof); assertThat(leaf).isNotNull(); assertThat(leaf.isLeaf()).isTrue(); @@ -254,10 +251,10 @@ public void testProof() throws InterruptedException, SolverException { } } - private ProofNode findanyProofLeaf(ProofNode pn) { + private Subproof findanyProofLeaf(Subproof pn) { if (pn.isLeaf()) { return pn; } - return findanyProofLeaf(pn.getChildren().get(0)); + return findanyProofLeaf(pn.getArguments().get(0)); } } From ea1735a4b9c5a477a3b224f21357c41421f45105 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Thu, 15 May 2025 18:10:56 +0200 Subject: [PATCH 103/132] Deleted method 'setProof' in 'ProofFrame'. Attribute proof now final. --- src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java b/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java index 706adef136..71677e7ef4 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java +++ b/src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java @@ -17,7 +17,7 @@ * @param The type of the proof object. */ public abstract class ProofFrame { - T proof; + final T proof; int numArgs = 0; boolean visited; @@ -50,8 +50,4 @@ public void setAsVisited(boolean isVisited) { public void setNumArgs(int numArgs) { this.numArgs = numArgs; } - - public void setProof(T proof) { - this.proof = proof; - } } From 6bbb92d7899772d78eb01d915fe04c41268363ae Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Thu, 15 May 2025 18:11:18 +0200 Subject: [PATCH 104/132] Made necessary changes to have proof production always enabled in Z3. --- src/org/sosy_lab/java_smt/SolverContextFactory.java | 3 +-- src/org/sosy_lab/java_smt/api/SolverContext.java | 7 ++++++- src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java | 4 ++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/org/sosy_lab/java_smt/SolverContextFactory.java b/src/org/sosy_lab/java_smt/SolverContextFactory.java index 21822c2b6f..b0f9604700 100644 --- a/src/org/sosy_lab/java_smt/SolverContextFactory.java +++ b/src/org/sosy_lab/java_smt/SolverContextFactory.java @@ -282,8 +282,7 @@ private SolverContext generateContext0(Solvers solverToCreate) case Z3: return Z3SolverContext.create( logger, - Configuration.builder().copyFrom(config) - .setOption("solver.z3.requireProofs", "true").build(), + Configuration.builder().copyFrom(config).setOption("requireProofs", "true").build(), shutdownNotifier, logfile, randomSeed, diff --git a/src/org/sosy_lab/java_smt/api/SolverContext.java b/src/org/sosy_lab/java_smt/api/SolverContext.java index 574dd6b2be..100eb55494 100644 --- a/src/org/sosy_lab/java_smt/api/SolverContext.java +++ b/src/org/sosy_lab/java_smt/api/SolverContext.java @@ -52,7 +52,12 @@ enum ProverOptions { */ GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS, - /** Whether the solver should generate proofs for unsatisfiable formulas. */ + /** + * Whether the solver should generate proofs for unsatisfiable formulas. For Z3, this parameter + * is context(not solver)-based, so for setting it, the extra option in the {@link + * org.sosy_lab.common.configuration.Configuration} instance: "requireProofs" should be set to + * "true". + */ GENERATE_PROOFS, /** Whether the solver should enable support for formulae build in SL theory. */ diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java index 51de53ea95..98a8b4cf32 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3SolverContext.java @@ -59,7 +59,7 @@ private static class ExtraOptions { secure = true, description = "Require proofs from SMT solver", values = {"true", "false"}) - boolean requireProofs = false; + String requireProofs = "true"; @Option( secure = true, @@ -145,7 +145,7 @@ public static synchronized Z3SolverContext create( } long cfg = Native.mkConfig(); - if (extraOptions.requireProofs) { + if (extraOptions.requireProofs.equals("true")) { Native.setParamValue(cfg, "PROOF", "true"); generateProofs = true; } From 81780c627b53e21cd54e9be8ca506fb4a40f339c Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Thu, 15 May 2025 18:11:40 +0200 Subject: [PATCH 105/132] Renamed 'ProofNode' into 'Subproof' --- .../delegate/logging/LoggingBasicProverEnvironment.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/logging/LoggingBasicProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/logging/LoggingBasicProverEnvironment.java index 3dd36f5e2a..2f70779d2e 100644 --- a/src/org/sosy_lab/java_smt/delegate/logging/LoggingBasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/delegate/logging/LoggingBasicProverEnvironment.java @@ -24,7 +24,7 @@ import org.sosy_lab.java_smt.api.Model; import org.sosy_lab.java_smt.api.Model.ValueAssignment; import org.sosy_lab.java_smt.api.SolverException; -import org.sosy_lab.java_smt.api.proofs.ProofNode; +import org.sosy_lab.java_smt.api.proofs.Proof.Subproof; /** Wraps a basic prover environment with a logging object. */ class LoggingBasicProverEnvironment implements BasicProverEnvironment { @@ -122,8 +122,8 @@ public ImmutableMap getStatistics() { } @Override - public ProofNode getProof() throws SolverException, InterruptedException { - ProofNode p = wrapped.getProof(); + public Subproof getProof() throws SolverException, InterruptedException { + Subproof p = wrapped.getProof(); logger.log(Level.FINE, "proof", p); return p; } From e751e16ecf3a4e766edcd8006bae619b748417b2 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 16 May 2025 17:00:28 +0200 Subject: [PATCH 106/132] Proofs: Proof edges is now a map from 'Subproof' -> 'LinkedHashSet''. The signatures of 'addEdge' and 'addChild' changed accordingly --- .../sosy_lab/java_smt/api/proofs/Proof.java | 7 +++-- .../java_smt/basicimpl/AbstractProof.java | 10 +++---- .../mathsat5/Mathsat5TheoremProver.java | 7 +++-- .../SmtInterpolAbstractProver.java | 28 +++++++++++++++---- .../z3/Z3ToResolutionProofConverter.java | 19 +++++++------ 5 files changed, 48 insertions(+), 23 deletions(-) diff --git a/src/org/sosy_lab/java_smt/api/proofs/Proof.java b/src/org/sosy_lab/java_smt/api/proofs/Proof.java index c6aa51769d..8aff1f1da6 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/Proof.java +++ b/src/org/sosy_lab/java_smt/api/proofs/Proof.java @@ -11,6 +11,7 @@ package org.sosy_lab.java_smt.api.proofs; import java.util.Collection; +import java.util.LinkedHashSet; import java.util.List; import org.sosy_lab.java_smt.api.Formula; @@ -30,8 +31,10 @@ public interface Proof { */ interface Subproof { - /** Get the children of the proof node. */ - List getArguments(); + /** + * Get the children of the proof node. + */ + LinkedHashSet getArguments(); boolean isLeaf(); diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java index 1809fe686e..69d5278182 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java @@ -11,11 +11,11 @@ package org.sosy_lab.java_smt.basicimpl; import com.google.common.base.Preconditions; -import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.List; +import java.util.LinkedHashSet; import java.util.Map; +import java.util.Set; import org.checkerframework.checker.nullness.qual.Nullable; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.Proof; @@ -36,12 +36,12 @@ public abstract class AbstractProof implements Proof { // protected abstract Proof generateProof(); //} - protected final Map> edges = new HashMap<>(); + protected final Map> edges = new HashMap<>(); protected void addEdge(Subproof source, Subproof target) { Preconditions.checkNotNull(source); Preconditions.checkNotNull(target); - edges.putIfAbsent(source, new ArrayList<>()); + edges.putIfAbsent(source, new LinkedHashSet<>()); edges.get(source).add(target); } @@ -67,7 +67,7 @@ public Formula getFormula() { } @Override - public List getArguments() { + public LinkedHashSet getArguments() { return this.proof.edges.get(this); } diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java index 4727582a1d..0654ef6b01 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.Deque; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -98,7 +99,8 @@ private void clausifyResChain(Subproof root, BooleanFormulaManager bfmgr) { // Push all children onto stack if (!node.isLeaf()) { - List children = node.getArguments(); + LinkedHashSet childrenSet = node.getArguments(); + List children = new ArrayList<>(childrenSet); for (int i = children.size() - 1; i >= 0; i--) { Subproof child = children.get(i); if (!visited.containsKey(child)) { @@ -121,7 +123,8 @@ private void clausifyResChain(Subproof root, BooleanFormulaManager bfmgr) { // process proof nodes and compute formulas for res-chain nodes private void processResChain(Subproof node, BooleanFormulaManager bfmgr) { - List children = node.getArguments(); + LinkedHashSet childrenSet = node.getArguments(); + List children = new ArrayList<>(childrenSet); // If the current node is a RES_CHAIN, compute the resolved formula if (node.getRule().equals(Rule.RES_CHAIN)) { diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java index 20ba7cfb69..a965e6b972 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java @@ -30,6 +30,7 @@ import java.util.Deque; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -227,9 +228,10 @@ public ImmutableMap getStatistics() { } @Override - public Subproof getProof() { + public Subproof getProof() throws InterruptedException { checkState(!closed); checkGenerateProofs(); + checkState(isUnsat()); final Term tProof; try { @@ -254,6 +256,20 @@ public Subproof getProof() { return proof; } + public Term smtInterpolGetProof(){ + Term tProof; + try { + tProof = env.getProof(); + } catch (SMTLIBException e) { + if (e.getMessage().contains("Context is inconsistent")) { + throw new IllegalStateException("Cannot get proof from satisfiable environment", e); + } else { + throw e; + } + } + return tProof; + } + @Override public void close() { if (!closed) { @@ -310,9 +326,10 @@ private void clausifyResChain(Subproof root, BooleanFormulaManager bfmgr) { visited.put(node, Boolean.TRUE); // Mark node as visited // Push all children onto stack - List children = node.getArguments(); - for (int i = children.size() - 1; i >= 0; i--) { - Subproof child = children.get(i); + LinkedHashSet children = node.getArguments(); + List childrenList = new ArrayList<>(children); + for (int i = childrenList.size() - 1; i >= 0; i--) { + Subproof child = childrenList.get(i); if (!visited.containsKey(child)) { stack.push(child); // Only push unvisited children visited.put(child, Boolean.FALSE); // Mark child as unvisited @@ -332,7 +349,8 @@ private void clausifyResChain(Subproof root, BooleanFormulaManager bfmgr) { // process proof nodes and compute formulas for res-chain nodes private void processResChain(Subproof node, BooleanFormulaManager bfmgr) { - List children = node.getArguments(); + LinkedHashSet childrenSet = node.getArguments(); + List children = new ArrayList<>(childrenSet); // If the current node is a RES_CHAIN, compute the resolved formula if (node.getRule().equals(ResAxiom.RESOLUTION)) { diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java index d2903e217a..7d50fbffd2 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java @@ -321,10 +321,11 @@ Subproof handleAsserted(Z3Subproof node) { Subproof handleModusPonens(Z3Subproof node) { BooleanFormula formula = (BooleanFormula) node.getFormula(); - BooleanFormula pivot = (BooleanFormula) node.getArguments().get(0).getFormula(); + BooleanFormula pivot = + (BooleanFormula) node.getArguments().stream().findFirst().get().getFormula(); ResolutionSubproof pn = new ResolutionSubproof(formula, pivot, proof); - Subproof c1 = handleNode((Z3Subproof) node.getArguments().get(0)); - Subproof c2 = handleNode((Z3Subproof) node.getArguments().get(1)); + Subproof c1 = handleNode((Z3Subproof) node.getArguments().stream().findFirst().get()); + Subproof c2 = handleNode((Z3Subproof) new ArrayList<>(node.getArguments()).get(1)); return pn; } @@ -336,20 +337,20 @@ Subproof handleReflexivity(Z3Subproof node) { Subproof handleSymmetry(Z3Subproof node) { BooleanFormula formula = (BooleanFormula) node.getFormula(); - BooleanFormula pivot = (BooleanFormula) node.getArguments().get(0).getFormula(); + BooleanFormula pivot = (BooleanFormula) node.getArguments().stream().findFirst().get().getFormula(); BooleanFormula snFormula = bfm.or(bfm.not(pivot), formula); ResolutionSubproof pn = new ResolutionSubproof(formula, pivot, proof); AxiomSubproof sn = new AxiomSubproof(ResAxiom.SYMMETRY, snFormula, proof); pn.addChild(sn); - pn.addChild(handleNode((Z3Subproof) node.getArguments().get(0))); + pn.addChild(handleNode((Z3Subproof) node.getArguments().stream().findFirst().get())); return pn; } Subproof handleTransitivity(Z3Subproof node) { - BooleanFormula t1 = (BooleanFormula) node.getArguments().get(0).getFormula(); - BooleanFormula t2 = (BooleanFormula) node.getArguments().get(1).getFormula(); + BooleanFormula t1 = (BooleanFormula) node.getArguments().stream().findFirst().get().getFormula(); + BooleanFormula t2 = (BooleanFormula) new ArrayList<>(node.getArguments()).get(1).getFormula(); BooleanFormula formula = (BooleanFormula) node.getFormula(); List equivalenceOperands1 = extractEquivalenceOperands(t1); @@ -384,9 +385,9 @@ Subproof handleTransitivityStar(Z3Subproof node) { for (int i = 0; i < numChildren; i++) { Collection newCollection = new ArrayList<>(); - formulas.add(bfm.not((BooleanFormula) node.getArguments().get(i).getFormula())); + formulas.add(bfm.not((BooleanFormula) new ArrayList<>(node.getArguments()).get(i).getFormula())); if (i == numChildren - 1) { - resPivot = (BooleanFormula) node.getArguments().get(i).getFormula(); + resPivot = (BooleanFormula) new ArrayList<>(node.getArguments()).get(i).getFormula(); } } From 640c6f7ca87908c060b8c5f6be9c53989f6ef15a Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 16 May 2025 17:00:43 +0200 Subject: [PATCH 107/132] SmtInterpol: Added extra proof rules. --- .../solvers/smtinterpol/SmtInterpolProof.java | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProof.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProof.java index b1bfa50f8d..688462b68f 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProof.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProof.java @@ -10,6 +10,7 @@ package org.sosy_lab.java_smt.solvers.smtinterpol; +import com.google.common.base.Preconditions; import de.uni_freiburg.informatik.ultimate.logic.AnnotatedTerm; import de.uni_freiburg.informatik.ultimate.logic.Annotation; import de.uni_freiburg.informatik.ultimate.logic.ApplicationTerm; @@ -40,12 +41,37 @@ */ class SmtInterpolProof extends AbstractProof { protected enum Rules implements ProofRule { + COEFFS, + VALUES, + DIVISOR, + POS, + UNIT, + DEFINE_FUN("define-fun"), + DECLARE_FUN("declare-fun"), RUP, PIVOT; + String name; + private Rules() {} + Rules(String pDefineFun) { + name = pDefineFun; + } + + static Rules getFromName(String pName){ + if (pName.equals("DEFINE-FUN")){ + return DEFINE_FUN; + } else if (pName.equals("DECLARE-FUN")){ + return DECLARE_FUN; + } + return Rules.valueOf(pName); + } @Override public String getName() { - return name().toLowerCase(Locale.ENGLISH); + if (this.equals(DEFINE_FUN) || this.equals(DECLARE_FUN)) { + return name; + } else{ + return name().toLowerCase(Locale.ENGLISH); + } } } @@ -103,8 +129,12 @@ SmtInterpolSubproof createProof(ProvitionalProofNode pProofNode) { stack.pop(); Formula formula = null; if (proofNode.formulas.size() > 1) { - Term or = Util.or(creator.getEnv(), proofNode.formulas.toArray(new Term[0])); - formula = creator.encapsulate(creator.getFormulaType(or), or); + //This can not stay like this, the algorithm calculating the formulas to be stored is + // needed, as what we retrieve here is simply arguments for generating a clause, + // meaning the arguments do not have to be boolean and therefore joining them with OR + // causes and exception. + //Term or = Util.or(creator.getEnv(), proofNode.formulas.toArray(new Term[0])); + //formula = creator.encapsulate(creator.getFormulaType(or), or); } else if (!proofNode.formulas.isEmpty()) { Term t = proofNode.formulas.get(0); formula = creator.encapsulate(creator.getFormulaType(t), t); @@ -196,7 +226,7 @@ private void processAnnotated(AnnotatedTerm term) { } for (Annotation annotation : term.getAnnotations()) { - ResAxiom rule; + ProofRule rule; String key = annotation.getKey().substring(1); if (term.getSubterm().toString().equals("..axiom")) { @@ -207,6 +237,8 @@ private void processAnnotated(AnnotatedTerm term) { key = key.startsWith(":") ? key.substring(1) : key; rule = ResProofRule.getFromName(key); + if (rule == null) rule = Rules.getFromName(key.toUpperCase(Locale.ENGLISH)); + Preconditions.checkNotNull(key); this.proofRule = rule; // This Annotation's value should have an array with the polarities and Terms that are From 303713b54ba55c8f00160d707ef2a3343dd28971 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 16 May 2025 17:01:20 +0200 Subject: [PATCH 108/132] 'ResProofRule': check for null removed. It should be checked elsewhere. --- src/org/sosy_lab/java_smt/ResProofRule.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/ResProofRule.java b/src/org/sosy_lab/java_smt/ResProofRule.java index 6291097762..580bd0d88e 100644 --- a/src/org/sosy_lab/java_smt/ResProofRule.java +++ b/src/org/sosy_lab/java_smt/ResProofRule.java @@ -152,7 +152,6 @@ public String getFormula() { */ public static ResAxiom getFromName(String name) { ResAxiom rule = RULE_MAP.get(name.toLowerCase(Locale.ENGLISH)); - Preconditions.checkNotNull(rule); return rule; } } From 84f1a16eaad70c0eb4a6f544200110df5e9021a1 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 16 May 2025 17:02:32 +0200 Subject: [PATCH 109/132] CVC5: 'getProof' now checks whether proof generation is enabled through 'checkGenerateProofs()', whether the solver is closed and whether the last evaluation was UNSAT --- .../solvers/cvc5/CVC5AbstractProver.java | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java index 6604bcc021..27027f6c2f 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java @@ -8,6 +8,8 @@ package org.sosy_lab.java_smt.solvers.cvc5; +import static com.google.common.base.Preconditions.checkState; + import com.google.common.base.Preconditions; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; @@ -142,7 +144,7 @@ protected void popImpl() { @CanIgnoreReturnValue protected String addConstraint0(BooleanFormula pF) { - Preconditions.checkState(!closed); + checkState(!closed); setChanged(); Term exp = creator.extractInfo(pF); if (incremental) { @@ -156,8 +158,8 @@ protected String addConstraint0(BooleanFormula pF) { @SuppressWarnings("resource") @Override public CVC5Model getModel() throws SolverException { - Preconditions.checkState(!closed); - Preconditions.checkState(!changedSinceLastSatQuery); + checkState(!closed); + checkState(!changedSinceLastSatQuery); checkGenerateModels(); // special case for CVC5: Models are not permanent and need to be closed // before any change is applied to the prover stack. So, we register the Model as Evaluator. @@ -171,7 +173,7 @@ public CVC5Model getModel() throws SolverException { @Override public Evaluator getEvaluator() { - Preconditions.checkState(!closed); + checkState(!closed); checkGenerateModels(); return getEvaluatorWithoutChecks(); } @@ -191,15 +193,15 @@ protected void setChanged() { @Override public ImmutableList getModelAssignments() throws SolverException { - Preconditions.checkState(!closed); - Preconditions.checkState(!changedSinceLastSatQuery); + checkState(!closed); + checkState(!changedSinceLastSatQuery); return super.getModelAssignments(); } @Override @SuppressWarnings("try") public boolean isUnsat() throws InterruptedException, SolverException { - Preconditions.checkState(!closed); + checkState(!closed); closeAllEvaluators(); changedSinceLastSatQuery = false; if (!incremental) { @@ -226,9 +228,9 @@ private boolean convertSatResult(Result result) throws InterruptedException, Sol @Override public List getUnsatCore() { - Preconditions.checkState(!closed); + checkState(!closed); checkGenerateUnsatCores(); - Preconditions.checkState(!changedSinceLastSatQuery); + checkState(!changedSinceLastSatQuery); List converted = new ArrayList<>(); for (Term aCore : solver.getUnsatCore()) { converted.add(creator.encapsulateBoolean(aCore)); @@ -249,7 +251,10 @@ public Optional> unsatCoreOverAssumptions( } @Override - public Subproof getProof() { + public Subproof getProof() throws SolverException, InterruptedException { + checkGenerateProofs(); + checkState(!closed); + checkState(isUnsat()); Proof[] proofs = solver.getProof(); if (proofs == null || proofs.length == 0) { @@ -261,7 +266,7 @@ public Subproof getProof() { CVC5Proof proof = new CVC5Proof(); return proof.generateProofImpl(proofs[0], creator); } catch (CVC5ApiException e) { - throw new RuntimeException(e); + throw new SolverException("There was a problem generating proof", e); } } From 86c01cd516a49ff5adb74d71d6bc3cdf23c92e74 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Fri, 16 May 2025 17:04:36 +0200 Subject: [PATCH 110/132] Proofs: Test cases for solvers' outputs for retrieving a proof when asserting true and false, and when previously having evaluated once for multiple assertions and retrieving a proof, then asserting different formulas, evaluating and requesting a proof again. --- .../java_smt/test/ProverEnvironmentTest.java | 248 +++++++++++++++++- 1 file changed, 246 insertions(+), 2 deletions(-) diff --git a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java index dd3801e78a..746294ead9 100644 --- a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java +++ b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java @@ -27,8 +27,14 @@ import org.junit.Test; import org.sosy_lab.java_smt.api.BasicProverEnvironment; import org.sosy_lab.java_smt.api.BooleanFormula; +import org.sosy_lab.java_smt.api.FormulaType; +import org.sosy_lab.java_smt.api.FunctionDeclaration; import org.sosy_lab.java_smt.api.Model; +import org.sosy_lab.java_smt.api.NumeralFormula; +import org.sosy_lab.java_smt.api.NumeralFormula.IntegerFormula; +import org.sosy_lab.java_smt.api.NumeralFormula.RationalFormula; import org.sosy_lab.java_smt.api.ProverEnvironment; +import org.sosy_lab.java_smt.api.RationalFormulaManager; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; import org.sosy_lab.java_smt.api.proofs.Proof.Subproof; @@ -198,7 +204,7 @@ private void checkSimpleQuery(ProverEnvironment pProver) } @Test - public void testProof() throws InterruptedException, SolverException { + public void testSimpleProof() throws InterruptedException, SolverException { requireProofGeneration(); // Ensures proofs are supported BooleanFormula q1 = bmgr.makeVariable("q1"); BooleanFormula q2 = bmgr.makeVariable("q2"); @@ -251,10 +257,248 @@ public void testProof() throws InterruptedException, SolverException { } } + @Test + public void testComplexProof() throws InterruptedException, SolverException { + requireProofGeneration(); // Ensures proofs are supported + + RationalFormula x1 = mgr.makeVariable(FormulaType.RationalType, "x1"); + NumeralFormula x2 = mgr.makeVariable(FormulaType.RationalType, "x2"); + RationalFormula x3 = mgr.makeVariable(FormulaType.RationalType, "x3"); + RationalFormula y1 = mgr.makeVariable(FormulaType.RationalType, "y1"); + NumeralFormula y2 = mgr.makeVariable(FormulaType.RationalType, "y2"); + RationalFormula y3 = mgr.makeVariable(FormulaType.RationalType, "y3"); + RationalFormula b = mgr.makeVariable(FormulaType.RationalType, "b"); + + FunctionDeclaration f = + mgr.getUFManager().declareUF("f", FormulaType.RationalType, FormulaType.RationalType); + FunctionDeclaration g = + mgr.getUFManager().declareUF("g", FormulaType.RationalType, FormulaType.RationalType); + + BooleanFormula a = bmgr.makeVariable("a"); + BooleanFormula c = bmgr.makeVariable("c"); + + rmgr = mgr.getRationalFormulaManager(); + + try (ProverEnvironment prover = context.newProverEnvironment(ProverOptions.GENERATE_PROOFS)) { + // Add constraints + prover.addConstraint( + bmgr.and( + a, + rmgr.equal(rmgr.add((NumeralFormula) mgr.makeApplication(f, y1), y2), y3), + rmgr.lessOrEquals(y1, x1))); + prover.addConstraint( + bmgr.and( + rmgr.equal(x2, (NumeralFormula) mgr.makeApplication(g, b)), + rmgr.equal(y2, (NumeralFormula) mgr.makeApplication(g, b)), + rmgr.lessOrEquals(x1, y1), + rmgr.lessThan(x3, y3))); + prover.addConstraint( + bmgr.equivalence( + a, rmgr.equal(rmgr.add((NumeralFormula) mgr.makeApplication(f, x1), x2), x3))); + prover.addConstraint(bmgr.and(bmgr.or(a, c), bmgr.not(c))); + + // Check unsatisfiability + assertThat(prover.isUnsat()).isTrue(); + + // Retrieve and verify proof + Subproof proof = prover.getProof(); + assertThat(proof).isNotNull(); + + // Root formula check + if (solverToUse().equals(SMTINTERPOL)) { + assertThat(proof.getFormula()).isNull(); + } else { + assertThat(proof.getFormula()).isEqualTo(bmgr.makeFalse()); + } + + // Rule check + assertThat(proof.getRule()).isNotNull(); + assertThat(proof.getRule()).isInstanceOf(ProofRule.class); + + // Arguments check + assertThat(proof.getArguments()).isNotNull(); + assertThat(proof.getArguments()).isNotEmpty(); + + // Leaf check + assertThat(proof.isLeaf()).isFalse(); + Subproof leaf = findanyProofLeaf(proof); + assertThat(leaf).isNotNull(); + assertThat(leaf.isLeaf()).isTrue(); + + } catch (UnsupportedOperationException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Proof generation is not available for the current solver."); + Class contextClass = context.getClass(); + boolean isExpected = + contextClass.equals(CVC4SolverContext.class) + || contextClass.equals(PrincessSolverContext.class) + || contextClass.equals(OpenSmtSolverContext.class) + || contextClass.equals(BoolectorSolverContext.class) + || contextClass.equals(BitwuzlaSolverContext.class) + || contextClass.equals(Yices2SolverContext.class); + assertThat(isExpected).isTrue(); + } + } + + @Test + public void proofOfTrueTest() throws InterruptedException, SolverException { + requireProofGeneration(); + + BooleanFormula tru = bmgr.makeTrue(); + + try (ProverEnvironment prover = context.newProverEnvironment(ProverOptions.GENERATE_PROOFS)) { + prover.addConstraint(tru); + assertThat(prover.isUnsat()).isFalse(); + + Subproof proof = prover.getProof(); + + + } catch (UnsupportedOperationException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Proof generation is not available for the current solver."); + Class contextClass = context.getClass(); + boolean isExpected = + contextClass.equals(CVC4SolverContext.class) + || contextClass.equals(PrincessSolverContext.class) + || contextClass.equals(OpenSmtSolverContext.class) + || contextClass.equals(BoolectorSolverContext.class) + || contextClass.equals(BitwuzlaSolverContext.class) + || contextClass.equals(Yices2SolverContext.class); + assertThat(isExpected).isTrue(); + } catch(IllegalStateException ie){ + //this should be thrown as getProof was called when last evaluation was SAT + } + } + + @Test + public void proofOfFalseTest() throws InterruptedException, SolverException { + requireProofGeneration(); + + BooleanFormula bottom = bmgr.makeFalse(); + + try (ProverEnvironment prover = context.newProverEnvironment(ProverOptions.GENERATE_PROOFS)) { + prover.addConstraint(bottom); + assertThat(prover.isUnsat()).isTrue(); + + Subproof proof = prover.getProof(); + assertThat(proof).isNotNull(); + + + } catch (UnsupportedOperationException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Proof generation is not available for the current solver."); + Class contextClass = context.getClass(); + boolean isExpected = + contextClass.equals(CVC4SolverContext.class) + || contextClass.equals(PrincessSolverContext.class) + || contextClass.equals(OpenSmtSolverContext.class) + || contextClass.equals(BoolectorSolverContext.class) + || contextClass.equals(BitwuzlaSolverContext.class) + || contextClass.equals(Yices2SolverContext.class); + assertThat(isExpected).isTrue(); + } catch(IllegalStateException ie){ + //this should be thrown as getProof was called when last evaluation was SAT + } + } + + @Test + public void proofAfterProofTest() throws InterruptedException, SolverException { + requireProofGeneration(); // Ensures proofs are supported + BooleanFormula q1 = bmgr.makeVariable("q1"); + BooleanFormula q2 = bmgr.makeVariable("q2"); + IntegerFormula x1 = imgr.makeVariable("x1"); + IntegerFormula two = imgr.makeNumber("2"); + IntegerFormula cero = imgr.makeNumber("0"); + + try (ProverEnvironment prover = context.newProverEnvironment(ProverOptions.GENERATE_PROOFS)) { + prover.addConstraint(bmgr.or(bmgr.not(q1), q2)); + prover.addConstraint(q1); + prover.addConstraint(bmgr.not(q2)); + + assertThat(prover.isUnsat()).isTrue(); + + // Test getProof() + Subproof proof = prover.getProof(); + assertThat(proof).isNotNull(); + + // Test getRule() + assertThat(proof.getRule()).isNotNull(); + assertThat(proof.getRule()).isInstanceOf(ProofRule.class); + + // Test getFormula(), the root should always be false + if (solverToUse().equals(SMTINTERPOL)) { + assertThat(proof.getFormula()).isNull(); + } else { + assertThat(proof.getFormula()).isEqualTo(bmgr.makeFalse()); + } + + // Test getArguments() + assertThat(proof.getArguments()).isNotNull(); + assertThat(proof.getArguments()).isNotEmpty(); + + // Test isLeaf() + assertThat(proof.isLeaf()).isFalse(); + Subproof leaf = findanyProofLeaf(proof); + assertThat(leaf).isNotNull(); + assertThat(leaf.isLeaf()).isTrue(); + + //assert integer formulas and test again + prover.addConstraint(imgr.equal(x1, two)); + prover.addConstraint(imgr.lessThan(x1, cero)); + + assertThat(prover.isUnsat()).isTrue(); + + // Test getProof() + proof = prover.getProof(); + assertThat(proof).isNotNull(); + + // Test getRule() + assertThat(proof.getRule()).isNotNull(); + assertThat(proof.getRule()).isInstanceOf(ProofRule.class); + + // Test getFormula(), the root should always be false + if (solverToUse().equals(SMTINTERPOL)) { + assertThat(proof.getFormula()).isNull(); + } else { + assertThat(proof.getFormula()).isEqualTo(bmgr.makeFalse()); + } + + // Test getArguments() + assertThat(proof.getArguments()).isNotNull(); + assertThat(proof.getArguments()).isNotEmpty(); + + // Test isLeaf() + assertThat(proof.isLeaf()).isFalse(); + leaf = findanyProofLeaf(proof); + assertThat(leaf).isNotNull(); + assertThat(leaf.isLeaf()).isTrue(); + + + + } catch (UnsupportedOperationException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Proof generation is not available for the current solver."); + Class contextClass = context.getClass(); + boolean isExpected = + contextClass.equals(CVC4SolverContext.class) + || contextClass.equals(PrincessSolverContext.class) + || contextClass.equals(OpenSmtSolverContext.class) + || contextClass.equals(BoolectorSolverContext.class) + || contextClass.equals(BitwuzlaSolverContext.class) + || contextClass.equals(Yices2SolverContext.class); + assertThat(isExpected).isTrue(); + } + } + + private Subproof findanyProofLeaf(Subproof pn) { if (pn.isLeaf()) { return pn; } - return findanyProofLeaf(pn.getArguments().get(0)); + return findanyProofLeaf(pn.getArguments().stream().findFirst().get()); } } From 24991fe7bda2bd8a039c1ebfccf35d16778cee88 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sat, 17 May 2025 19:57:04 +0200 Subject: [PATCH 111/132] Changed incorrect cast in 'AbstractProof' --- src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java index 69d5278182..9c31c3c884 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java @@ -15,7 +15,6 @@ import java.util.HashMap; import java.util.LinkedHashSet; import java.util.Map; -import java.util.Set; import org.checkerframework.checker.nullness.qual.Nullable; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.Proof; @@ -50,7 +49,8 @@ public Collection getSubproofs() { return edges.keySet(); } - protected abstract static class AbstractSubproof implements Subproof { + + public abstract static class AbstractSubproof implements Subproof { private final AbstractProof proof; private ProofRule rule; @Nullable protected Formula formula; @@ -98,7 +98,7 @@ public Proof getDAG() { } // use this for debugging - protected String proofAsString() { + public String proofAsString() { return proofAsString(0); } @@ -119,7 +119,7 @@ protected String proofAsString(int indentLevel) { if (!isLeaf()) { for (Subproof child : getArguments()) { proof.append(indent).append("Child ").append(++i).append(":\n"); - proof.append(((Z3Subproof) child).proofAsString(indentLevel + 1)); + proof.append(((AbstractSubproof) child).proofAsString(indentLevel + 1)); } } From 331f7aceddcdaf4b5955a0423d3b2b750473ea14 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sat, 17 May 2025 22:23:34 +0200 Subject: [PATCH 112/132] 'AbstractProof' method 'proofAsString' did not print formulas correctly in the last changes to it. --- .../sosy_lab/java_smt/basicimpl/AbstractProof.java | 11 ++++++++++- .../java_smt/solvers/mathsat5/Mathsat5Proof.java | 2 +- .../solvers/smtinterpol/SmtInterpolProof.java | 2 +- src/org/sosy_lab/java_smt/solvers/z3/Z3Proof.java | 2 +- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java index 9c31c3c884..c3759d74ef 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java @@ -106,7 +106,16 @@ protected String proofAsString(int indentLevel) { StringBuilder proof = new StringBuilder(); String indent = " ".repeat(indentLevel); - proof.append(indent).append("Formula: ").append(getFormula().toString()).append("\n"); + Formula formula = getFormula(); + String sFormula; + if (formula != null) { + sFormula = formula.toString(); + } else { + sFormula = "null"; + } + + proof.append(indent).append("Formula: ").append(sFormula).append( + "\n"); proof.append(indent).append("Rule: ").append(getRule().getName()).append("\n"); proof .append(indent) diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5Proof.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5Proof.java index ad39f34ef3..e87d90d43f 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5Proof.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5Proof.java @@ -185,7 +185,7 @@ protected void addChild(Subproof subproof) { } @Override - protected String proofAsString() { + public String proofAsString() { return super.proofAsString(); } } diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProof.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProof.java index 688462b68f..0182971281 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProof.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProof.java @@ -86,7 +86,7 @@ protected void addChild(Subproof pSubproof) { } @Override - protected String proofAsString() { + public String proofAsString() { return super.proofAsString(); } } diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3Proof.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3Proof.java index 907090acf5..05dc755367 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3Proof.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3Proof.java @@ -42,7 +42,7 @@ protected void addChild(Subproof child) { } @Override - protected String proofAsString() { + public String proofAsString() { return super.proofAsString(); } } From 48534bd338443db26825969aac76c5735abd94d6 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sat, 17 May 2025 22:23:40 +0200 Subject: [PATCH 113/132] 'AbstractProof' method 'proofAsString' did not print formulas correctly in the last changes to it. --- src/org/sosy_lab/java_smt/solvers/cvc5/CVC5Proof.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5Proof.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5Proof.java index 2253f9fc16..a062036267 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5Proof.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5Proof.java @@ -106,7 +106,7 @@ protected void addChild(Subproof pSubproof) { // } @Override - protected String proofAsString() { + public String proofAsString() { return super.proofAsString(); } } From dd460aad7ab6cd22f4a5d289e6e7e32e8a708564 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sat, 17 May 2025 22:24:20 +0200 Subject: [PATCH 114/132] 'TOTAL_INT' rule in 'ResProofRule' had wrong name previously. --- src/org/sosy_lab/java_smt/ResProofRule.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/ResProofRule.java b/src/org/sosy_lab/java_smt/ResProofRule.java index 580bd0d88e..240520aadb 100644 --- a/src/org/sosy_lab/java_smt/ResProofRule.java +++ b/src/org/sosy_lab/java_smt/ResProofRule.java @@ -103,7 +103,7 @@ public enum ResAxiom implements ProofRule { NEG_DEF("neg_def", "(+ (= (- a) (* (- 1) a)))"), NEG_DEF2("neg_def2", "(+ (= (- a b1 ... bn) (+ a (* (- 1) b1)) ... (* (- 1) bn)))"), ABS_DEF("abs_def", "(+ (= (abs x) (ite (< x 0) (- x) x)))"), - TOTAL_INT("total_int", "(+ (<= a c) (<= (c+1) a))"), + TOTAL_INT("total-int", "(+ (<= a c) (<= (c+1) a))"), TO_INT_LOW("to_int_low", "(+ (<= (to_real (to_int x)) x))"), TO_INT_HIGH("to_int_high", "(+ (< x (+ (to_real (to_int x)) 1.0)))"), DIV_LOW("div_low", "(+ (<= (* d (div x d)) x) (= d 0))"), From a6872653adaddda60a3b939f476af316334ab67a Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sat, 17 May 2025 22:25:09 +0200 Subject: [PATCH 115/132] MathSAT5: method 'getProof' now checks that proof generation is enabled through 'checkGenerateProofs' --- .../java_smt/solvers/mathsat5/Mathsat5TheoremProver.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java index 0654ef6b01..02124dc03e 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java @@ -67,6 +67,7 @@ protected Void addConstraintImpl(BooleanFormula constraint) throws InterruptedEx public Subproof getProof() throws SolverException, InterruptedException { Preconditions.checkState(!closed); Preconditions.checkState(this.isUnsat()); + checkGenerateProofs(); Mathsat5Proof proof = new Mathsat5Proof(); From 0bbaa73727a7d0dff65303f106bacde34b6bb692 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sat, 17 May 2025 22:27:23 +0200 Subject: [PATCH 116/132] Added multiple tests for proofs: test boolean proof, integer proof, rational and UF proof, test proof for only asserting false/true, test getting 2 different proofs with same prover instance. --- .../java_smt/test/ProverEnvironmentTest.java | 268 +++++++++++++++--- 1 file changed, 236 insertions(+), 32 deletions(-) diff --git a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java index 746294ead9..c7a0ef0f1c 100644 --- a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java +++ b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java @@ -10,13 +10,16 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.TruthJUnit.assume; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.CVC4; import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.CVC5; import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.MATHSAT5; import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.OPENSMT; import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.PRINCESS; import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.SMTINTERPOL; +import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.Z3; import static org.sosy_lab.java_smt.api.SolverContext.ProverOptions.GENERATE_UNSAT_CORE; import static org.sosy_lab.java_smt.api.SolverContext.ProverOptions.GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS; import static org.sosy_lab.java_smt.test.ProverEnvironmentSubject.assertThat; @@ -39,6 +42,7 @@ import org.sosy_lab.java_smt.api.SolverException; import org.sosy_lab.java_smt.api.proofs.Proof.Subproof; import org.sosy_lab.java_smt.api.proofs.ProofRule; +import org.sosy_lab.java_smt.basicimpl.AbstractProof.AbstractSubproof; import org.sosy_lab.java_smt.solvers.bitwuzla.BitwuzlaSolverContext; import org.sosy_lab.java_smt.solvers.boolector.BoolectorSolverContext; import org.sosy_lab.java_smt.solvers.cvc4.CVC4SolverContext; @@ -98,7 +102,7 @@ public void unsatCoreTestForInterpolation() throws SolverException, InterruptedE requireUnsatCore(); requireInterpolation(); try (BasicProverEnvironment pe = - context.newProverEnvironmentWithInterpolation(GENERATE_UNSAT_CORE)) { + context.newProverEnvironmentWithInterpolation(GENERATE_UNSAT_CORE)) { unsatCoreTest0(pe); } } @@ -108,7 +112,7 @@ public void unsatCoreTestForOptimizationProver() throws SolverException, Interru requireUnsatCore(); requireOptimization(); try (BasicProverEnvironment pe = - context.newOptimizationProverEnvironment(GENERATE_UNSAT_CORE)) { + context.newOptimizationProverEnvironment(GENERATE_UNSAT_CORE)) { unsatCoreTest0(pe); } } @@ -138,7 +142,7 @@ public void unsatCoreWithAssumptionsNullTest() { .isNoneOf(PRINCESS, CVC4, CVC5, OPENSMT); try (ProverEnvironment pe = - context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { + context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { assertThrows(NullPointerException.class, () -> pe.unsatCoreOverAssumptions(null)); } } @@ -153,7 +157,7 @@ public void unsatCoreWithAssumptionsTest() throws SolverException, InterruptedEx .that(solverToUse()) .isNoneOf(PRINCESS, CVC4, CVC5, OPENSMT); try (ProverEnvironment pe = - context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { + context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { pe.push(); pe.addConstraint(imgr.equal(imgr.makeVariable("y"), imgr.makeNumber(2))); BooleanFormula selector = bmgr.makeVariable("b"); @@ -175,12 +179,13 @@ public void testSatWithUnsatUnsatCoreOptions() throws InterruptedException, Solv requireUnsatCoreOverAssumptions(); try (ProverEnvironment prover = - context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { + context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { checkSimpleQuery(prover); } try (ProverEnvironment prover = - context.newProverEnvironment(GENERATE_UNSAT_CORE, GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { + context.newProverEnvironment(GENERATE_UNSAT_CORE, + GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { checkSimpleQuery(prover); } } @@ -204,7 +209,7 @@ private void checkSimpleQuery(ProverEnvironment pProver) } @Test - public void testSimpleProof() throws InterruptedException, SolverException { + public void testGetSimpleBooleanProof() throws InterruptedException, SolverException { requireProofGeneration(); // Ensures proofs are supported BooleanFormula q1 = bmgr.makeVariable("q1"); BooleanFormula q2 = bmgr.makeVariable("q2"); @@ -258,47 +263,62 @@ public void testSimpleProof() throws InterruptedException, SolverException { } @Test - public void testComplexProof() throws InterruptedException, SolverException { + public void testGetComplexRationalNumeralaAndUFProof() throws InterruptedException, + SolverException { requireProofGeneration(); // Ensures proofs are supported - + // "(declare-fun x1 () Real)" + + // "(declare-fun x2 () Real)" + + // "(declare-fun x3 () Real)" + + // "(declare-fun y1 () Real)" + + // "(declare-fun y2 () Real)" + + // "(declare-fun y3 () Real)" + + // "(declare-fun b () Real)" + + // "(declare-fun f (Real) Real)" + + // "(declare-fun g (Real) Real)" + + // "(declare-fun a () Bool)" + + // "(declare-fun c () Bool)" + + // "(assert (and a (= (+ (f y1) y2) y3) (<= y1 x1)))" + + // "(assert (and (= x2 (g b)) (= y2 (g b)) (<= x1 y1) (< x3 y3)))" + + // "(assert (= a (= (+ (f x1) x2) x3)))" + + // "(assert (and (or a c) (not c)))"; RationalFormula x1 = mgr.makeVariable(FormulaType.RationalType, "x1"); - NumeralFormula x2 = mgr.makeVariable(FormulaType.RationalType, "x2"); + RationalFormula x2 = mgr.makeVariable(FormulaType.RationalType, "x2"); RationalFormula x3 = mgr.makeVariable(FormulaType.RationalType, "x3"); RationalFormula y1 = mgr.makeVariable(FormulaType.RationalType, "y1"); - NumeralFormula y2 = mgr.makeVariable(FormulaType.RationalType, "y2"); + RationalFormula y2 = mgr.makeVariable(FormulaType.RationalType, "y2"); RationalFormula y3 = mgr.makeVariable(FormulaType.RationalType, "y3"); RationalFormula b = mgr.makeVariable(FormulaType.RationalType, "b"); - - FunctionDeclaration f = + FunctionDeclaration f = mgr.getUFManager().declareUF("f", FormulaType.RationalType, FormulaType.RationalType); - FunctionDeclaration g = + FunctionDeclaration g = mgr.getUFManager().declareUF("g", FormulaType.RationalType, FormulaType.RationalType); - BooleanFormula a = bmgr.makeVariable("a"); BooleanFormula c = bmgr.makeVariable("c"); - rmgr = mgr.getRationalFormulaManager(); + RationalFormulaManager rfmgr = mgr.getRationalFormulaManager(); - try (ProverEnvironment prover = context.newProverEnvironment(ProverOptions.GENERATE_PROOFS)) { - // Add constraints + try (ProverEnvironment prover = + context.newProverEnvironment(ProverOptions.GENERATE_PROOFS)) { + // "(assert (and a (= (+ (f y1) y2) y3) (<= y1 x1)))" prover.addConstraint( bmgr.and( a, - rmgr.equal(rmgr.add((NumeralFormula) mgr.makeApplication(f, y1), y2), y3), - rmgr.lessOrEquals(y1, x1))); + rfmgr.equal(rfmgr.add((NumeralFormula) mgr.makeApplication(f, y1), y2), y3), + rfmgr.lessOrEquals(y1, x1))); + // "(assert (and (= x2 (g b)) (= y2 (g b)) (<= x1 y1) (< x3 y3)))" prover.addConstraint( bmgr.and( - rmgr.equal(x2, (NumeralFormula) mgr.makeApplication(g, b)), - rmgr.equal(y2, (NumeralFormula) mgr.makeApplication(g, b)), - rmgr.lessOrEquals(x1, y1), - rmgr.lessThan(x3, y3))); + rfmgr.equal(x2, (NumeralFormula) mgr.makeApplication(g, b)), + rfmgr.equal(y2, (NumeralFormula) mgr.makeApplication(g, b)), + rfmgr.lessOrEquals(x1, y1), + rfmgr.lessThan(x3, y3))); + // "(assert (= a (= (+ (f x1) x2) x3)))" prover.addConstraint( bmgr.equivalence( - a, rmgr.equal(rmgr.add((NumeralFormula) mgr.makeApplication(f, x1), x2), x3))); + a, rfmgr.equal(rfmgr.add((NumeralFormula) mgr.makeApplication(f, x1), x2), x3))); + // "(assert (and (or a c) (not c)))" prover.addConstraint(bmgr.and(bmgr.or(a, c), bmgr.not(c))); - - // Check unsatisfiability - assertThat(prover.isUnsat()).isTrue(); + assertTrue(prover.isUnsat()); // Retrieve and verify proof Subproof proof = prover.getProof(); @@ -367,7 +387,7 @@ public void proofOfTrueTest() throws InterruptedException, SolverException { || contextClass.equals(BitwuzlaSolverContext.class) || contextClass.equals(Yices2SolverContext.class); assertThat(isExpected).isTrue(); - } catch(IllegalStateException ie){ + } catch (IllegalStateException ie) { //this should be thrown as getProof was called when last evaluation was SAT } } @@ -399,13 +419,68 @@ public void proofOfFalseTest() throws InterruptedException, SolverException { || contextClass.equals(BitwuzlaSolverContext.class) || contextClass.equals(Yices2SolverContext.class); assertThat(isExpected).isTrue(); - } catch(IllegalStateException ie){ + } catch (IllegalStateException ie) { //this should be thrown as getProof was called when last evaluation was SAT } } + @Test - public void proofAfterProofTest() throws InterruptedException, SolverException { + public void testGetSimpleIntegerProof() throws InterruptedException, SolverException { + requireProofGeneration(); // Ensures proofs are supported + IntegerFormula x1 = imgr.makeVariable("x1"); + IntegerFormula two = imgr.makeNumber("2"); + IntegerFormula cero = imgr.makeNumber("0"); + + try (ProverEnvironment prover = context.newProverEnvironment(ProverOptions.GENERATE_PROOFS)) { + prover.addConstraint(imgr.equal(x1, two)); + prover.addConstraint(imgr.lessThan(x1, cero)); + assertThat(prover.isUnsat()).isTrue(); + + // Test getProof() + Subproof proof = prover.getProof(); + assertThat(proof).isNotNull(); + + // Test getRule() + assertThat(proof.getRule()).isNotNull(); + assertThat(proof.getRule()).isInstanceOf(ProofRule.class); + + // Test getFormula(), the root should always be false + if (solverToUse().equals(SMTINTERPOL)) { + assertThat(proof.getFormula()).isNull(); + } else { + assertThat(proof.getFormula()).isEqualTo(bmgr.makeFalse()); + } + + // Test getArguments() + assertThat(proof.getArguments()).isNotNull(); + assertThat(proof.getArguments()).isNotEmpty(); + + // Test isLeaf() + assertThat(proof.isLeaf()).isFalse(); + Subproof leaf = findanyProofLeaf(proof); + assertThat(leaf).isNotNull(); + assertThat(leaf.isLeaf()).isTrue(); + + } catch (UnsupportedOperationException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Proof generation is not available for the current solver."); + Class contextClass = context.getClass(); + boolean isExpected = + contextClass.equals(CVC4SolverContext.class) + || contextClass.equals(PrincessSolverContext.class) + || contextClass.equals(OpenSmtSolverContext.class) + || contextClass.equals(BoolectorSolverContext.class) + || contextClass.equals(BitwuzlaSolverContext.class) + || contextClass.equals(Yices2SolverContext.class); + assertThat(isExpected).isTrue(); + } + } + + @Test + public void getProofAfterGetProofAndAddingAssertionsTest() throws InterruptedException, + SolverException { requireProofGeneration(); // Ensures proofs are supported BooleanFormula q1 = bmgr.makeVariable("q1"); BooleanFormula q2 = bmgr.makeVariable("q2"); @@ -452,7 +527,68 @@ public void proofAfterProofTest() throws InterruptedException, SolverException { assertThat(prover.isUnsat()).isTrue(); // Test getProof() - proof = prover.getProof(); + Subproof secondProof = prover.getProof(); + assertThat(secondProof).isNotNull(); + + // Test getRule() + assertThat(secondProof.getRule()).isNotNull(); + assertThat(secondProof.getRule()).isInstanceOf(ProofRule.class); + + // Test getFormula(), the root should always be false + if (solverToUse().equals(SMTINTERPOL)) { + assertThat(secondProof.getFormula()).isNull(); + } else { + assertThat(secondProof.getFormula()).isEqualTo(bmgr.makeFalse()); + } + + // Test getArguments() + assertThat(secondProof.getArguments()).isNotNull(); + assertThat(secondProof.getArguments()).isNotEmpty(); + + // Test isLeaf() + assertThat(secondProof.isLeaf()).isFalse(); + leaf = findanyProofLeaf(secondProof); + assertThat(leaf).isNotNull(); + assertThat(leaf.isLeaf()).isTrue(); + + assertNotEquals(proof, secondProof); + + } catch (UnsupportedOperationException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Proof generation is not available for the current solver."); + Class contextClass = context.getClass(); + boolean isExpected = + contextClass.equals(CVC4SolverContext.class) + || contextClass.equals(PrincessSolverContext.class) + || contextClass.equals(OpenSmtSolverContext.class) + || contextClass.equals(BoolectorSolverContext.class) + || contextClass.equals(BitwuzlaSolverContext.class) + || contextClass.equals(Yices2SolverContext.class); + assertThat(isExpected).isTrue(); + } + } + + @Test + public void getProofAfterGetProofClearingStackAndAddingDifferentAssertionsTest() + throws InterruptedException, SolverException { + requireProofGeneration(); // Ensures proofs are supported + BooleanFormula q1 = bmgr.makeVariable("q1"); + BooleanFormula q2 = bmgr.makeVariable("q2"); + IntegerFormula x1 = imgr.makeVariable("x1"); + IntegerFormula two = imgr.makeNumber("2"); + IntegerFormula cero = imgr.makeNumber("0"); + + try (ProverEnvironment prover = context.newProverEnvironment(ProverOptions.GENERATE_PROOFS)) { + + prover.push(bmgr.or(bmgr.not(q1), q2)); + prover.push(q1); + prover.push(bmgr.not(q2)); + + assertThat(prover.isUnsat()).isTrue(); + + // Test getProof() + Subproof proof = prover.getProof(); assertThat(proof).isNotNull(); // Test getRule() @@ -472,11 +608,51 @@ public void proofAfterProofTest() throws InterruptedException, SolverException { // Test isLeaf() assertThat(proof.isLeaf()).isFalse(); + Subproof leaf = findanyProofLeaf(proof); + assertThat(leaf).isNotNull(); + assertThat(leaf.isLeaf()).isTrue(); + + //System.out.println(((AbstractSubproof) proof).proofAsString()); + + prover.pop(); + prover.pop(); + prover.pop(); + + //assert integer formulas and test again + prover.push(imgr.equal(x1, two)); + prover.push(imgr.lessThan(x1, cero)); + + assertThat(prover.isUnsat()).isTrue(); + + // Test getProof() + Subproof secondProof = prover.getProof(); + assertThat(secondProof).isNotNull(); + + // Test getRule() + assertThat(secondProof.getRule()).isNotNull(); + assertThat(secondProof.getRule()).isInstanceOf(ProofRule.class); + + // Test getFormula(), the root should always be false + if (solverToUse().equals(SMTINTERPOL)) { + assertThat(secondProof.getFormula()).isNull(); + } else { + assertThat(secondProof.getFormula()).isEqualTo(bmgr.makeFalse()); + } + + // Test getArguments() + assertThat(secondProof.getArguments()).isNotNull(); + assertThat(secondProof.getArguments()).isNotEmpty(); + + // Test isLeaf() + assertThat(secondProof.isLeaf()).isFalse(); leaf = findanyProofLeaf(proof); assertThat(leaf).isNotNull(); assertThat(leaf.isLeaf()).isTrue(); + //System.out.println(((AbstractSubproof) proof).proofAsString()); + assertNotEquals(proof, secondProof); + assertNotEquals(proof.getDAG(), secondProof.getDAG()); } catch (UnsupportedOperationException e) { assertThat(e) @@ -494,6 +670,34 @@ public void proofAfterProofTest() throws InterruptedException, SolverException { } } + @Test + public void getProofWithoutProofProductionEnabledTest() + throws InterruptedException, SolverException { + requireProofGeneration(); + + BooleanFormula bottom = bmgr.makeFalse(); + + try (ProverEnvironment prover = context.newProverEnvironment()) { + prover.addConstraint(bottom); + assertThat(prover.isUnsat()).isTrue(); + + Subproof proof = prover.getProof(); + + //Z3 always has proof generation on + if (solverToUse().equals(Z3)) { + assertThat(proof.getFormula()).isNotNull(); + } + + } catch (UnsupportedOperationException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Proof generation is not available for the current solver."); + } catch (IllegalStateException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Please set the prover option GENERATE_PROOFS."); + } + } private Subproof findanyProofLeaf(Subproof pn) { if (pn.isLeaf()) { From 073966139138d003c52a07fe1d47f3a4be4f657b Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sat, 17 May 2025 22:27:59 +0200 Subject: [PATCH 117/132] Checkstyle --- src/org/sosy_lab/java_smt/ResProofRule.java | 1 - .../sosy_lab/java_smt/api/proofs/Proof.java | 5 +- .../java_smt/basicimpl/AbstractProof.java | 13 ++---- .../solvers/cvc5/CVC5AbstractProver.java | 1 - .../SmtInterpolAbstractProver.java | 2 +- .../solvers/smtinterpol/SmtInterpolProof.java | 16 ++++--- .../z3/Z3ToResolutionProofConverter.java | 9 ++-- .../java_smt/test/ProverEnvironmentTest.java | 46 ++++++++----------- 8 files changed, 41 insertions(+), 52 deletions(-) diff --git a/src/org/sosy_lab/java_smt/ResProofRule.java b/src/org/sosy_lab/java_smt/ResProofRule.java index 240520aadb..7d612d5287 100644 --- a/src/org/sosy_lab/java_smt/ResProofRule.java +++ b/src/org/sosy_lab/java_smt/ResProofRule.java @@ -10,7 +10,6 @@ package org.sosy_lab.java_smt; -import com.google.common.base.Preconditions; import java.util.HashMap; import java.util.Locale; import java.util.Map; diff --git a/src/org/sosy_lab/java_smt/api/proofs/Proof.java b/src/org/sosy_lab/java_smt/api/proofs/Proof.java index 8aff1f1da6..0043088094 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/Proof.java +++ b/src/org/sosy_lab/java_smt/api/proofs/Proof.java @@ -12,7 +12,6 @@ import java.util.Collection; import java.util.LinkedHashSet; -import java.util.List; import org.sosy_lab.java_smt.api.Formula; /** @@ -31,9 +30,7 @@ public interface Proof { */ interface Subproof { - /** - * Get the children of the proof node. - */ + /** Get the children of the proof node. */ LinkedHashSet getArguments(); boolean isLeaf(); diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java index c3759d74ef..a7d464940a 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java @@ -19,7 +19,6 @@ import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.Proof; import org.sosy_lab.java_smt.api.proofs.ProofRule; -import org.sosy_lab.java_smt.solvers.z3.Z3Proof.Z3Subproof; /** * A proof DAG of a proof. @@ -28,12 +27,12 @@ */ public abstract class AbstractProof implements Proof { - //protected abstract class Transformation { + // protected abstract class Transformation { // protected Transformation( // FormulaCreator formulaCreator, T proof) {} -// protected abstract Proof generateProof(); - //} + // protected abstract Proof generateProof(); + // } protected final Map> edges = new HashMap<>(); @@ -49,7 +48,6 @@ public Collection getSubproofs() { return edges.keySet(); } - public abstract static class AbstractSubproof implements Subproof { private final AbstractProof proof; private ProofRule rule; @@ -109,13 +107,12 @@ protected String proofAsString(int indentLevel) { Formula formula = getFormula(); String sFormula; if (formula != null) { - sFormula = formula.toString(); + sFormula = formula.toString(); } else { sFormula = "null"; } - proof.append(indent).append("Formula: ").append(sFormula).append( - "\n"); + proof.append(indent).append("Formula: ").append(sFormula).append("\n"); proof.append(indent).append("Rule: ").append(getRule().getName()).append("\n"); proof .append(indent) diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java index 27027f6c2f..774bdc1d03 100644 --- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5AbstractProver.java @@ -10,7 +10,6 @@ import static com.google.common.base.Preconditions.checkState; -import com.google.common.base.Preconditions; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java index a965e6b972..dfc363b8c2 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java @@ -256,7 +256,7 @@ public Subproof getProof() throws InterruptedException { return proof; } - public Term smtInterpolGetProof(){ + public Term smtInterpolGetProof() { Term tProof; try { tProof = env.getProof(); diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProof.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProof.java index 0182971281..70d104ccb8 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProof.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProof.java @@ -51,15 +51,17 @@ protected enum Rules implements ProofRule { RUP, PIVOT; String name; + private Rules() {} + Rules(String pDefineFun) { name = pDefineFun; } - static Rules getFromName(String pName){ - if (pName.equals("DEFINE-FUN")){ + static Rules getFromName(String pName) { + if (pName.equals("DEFINE-FUN")) { return DEFINE_FUN; - } else if (pName.equals("DECLARE-FUN")){ + } else if (pName.equals("DECLARE-FUN")) { return DECLARE_FUN; } return Rules.valueOf(pName); @@ -69,7 +71,7 @@ static Rules getFromName(String pName){ public String getName() { if (this.equals(DEFINE_FUN) || this.equals(DECLARE_FUN)) { return name; - } else{ + } else { return name().toLowerCase(Locale.ENGLISH); } } @@ -129,12 +131,12 @@ SmtInterpolSubproof createProof(ProvitionalProofNode pProofNode) { stack.pop(); Formula formula = null; if (proofNode.formulas.size() > 1) { - //This can not stay like this, the algorithm calculating the formulas to be stored is + // This can not stay like this, the algorithm calculating the formulas to be stored is // needed, as what we retrieve here is simply arguments for generating a clause, // meaning the arguments do not have to be boolean and therefore joining them with OR // causes and exception. - //Term or = Util.or(creator.getEnv(), proofNode.formulas.toArray(new Term[0])); - //formula = creator.encapsulate(creator.getFormulaType(or), or); + // Term or = Util.or(creator.getEnv(), proofNode.formulas.toArray(new Term[0])); + // formula = creator.encapsulate(creator.getFormulaType(or), or); } else if (!proofNode.formulas.isEmpty()) { Term t = proofNode.formulas.get(0); formula = creator.encapsulate(creator.getFormulaType(t), t); diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java index 7d50fbffd2..317fad2a61 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3ToResolutionProofConverter.java @@ -337,7 +337,8 @@ Subproof handleReflexivity(Z3Subproof node) { Subproof handleSymmetry(Z3Subproof node) { BooleanFormula formula = (BooleanFormula) node.getFormula(); - BooleanFormula pivot = (BooleanFormula) node.getArguments().stream().findFirst().get().getFormula(); + BooleanFormula pivot = + (BooleanFormula) node.getArguments().stream().findFirst().get().getFormula(); BooleanFormula snFormula = bfm.or(bfm.not(pivot), formula); ResolutionSubproof pn = new ResolutionSubproof(formula, pivot, proof); @@ -349,7 +350,8 @@ Subproof handleSymmetry(Z3Subproof node) { Subproof handleTransitivity(Z3Subproof node) { - BooleanFormula t1 = (BooleanFormula) node.getArguments().stream().findFirst().get().getFormula(); + BooleanFormula t1 = + (BooleanFormula) node.getArguments().stream().findFirst().get().getFormula(); BooleanFormula t2 = (BooleanFormula) new ArrayList<>(node.getArguments()).get(1).getFormula(); BooleanFormula formula = (BooleanFormula) node.getFormula(); @@ -385,7 +387,8 @@ Subproof handleTransitivityStar(Z3Subproof node) { for (int i = 0; i < numChildren; i++) { Collection newCollection = new ArrayList<>(); - formulas.add(bfm.not((BooleanFormula) new ArrayList<>(node.getArguments()).get(i).getFormula())); + formulas.add( + bfm.not((BooleanFormula) new ArrayList<>(node.getArguments()).get(i).getFormula())); if (i == numChildren - 1) { resPivot = (BooleanFormula) new ArrayList<>(node.getArguments()).get(i).getFormula(); } diff --git a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java index c7a0ef0f1c..2553c003de 100644 --- a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java +++ b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java @@ -42,7 +42,6 @@ import org.sosy_lab.java_smt.api.SolverException; import org.sosy_lab.java_smt.api.proofs.Proof.Subproof; import org.sosy_lab.java_smt.api.proofs.ProofRule; -import org.sosy_lab.java_smt.basicimpl.AbstractProof.AbstractSubproof; import org.sosy_lab.java_smt.solvers.bitwuzla.BitwuzlaSolverContext; import org.sosy_lab.java_smt.solvers.boolector.BoolectorSolverContext; import org.sosy_lab.java_smt.solvers.cvc4.CVC4SolverContext; @@ -102,7 +101,7 @@ public void unsatCoreTestForInterpolation() throws SolverException, InterruptedE requireUnsatCore(); requireInterpolation(); try (BasicProverEnvironment pe = - context.newProverEnvironmentWithInterpolation(GENERATE_UNSAT_CORE)) { + context.newProverEnvironmentWithInterpolation(GENERATE_UNSAT_CORE)) { unsatCoreTest0(pe); } } @@ -112,7 +111,7 @@ public void unsatCoreTestForOptimizationProver() throws SolverException, Interru requireUnsatCore(); requireOptimization(); try (BasicProverEnvironment pe = - context.newOptimizationProverEnvironment(GENERATE_UNSAT_CORE)) { + context.newOptimizationProverEnvironment(GENERATE_UNSAT_CORE)) { unsatCoreTest0(pe); } } @@ -142,7 +141,7 @@ public void unsatCoreWithAssumptionsNullTest() { .isNoneOf(PRINCESS, CVC4, CVC5, OPENSMT); try (ProverEnvironment pe = - context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { + context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { assertThrows(NullPointerException.class, () -> pe.unsatCoreOverAssumptions(null)); } } @@ -157,7 +156,7 @@ public void unsatCoreWithAssumptionsTest() throws SolverException, InterruptedEx .that(solverToUse()) .isNoneOf(PRINCESS, CVC4, CVC5, OPENSMT); try (ProverEnvironment pe = - context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { + context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { pe.push(); pe.addConstraint(imgr.equal(imgr.makeVariable("y"), imgr.makeNumber(2))); BooleanFormula selector = bmgr.makeVariable("b"); @@ -179,13 +178,12 @@ public void testSatWithUnsatUnsatCoreOptions() throws InterruptedException, Solv requireUnsatCoreOverAssumptions(); try (ProverEnvironment prover = - context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { + context.newProverEnvironment(GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { checkSimpleQuery(prover); } try (ProverEnvironment prover = - context.newProverEnvironment(GENERATE_UNSAT_CORE, - GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { + context.newProverEnvironment(GENERATE_UNSAT_CORE, GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS)) { checkSimpleQuery(prover); } } @@ -263,8 +261,8 @@ public void testGetSimpleBooleanProof() throws InterruptedException, SolverExcep } @Test - public void testGetComplexRationalNumeralaAndUFProof() throws InterruptedException, - SolverException { + public void testGetComplexRationalNumeralaAndUFProof() + throws InterruptedException, SolverException { requireProofGeneration(); // Ensures proofs are supported // "(declare-fun x1 () Real)" + // "(declare-fun x2 () Real)" + @@ -297,8 +295,7 @@ public void testGetComplexRationalNumeralaAndUFProof() throws InterruptedExcepti RationalFormulaManager rfmgr = mgr.getRationalFormulaManager(); - try (ProverEnvironment prover = - context.newProverEnvironment(ProverOptions.GENERATE_PROOFS)) { + try (ProverEnvironment prover = context.newProverEnvironment(ProverOptions.GENERATE_PROOFS)) { // "(assert (and a (= (+ (f y1) y2) y3) (<= y1 x1)))" prover.addConstraint( bmgr.and( @@ -373,7 +370,6 @@ public void proofOfTrueTest() throws InterruptedException, SolverException { Subproof proof = prover.getProof(); - } catch (UnsupportedOperationException e) { assertThat(e) .hasMessageThat() @@ -388,7 +384,7 @@ public void proofOfTrueTest() throws InterruptedException, SolverException { || contextClass.equals(Yices2SolverContext.class); assertThat(isExpected).isTrue(); } catch (IllegalStateException ie) { - //this should be thrown as getProof was called when last evaluation was SAT + // this should be thrown as getProof was called when last evaluation was SAT } } @@ -405,7 +401,6 @@ public void proofOfFalseTest() throws InterruptedException, SolverException { Subproof proof = prover.getProof(); assertThat(proof).isNotNull(); - } catch (UnsupportedOperationException e) { assertThat(e) .hasMessageThat() @@ -420,11 +415,10 @@ public void proofOfFalseTest() throws InterruptedException, SolverException { || contextClass.equals(Yices2SolverContext.class); assertThat(isExpected).isTrue(); } catch (IllegalStateException ie) { - //this should be thrown as getProof was called when last evaluation was SAT + // this should be thrown as getProof was called when last evaluation was SAT } } - @Test public void testGetSimpleIntegerProof() throws InterruptedException, SolverException { requireProofGeneration(); // Ensures proofs are supported @@ -479,8 +473,8 @@ public void testGetSimpleIntegerProof() throws InterruptedException, SolverExcep } @Test - public void getProofAfterGetProofAndAddingAssertionsTest() throws InterruptedException, - SolverException { + public void getProofAfterGetProofAndAddingAssertionsTest() + throws InterruptedException, SolverException { requireProofGeneration(); // Ensures proofs are supported BooleanFormula q1 = bmgr.makeVariable("q1"); BooleanFormula q2 = bmgr.makeVariable("q2"); @@ -520,7 +514,7 @@ public void getProofAfterGetProofAndAddingAssertionsTest() throws InterruptedExc assertThat(leaf).isNotNull(); assertThat(leaf.isLeaf()).isTrue(); - //assert integer formulas and test again + // assert integer formulas and test again prover.addConstraint(imgr.equal(x1, two)); prover.addConstraint(imgr.lessThan(x1, cero)); @@ -612,13 +606,13 @@ public void getProofAfterGetProofClearingStackAndAddingDifferentAssertionsTest() assertThat(leaf).isNotNull(); assertThat(leaf.isLeaf()).isTrue(); - //System.out.println(((AbstractSubproof) proof).proofAsString()); + // System.out.println(((AbstractSubproof) proof).proofAsString()); prover.pop(); prover.pop(); prover.pop(); - //assert integer formulas and test again + // assert integer formulas and test again prover.push(imgr.equal(x1, two)); prover.push(imgr.lessThan(x1, cero)); @@ -649,7 +643,7 @@ public void getProofAfterGetProofClearingStackAndAddingDifferentAssertionsTest() assertThat(leaf).isNotNull(); assertThat(leaf.isLeaf()).isTrue(); - //System.out.println(((AbstractSubproof) proof).proofAsString()); + // System.out.println(((AbstractSubproof) proof).proofAsString()); assertNotEquals(proof, secondProof); assertNotEquals(proof.getDAG(), secondProof.getDAG()); @@ -683,7 +677,7 @@ public void getProofWithoutProofProductionEnabledTest() Subproof proof = prover.getProof(); - //Z3 always has proof generation on + // Z3 always has proof generation on if (solverToUse().equals(Z3)) { assertThat(proof.getFormula()).isNotNull(); } @@ -693,9 +687,7 @@ public void getProofWithoutProofProductionEnabledTest() .hasMessageThat() .isEqualTo("Proof generation is not available for the current solver."); } catch (IllegalStateException e) { - assertThat(e) - .hasMessageThat() - .isEqualTo("Please set the prover option GENERATE_PROOFS."); + assertThat(e).hasMessageThat().isEqualTo("Please set the prover option GENERATE_PROOFS."); } } From bcad354b3907bdf6f96176060e49868ead908800 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Tue, 20 May 2025 21:47:43 +0200 Subject: [PATCH 118/132] Some (not working) code added so that proofs from OpenSMT are parsed and transformed into JavaSMT proofs. There is no apparent way to retrieve a formula just from a String. --- .../solvers/opensmt/OpenSMTProof.java | 240 ++++++++++++++++++ .../opensmt/OpenSmtAbstractProver.java | 11 + 2 files changed, 251 insertions(+) create mode 100644 src/org/sosy_lab/java_smt/solvers/opensmt/OpenSMTProof.java diff --git a/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSMTProof.java b/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSMTProof.java new file mode 100644 index 0000000000..da706682bc --- /dev/null +++ b/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSMTProof.java @@ -0,0 +1,240 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2024 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.solvers.opensmt; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Deque; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.proofs.ProofRule; +import org.sosy_lab.java_smt.basicimpl.AbstractProof; + +class OpenSMTProof extends AbstractProof { + class OpenSMTProofRule implements ProofRule { + private String name; + + OpenSMTProofRule(String pName) { + name = pName; + } + + @Override + public String getName() { + return name; + } + } + + class OpenSMTSubproof extends AbstractSubproof { + protected OpenSMTSubproof(ProofRule rule, Formula formula, AbstractProof proof) { + super(rule, formula, proof); + } + } + + OpenSMTSubproof generateProof(String proof, OpenSmtFormulaCreator creator) { + Deque resNodes = new ArrayDeque<>(); + Map nodes = new HashMap<>(); + Deque rootStack = ProofParser.parse(ProofParser.tokenize(proof)); + + Deque> iterStack = new ArrayDeque<>(); + iterStack.push(rootStack.iterator()); + + OpenSMTSubproof result = null; + Formula formula = null; + String formulaStr = ""; + + while (!iterStack.isEmpty()) { + Iterator currentIter = iterStack.peek(); + + if (!currentIter.hasNext()) { + iterStack.pop(); + continue; + } + + Object exp = currentIter.next(); + + if (exp instanceof String) { + String token = (String) exp; + switch (token) { + case "let": + // next element is a Deque with clause name and formula + if (!currentIter.hasNext()) { + throw new IllegalStateException("Expected argument after 'let'"); + } + Object letArg = currentIter.next(); + handleLet(letArg, nodes, resNodes, creator); + break; + + case ";": + if (!currentIter.hasNext()) { + throw new IllegalStateException("Expected formula string after ';'"); + } + formulaStr = (String) currentIter.next(); + formula = creator.encapsulate(creator.getEnv().parseFormula(formulaStr)); + break; + + case "res": + String cls1 = (String) currentIter.next(); + String cls2 = (String) currentIter.next(); + String cls3 = (String) currentIter.next(); + + OpenSMTSubproof pre = resNodes.pop(); + pre.setFormula(formula); + this.addEdge(pre, nodes.get(cls1)); + this.addEdge(pre, nodes.get(cls2)); + formula = creator.encapsulate(creator.getEnv().parseFormula(cls3)); + OpenSMTSubproof pivot = + new OpenSMTSubproof(new OpenSMTProofRule("pivot"), formula, this); + this.addEdge(pre, nodes.get(cls3)); + + if (formulaStr.equals("-")) result = pre; + + default: + break; + } + } else if (exp instanceof Deque) { + iterStack.push(((Deque) exp).iterator()); + } + } + + return result; + } + + void handleLet( + Object stack, + Map nodes, + Deque resNodes, + OpenSmtFormulaCreator creator) { + assert stack instanceof Deque; // no unchecked cast + Object exp = ((Deque) stack).pop(); + if (exp instanceof String) { // first element should be the assigned name + Object v1 = ((Deque) stack).peek(); + if (v1 instanceof Deque) { // then a stack with the formula + Object v2 = ((Deque) stack).peek(); + if (v2 instanceof String) { + if (v2.equals("res")) { + OpenSMTSubproof res = new OpenSMTSubproof(new OpenSMTProofRule("res"), null, this); + resNodes.push(res); + nodes.putIfAbsent((String) exp, res); + } else { + String formulaStr = serializeDeque((Deque) v2); + nodes.putIfAbsent( + (String) exp, + new OpenSMTSubproof( + new OpenSMTProofRule("leaf"), + creator.encapsulate(creator.getEnv().parseFormula(formulaStr)), + this)); + } + } else { + String formulaStr = serializeDeque((Deque) v1); + nodes.putIfAbsent( + (String) exp, + new OpenSMTSubproof( + new OpenSMTProofRule("leaf"), + creator.encapsulate(creator.getEnv().parseFormula(formulaStr)), + this)); + } + } else if (v1 instanceof String) { // or a formula + nodes.putIfAbsent( + (String) exp, + new OpenSMTSubproof( + new OpenSMTProofRule("leaf"), + creator.encapsulate(creator.getEnv().parseFormula((String) v1)), // this does not + // work right now + this)); + } + } + } + + private String serializeDeque(Deque deque) { + StringBuilder sb = new StringBuilder(); + serializeHelper(deque, sb); + return sb.toString(); + } + + private void serializeHelper(Object obj, StringBuilder sb) { + if (obj instanceof Deque) { + sb.append("("); + Deque inner = (Deque) obj; + boolean first = true; + for (Object o : inner) { + if (!first) sb.append(" "); + serializeHelper(o, sb); + first = false; + } + sb.append(")"); + } else if (obj instanceof String) { + sb.append((String) obj); + } + } + + static class ProofParser { + static List tokenize(String input) { + List tokens = new ArrayList<>(); + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < input.length(); i++) { + char c = input.charAt(i); + + if (Character.isWhitespace(c)) { + if (sb.length() > 0) { + String token = sb.toString(); + if (":core".equals(token)) { + tokens.add(")"); + break; + } + tokens.add(token); + sb.setLength(0); + } + } else if (c == '(' || c == ')') { + if (sb.length() > 0) { + String token = sb.toString(); + if (":core".equals(token)) { + tokens.add(")"); + break; + } + tokens.add(token); + sb.setLength(0); + } + tokens.add(Character.toString(c)); + } else { + sb.append(c); + } + } + + return tokens; + } + + static Deque parse(List tokens) { + Deque> stack = new ArrayDeque<>(); + Deque current = new ArrayDeque<>(); + + for (int i = 0; i < tokens.size(); i++) { + String token = tokens.get(i); + + if ("(".equals(token)) { + stack.push(current); + current = new ArrayDeque<>(); + } else if (")".equals(token)) { + Deque completed = current; + current = stack.pop(); + current.addLast(completed); + } else { + current.addLast(token); + } + } + + return current; + } + } +} diff --git a/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSmtAbstractProver.java b/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSmtAbstractProver.java index 6678fb9b1c..328504afd5 100644 --- a/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSmtAbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSmtAbstractProver.java @@ -28,6 +28,7 @@ import org.sosy_lab.java_smt.api.Model.ValueAssignment; import org.sosy_lab.java_smt.api.SolverContext.ProverOptions; import org.sosy_lab.java_smt.api.SolverException; +import org.sosy_lab.java_smt.api.proofs.Proof.Subproof; import org.sosy_lab.java_smt.basicimpl.AbstractProverWithAllSat; import org.sosy_lab.java_smt.basicimpl.ShutdownHook; import org.sosy_lab.java_smt.solvers.opensmt.OpenSmtSolverContext.OpenSMTOptions; @@ -78,6 +79,8 @@ protected static SMTConfig getConfigInstance( config.setOption(":produce-unsat-cores", optUnsatCore); config.setOption(":print-cores-full", optUnsatCore); config.setOption(":produce-interpolants", new SMTOption(interpolation)); + config.setOption( + ":produce-proofs", new SMTOption(pOptions.contains(ProverOptions.GENERATE_PROOFS))); if (interpolation) { config.setOption(":interpolation-bool-algorithm", new SMTOption(pSolverOptions.algBool)); config.setOption(":interpolation-euf-algorithm", new SMTOption(pSolverOptions.algUf)); @@ -282,6 +285,14 @@ public Optional> unsatCoreOverAssumptions( throw new UnsupportedOperationException("OpenSMT does not support solving with assumptions."); } + @Override + public Subproof getProof() { + throw new UnsupportedOperationException( + "Proof generation is not available for the current solver."); + // OpenSMTProof proof = new OpenSMTProof(); + // return proof.generateProof(osmtSolver.printResolutionProofSMT2(), creator); + } + @Override public void close() { if (!closed) { From e86e7e2b96883ddd1916a961f8ab9b730ab2c0ac Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Wed, 21 May 2025 12:10:57 +0200 Subject: [PATCH 119/132] No longer logging whole proof in 'LoggingBasicProverEnvironment' --- .../java_smt/delegate/logging/LoggingBasicProverEnvironment.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/delegate/logging/LoggingBasicProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/logging/LoggingBasicProverEnvironment.java index 2f70779d2e..bb79dd12d1 100644 --- a/src/org/sosy_lab/java_smt/delegate/logging/LoggingBasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/delegate/logging/LoggingBasicProverEnvironment.java @@ -124,7 +124,6 @@ public ImmutableMap getStatistics() { @Override public Subproof getProof() throws SolverException, InterruptedException { Subproof p = wrapped.getProof(); - logger.log(Level.FINE, "proof", p); return p; } From 7aa247cd0cea095e86b225e44bff1fea63e4311d Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Sat, 24 May 2025 17:31:12 +0200 Subject: [PATCH 120/132] Added bit vector and array tests for retrieving proofs in `ProverEnvironmentTest` --- .../java_smt/test/ProverEnvironmentTest.java | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java index 2553c003de..03e0cb6200 100644 --- a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java +++ b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java @@ -20,6 +20,7 @@ import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.PRINCESS; import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.SMTINTERPOL; import static org.sosy_lab.java_smt.SolverContextFactory.Solvers.Z3; +import static org.sosy_lab.java_smt.api.FormulaType.IntegerType; import static org.sosy_lab.java_smt.api.SolverContext.ProverOptions.GENERATE_UNSAT_CORE; import static org.sosy_lab.java_smt.api.SolverContext.ProverOptions.GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS; import static org.sosy_lab.java_smt.test.ProverEnvironmentSubject.assertThat; @@ -28,9 +29,12 @@ import java.util.List; import java.util.Optional; import org.junit.Test; +import org.sosy_lab.java_smt.api.ArrayFormula; import org.sosy_lab.java_smt.api.BasicProverEnvironment; +import org.sosy_lab.java_smt.api.BitvectorFormula; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.FormulaType; +import org.sosy_lab.java_smt.api.FormulaType.ArrayFormulaType; import org.sosy_lab.java_smt.api.FunctionDeclaration; import org.sosy_lab.java_smt.api.Model; import org.sosy_lab.java_smt.api.NumeralFormula; @@ -691,6 +695,113 @@ public void getProofWithoutProofProductionEnabledTest() } } + // This test is based on the bvIsZeroAfterShiftLeft() test in BitvectorFormulaManagerTest + @Test + public void getBitVectorProofTest() throws InterruptedException, SolverException { + requireProofGeneration(); + BitvectorFormula one = bvmgr.makeBitvector(32, 1); + + // unsigned char + BitvectorFormula a = bvmgr.makeVariable(8, "char_a"); + BitvectorFormula b = bvmgr.makeVariable(8, "char_b"); + BitvectorFormula rightOp = bvmgr.makeBitvector(32, 7); + + // 'cast' a to unsigned int + a = bvmgr.extend(a, 32 - 8, false); + b = bvmgr.extend(b, 32 - 8, false); + a = bvmgr.or(a, one); + b = bvmgr.or(b, one); + a = bvmgr.extract(a, 7, 0); + b = bvmgr.extract(b, 7, 0); + a = bvmgr.extend(a, 32 - 8, false); + b = bvmgr.extend(b, 32 - 8, false); + + a = bvmgr.shiftLeft(a, rightOp); + b = bvmgr.shiftLeft(b, rightOp); + a = bvmgr.extract(a, 7, 0); + b = bvmgr.extract(b, 7, 0); + BooleanFormula f = bmgr.not(bvmgr.equal(a, b)); + + try (ProverEnvironment prover = context.newProverEnvironment(ProverOptions.GENERATE_PROOFS)) { + prover.addConstraint(f); + assertThat(prover.isUnsat()).isTrue(); + + // Test getProof() + Subproof proof = prover.getProof(); + assertThat(proof).isNotNull(); + + // Test getRule() + assertThat(proof.getRule()).isNotNull(); + assertThat(proof.getRule()).isInstanceOf(ProofRule.class); + + // Test getFormula(), the root should always be false + if (solverToUse().equals(SMTINTERPOL)) { + assertThat(proof.getFormula()).isNull(); + } else { + assertThat(proof.getFormula()).isEqualTo(bmgr.makeFalse()); + } + + // Test getArguments() + assertThat(proof.getArguments()).isNotNull(); + assertThat(proof.getArguments()).isNotEmpty(); + + // Test isLeaf() + assertThat(proof.isLeaf()).isFalse(); + Subproof leaf = findanyProofLeaf(proof); + assertThat(leaf).isNotNull(); + assertThat(leaf.isLeaf()).isTrue(); + } + } + + // This test is based on the testIntIndexIntValue() test in ArrayFormulaManagerTest + @Test + public void getArrayProofTest() throws InterruptedException, SolverException { + requireProofGeneration(); + requireIntegers(); + + // (arr2 = store(arr1, 4, 2)) & !(select(arr2, 4) = 2) + ArrayFormulaType type = + FormulaType.getArrayType(IntegerType, IntegerType); + IntegerFormula num2 = imgr.makeNumber(2); + IntegerFormula num4 = imgr.makeNumber(4); + ArrayFormula arr1 = amgr.makeArray("arr1", type); + ArrayFormula arr2 = amgr.makeArray("arr2", type); + BooleanFormula query = + bmgr.and( + amgr.equivalence(arr2, amgr.store(arr1, num4, num2)), + bmgr.not(imgr.equal(num2, amgr.select(arr2, num4)))); + + try (ProverEnvironment prover = context.newProverEnvironment(ProverOptions.GENERATE_PROOFS)) { + prover.addConstraint(query); + assertThat(prover.isUnsat()).isTrue(); + + // Test getProof() + Subproof proof = prover.getProof(); + assertThat(proof).isNotNull(); + + // Test getRule() + assertThat(proof.getRule()).isNotNull(); + assertThat(proof.getRule()).isInstanceOf(ProofRule.class); + + // Test getFormula(), the root should always be false + if (solverToUse().equals(SMTINTERPOL)) { + assertThat(proof.getFormula()).isNull(); + } else { + assertThat(proof.getFormula()).isEqualTo(bmgr.makeFalse()); + } + + // Test getArguments() + assertThat(proof.getArguments()).isNotNull(); + assertThat(proof.getArguments()).isNotEmpty(); + + // Test isLeaf() + assertThat(proof.isLeaf()).isFalse(); + Subproof leaf = findanyProofLeaf(proof); + assertThat(leaf).isNotNull(); + assertThat(leaf.isLeaf()).isTrue(); + } + } + private Subproof findanyProofLeaf(Subproof pn) { if (pn.isLeaf()) { return pn; From cec06cfd2447766122b4e926db5c2d32282b1d2a Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 26 May 2025 13:30:52 +0200 Subject: [PATCH 121/132] Multiple changes regarding the proof interface to fix warnings. Unchecked warning remains in `OpenSMTProof` but is suppressed --- .../sosy_lab/java_smt/api/proofs/Proof.java | 4 +-- .../java_smt/basicimpl/AbstractProof.java | 26 ++++++++++--------- .../solvers/mathsat5/Mathsat5Proof.java | 2 +- .../mathsat5/Mathsat5TheoremProver.java | 5 ++-- .../solvers/opensmt/OpenSMTProof.java | 20 ++++++-------- .../SmtInterpolAbstractProver.java | 5 ++-- .../solvers/smtinterpol/SmtInterpolProof.java | 23 ++++++++-------- .../java_smt/test/ProverEnvironmentTest.java | 16 ++++++------ 8 files changed, 49 insertions(+), 52 deletions(-) diff --git a/src/org/sosy_lab/java_smt/api/proofs/Proof.java b/src/org/sosy_lab/java_smt/api/proofs/Proof.java index 0043088094..f48acd0494 100644 --- a/src/org/sosy_lab/java_smt/api/proofs/Proof.java +++ b/src/org/sosy_lab/java_smt/api/proofs/Proof.java @@ -11,7 +11,7 @@ package org.sosy_lab.java_smt.api.proofs; import java.util.Collection; -import java.util.LinkedHashSet; +import java.util.Set; import org.sosy_lab.java_smt.api.Formula; /** @@ -31,7 +31,7 @@ public interface Proof { interface Subproof { /** Get the children of the proof node. */ - LinkedHashSet getArguments(); + Set getArguments(); boolean isLeaf(); diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java index a7d464940a..4fdabd445b 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java @@ -15,6 +15,7 @@ import java.util.HashMap; import java.util.LinkedHashSet; import java.util.Map; +import java.util.Set; import org.checkerframework.checker.nullness.qual.Nullable; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.proofs.Proof; @@ -65,7 +66,7 @@ public Formula getFormula() { } @Override - public LinkedHashSet getArguments() { + public Set getArguments() { return this.proof.edges.get(this); } @@ -91,6 +92,7 @@ public void setFormula(Formula pFormula) { formula = pFormula; } + @Override public Proof getDAG() { return proof; } @@ -101,35 +103,35 @@ public String proofAsString() { } protected String proofAsString(int indentLevel) { - StringBuilder proof = new StringBuilder(); + StringBuilder sb = new StringBuilder(); String indent = " ".repeat(indentLevel); - Formula formula = getFormula(); + Formula f = getFormula(); String sFormula; - if (formula != null) { - sFormula = formula.toString(); + if (f != null) { + sFormula = f.toString(); } else { sFormula = "null"; } - proof.append(indent).append("Formula: ").append(sFormula).append("\n"); - proof.append(indent).append("Rule: ").append(getRule().getName()).append("\n"); - proof + sb.append(indent).append("Formula: ").append(sFormula).append("\n"); + sb.append(indent).append("Rule: ").append(getRule().getName()).append("\n"); + sb .append(indent) .append("No. Children: ") .append(this.isLeaf() ? 0 : getArguments().size()) .append("\n"); - proof.append(indent).append("leaf: ").append(isLeaf()).append("\n"); + sb.append(indent).append("leaf: ").append(isLeaf()).append("\n"); int i = 0; if (!isLeaf()) { for (Subproof child : getArguments()) { - proof.append(indent).append("Child ").append(++i).append(":\n"); - proof.append(((AbstractSubproof) child).proofAsString(indentLevel + 1)); + sb.append(indent).append("Child ").append(++i).append(":\n"); + sb.append(((AbstractSubproof) child).proofAsString(indentLevel + 1)); } } - return proof.toString(); + return sb.toString(); } } } diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5Proof.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5Proof.java index e87d90d43f..f3178f04ac 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5Proof.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5Proof.java @@ -173,7 +173,7 @@ protected static class MsatProofFrame extends ProofFrame { } } - class Mathsat5Subproof extends AbstractSubproof { + static class Mathsat5Subproof extends AbstractSubproof { protected Mathsat5Subproof(@Nullable ProofRule rule, Formula formula, Mathsat5Proof proof) { super(rule, formula, proof); diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java index 02124dc03e..799a1b95a2 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java @@ -19,7 +19,6 @@ import java.util.ArrayList; import java.util.Deque; import java.util.HashMap; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -100,7 +99,7 @@ private void clausifyResChain(Subproof root, BooleanFormulaManager bfmgr) { // Push all children onto stack if (!node.isLeaf()) { - LinkedHashSet childrenSet = node.getArguments(); + Set childrenSet = node.getArguments(); List children = new ArrayList<>(childrenSet); for (int i = children.size() - 1; i >= 0; i--) { Subproof child = children.get(i); @@ -124,7 +123,7 @@ private void clausifyResChain(Subproof root, BooleanFormulaManager bfmgr) { // process proof nodes and compute formulas for res-chain nodes private void processResChain(Subproof node, BooleanFormulaManager bfmgr) { - LinkedHashSet childrenSet = node.getArguments(); + Set childrenSet = node.getArguments(); List children = new ArrayList<>(childrenSet); // If the current node is a RES_CHAIN, compute the resolved formula diff --git a/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSMTProof.java b/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSMTProof.java index da706682bc..39d2e480b0 100644 --- a/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSMTProof.java +++ b/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSMTProof.java @@ -21,9 +21,10 @@ import org.sosy_lab.java_smt.api.proofs.ProofRule; import org.sosy_lab.java_smt.basicimpl.AbstractProof; +@SuppressWarnings("unchecked") class OpenSMTProof extends AbstractProof { - class OpenSMTProofRule implements ProofRule { - private String name; + static class OpenSMTProofRule implements ProofRule { + private final String name; OpenSMTProofRule(String pName) { name = pName; @@ -35,7 +36,7 @@ public String getName() { } } - class OpenSMTSubproof extends AbstractSubproof { + static class OpenSMTSubproof extends AbstractSubproof { protected OpenSMTSubproof(ProofRule rule, Formula formula, AbstractProof proof) { super(rule, formula, proof); } @@ -95,18 +96,21 @@ OpenSMTSubproof generateProof(String proof, OpenSmtFormulaCreator creator) { formula = creator.encapsulate(creator.getEnv().parseFormula(cls3)); OpenSMTSubproof pivot = new OpenSMTSubproof(new OpenSMTProofRule("pivot"), formula, this); + nodes.put(cls3, pivot); this.addEdge(pre, nodes.get(cls3)); if (formulaStr.equals("-")) result = pre; + break; default: break; } - } else if (exp instanceof Deque) { + } else if (exp instanceof Deque) { iterStack.push(((Deque) exp).iterator()); } } + assert result != null; return result; } @@ -126,14 +130,6 @@ void handleLet( OpenSMTSubproof res = new OpenSMTSubproof(new OpenSMTProofRule("res"), null, this); resNodes.push(res); nodes.putIfAbsent((String) exp, res); - } else { - String formulaStr = serializeDeque((Deque) v2); - nodes.putIfAbsent( - (String) exp, - new OpenSMTSubproof( - new OpenSMTProofRule("leaf"), - creator.encapsulate(creator.getEnv().parseFormula(formulaStr)), - this)); } } else { String formulaStr = serializeDeque((Deque) v1); diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java index dfc363b8c2..ea35012642 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolAbstractProver.java @@ -30,7 +30,6 @@ import java.util.Deque; import java.util.HashMap; import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -326,7 +325,7 @@ private void clausifyResChain(Subproof root, BooleanFormulaManager bfmgr) { visited.put(node, Boolean.TRUE); // Mark node as visited // Push all children onto stack - LinkedHashSet children = node.getArguments(); + Set children = node.getArguments(); List childrenList = new ArrayList<>(children); for (int i = childrenList.size() - 1; i >= 0; i--) { Subproof child = childrenList.get(i); @@ -349,7 +348,7 @@ private void clausifyResChain(Subproof root, BooleanFormulaManager bfmgr) { // process proof nodes and compute formulas for res-chain nodes private void processResChain(Subproof node, BooleanFormulaManager bfmgr) { - LinkedHashSet childrenSet = node.getArguments(); + Set childrenSet = node.getArguments(); List children = new ArrayList<>(childrenSet); // If the current node is a RES_CHAIN, compute the resolved formula diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProof.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProof.java index 70d104ccb8..15758e916b 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProof.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProof.java @@ -41,23 +41,24 @@ */ class SmtInterpolProof extends AbstractProof { protected enum Rules implements ProofRule { - COEFFS, - VALUES, - DIVISOR, - POS, - UNIT, + COEFFS("coeffs"), + VALUES("values"), + DIVISOR("divisor"), + POS("pos"), + UNIT("unit"), DEFINE_FUN("define-fun"), DECLARE_FUN("declare-fun"), - RUP, - PIVOT; - String name; + RUP("rup"), + PIVOT("pivot"); + final String name; - private Rules() {} Rules(String pDefineFun) { name = pDefineFun; } + + static Rules getFromName(String pName) { if (pName.equals("DEFINE-FUN")) { return DEFINE_FUN; @@ -155,8 +156,8 @@ SmtInterpolSubproof createProof(ProvitionalProofNode pProofNode) { return computed.get(pProofNode); } - ProvitionalProofNode createPPNDag(Term proof) { - return new ProvitionalProofNode(proof); + ProvitionalProofNode createPPNDag(Term pTerm) { + return new ProvitionalProofNode(pTerm); } class ProvitionalProofNode { diff --git a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java index 03e0cb6200..6657df06b8 100644 --- a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java +++ b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java @@ -37,7 +37,6 @@ import org.sosy_lab.java_smt.api.FormulaType.ArrayFormulaType; import org.sosy_lab.java_smt.api.FunctionDeclaration; import org.sosy_lab.java_smt.api.Model; -import org.sosy_lab.java_smt.api.NumeralFormula; import org.sosy_lab.java_smt.api.NumeralFormula.IntegerFormula; import org.sosy_lab.java_smt.api.NumeralFormula.RationalFormula; import org.sosy_lab.java_smt.api.ProverEnvironment; @@ -265,7 +264,7 @@ public void testGetSimpleBooleanProof() throws InterruptedException, SolverExcep } @Test - public void testGetComplexRationalNumeralaAndUFProof() + public void testGetComplexRationalNumeralAndUFProof() throws InterruptedException, SolverException { requireProofGeneration(); // Ensures proofs are supported // "(declare-fun x1 () Real)" + @@ -290,9 +289,9 @@ public void testGetComplexRationalNumeralaAndUFProof() RationalFormula y2 = mgr.makeVariable(FormulaType.RationalType, "y2"); RationalFormula y3 = mgr.makeVariable(FormulaType.RationalType, "y3"); RationalFormula b = mgr.makeVariable(FormulaType.RationalType, "b"); - FunctionDeclaration f = + FunctionDeclaration f = mgr.getUFManager().declareUF("f", FormulaType.RationalType, FormulaType.RationalType); - FunctionDeclaration g = + FunctionDeclaration g = mgr.getUFManager().declareUF("g", FormulaType.RationalType, FormulaType.RationalType); BooleanFormula a = bmgr.makeVariable("a"); BooleanFormula c = bmgr.makeVariable("c"); @@ -304,19 +303,19 @@ public void testGetComplexRationalNumeralaAndUFProof() prover.addConstraint( bmgr.and( a, - rfmgr.equal(rfmgr.add((NumeralFormula) mgr.makeApplication(f, y1), y2), y3), + rfmgr.equal(rfmgr.add(mgr.makeApplication(f, y1), y2), y3), rfmgr.lessOrEquals(y1, x1))); // "(assert (and (= x2 (g b)) (= y2 (g b)) (<= x1 y1) (< x3 y3)))" prover.addConstraint( bmgr.and( - rfmgr.equal(x2, (NumeralFormula) mgr.makeApplication(g, b)), - rfmgr.equal(y2, (NumeralFormula) mgr.makeApplication(g, b)), + rfmgr.equal(x2, mgr.makeApplication(g, b)), + rfmgr.equal(y2, mgr.makeApplication(g, b)), rfmgr.lessOrEquals(x1, y1), rfmgr.lessThan(x3, y3))); // "(assert (= a (= (+ (f x1) x2) x3)))" prover.addConstraint( bmgr.equivalence( - a, rfmgr.equal(rfmgr.add((NumeralFormula) mgr.makeApplication(f, x1), x2), x3))); + a, rfmgr.equal(rfmgr.add(mgr.makeApplication(f, x1), x2), x3))); // "(assert (and (or a c) (not c)))" prover.addConstraint(bmgr.and(bmgr.or(a, c), bmgr.not(c))); assertTrue(prover.isUnsat()); @@ -373,6 +372,7 @@ public void proofOfTrueTest() throws InterruptedException, SolverException { assertThat(prover.isUnsat()).isFalse(); Subproof proof = prover.getProof(); + assertThat(proof).isNotNull(); } catch (UnsupportedOperationException e) { assertThat(e) From c8009f0f7def46f3f7daf9010b569c29ac47cef5 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 26 May 2025 15:54:16 +0200 Subject: [PATCH 122/132] MathSAT5: added test in `Mathsat5NativeApiTest` taken from `api_example_proofs.c`. --- .../mathsat5/Mathsat5NativeApiTest.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java index c3fe83bfaf..68d10a11a6 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java @@ -17,6 +17,7 @@ import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_decl_get_arity; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_decl_get_name; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_destroy_config; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_destroy_env; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_destroy_model_iterator; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_destroy_proof_manager; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_from_smtlib2; @@ -128,6 +129,56 @@ public void proofSharedEnvironmentTest() testProofManager(sharedEnv); } + @Test + public void api_exampleProofTest() throws SolverException, InterruptedException { + + long cfg = msat_create_config(); + msat_set_option_checked(cfg, "proof_generation", "true"); + msat_set_option_checked(cfg, "preprocessor.toplevel_propagation", "false"); + msat_set_option_checked(cfg, "preprocessor.simplification", "0"); + msat_set_option_checked(cfg, "theory.bv.eager", "false"); // for BV, only the lazy solver is + + msat_set_option_checked(cfg, "theory.fp.mode", "2"); + + long env = msat_create_env(cfg); + msat_destroy_config(cfg); + + long f; + + String smtlib2 = + "(declare-fun x1 () Real)" + + "(declare-fun x2 () Real)" + + "(declare-fun x3 () Real)" + + "(declare-fun y1 () Real)" + + "(declare-fun y2 () Real)" + + "(declare-fun y3 () Real)" + + "(declare-fun b () Real)" + + "(declare-fun f (Real) Real)" + + "(declare-fun g (Real) Real)" + + "(declare-fun a () Bool)" + + "(declare-fun c () Bool)" + + "(assert (and a (= (+ (f y1) y2) y3) (<= y1 x1)))" + + "(assert (and (= x2 (g b)) (= y2 (g b)) (<= x1 y1) (< x3 y3)))" + + "(assert (= a (= (+ (f x1) x2) x3)))" + + "(assert (and (or a c) (not c)))"; + f = msat_from_smtlib2(env, smtlib2); + + msat_assert_formula(env, f); + + boolean isSat = msat_check_sat(env); + + assertThat(isSat).isFalse(); + + long pm = msat_get_proof_manager(env); + + long proof = msat_get_proof(pm); + + assertThat(proof).isNotNull(); + + msat_destroy_proof_manager(pm); + msat_destroy_env(env); + } + private void testProofManager(long testEnv) throws InterruptedException, SolverException { const0 = msat_make_number(testEnv, "0"); const1 = msat_make_number(testEnv, "1"); From 25f67f7448467fab78843afd8b257a8b96918a7e Mon Sep 17 00:00:00 2001 From: BaierD Date: Mon, 26 May 2025 16:46:41 +0200 Subject: [PATCH 123/132] Don't check primitive for null in Mathsat5 native tests and simply check that some proof is returned. --- .../java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java index 68d10a11a6..05259d38a9 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java @@ -129,6 +129,7 @@ public void proofSharedEnvironmentTest() testProofManager(sharedEnv); } + @SuppressWarnings("CheckReturnValue") @Test public void api_exampleProofTest() throws SolverException, InterruptedException { @@ -171,9 +172,7 @@ public void api_exampleProofTest() throws SolverException, InterruptedException long pm = msat_get_proof_manager(env); - long proof = msat_get_proof(pm); - - assertThat(proof).isNotNull(); + msat_get_proof(pm); msat_destroy_proof_manager(pm); msat_destroy_env(env); From 420011296a0d3b9f6fb6c257e71cfab7c8a3f49e Mon Sep 17 00:00:00 2001 From: BaierD Date: Mon, 26 May 2025 16:50:55 +0200 Subject: [PATCH 124/132] Add require methods for theories used in proof tests --- .../java_smt/test/ProverEnvironmentTest.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java index 6657df06b8..b5983fac01 100644 --- a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java +++ b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java @@ -309,13 +309,12 @@ public void testGetComplexRationalNumeralAndUFProof() prover.addConstraint( bmgr.and( rfmgr.equal(x2, mgr.makeApplication(g, b)), - rfmgr.equal(y2, mgr.makeApplication(g, b)), + rfmgr.equal(y2, mgr.makeApplication(g, b)), rfmgr.lessOrEquals(x1, y1), rfmgr.lessThan(x3, y3))); // "(assert (= a (= (+ (f x1) x2) x3)))" prover.addConstraint( - bmgr.equivalence( - a, rfmgr.equal(rfmgr.add(mgr.makeApplication(f, x1), x2), x3))); + bmgr.equivalence(a, rfmgr.equal(rfmgr.add(mgr.makeApplication(f, x1), x2), x3))); // "(assert (and (or a c) (not c)))" prover.addConstraint(bmgr.and(bmgr.or(a, c), bmgr.not(c))); assertTrue(prover.isUnsat()); @@ -426,6 +425,8 @@ public void proofOfFalseTest() throws InterruptedException, SolverException { @Test public void testGetSimpleIntegerProof() throws InterruptedException, SolverException { requireProofGeneration(); // Ensures proofs are supported + requireIntegers(); + IntegerFormula x1 = imgr.makeVariable("x1"); IntegerFormula two = imgr.makeNumber("2"); IntegerFormula cero = imgr.makeNumber("0"); @@ -571,6 +572,8 @@ public void getProofAfterGetProofAndAddingAssertionsTest() public void getProofAfterGetProofClearingStackAndAddingDifferentAssertionsTest() throws InterruptedException, SolverException { requireProofGeneration(); // Ensures proofs are supported + requireIntegers(); + BooleanFormula q1 = bmgr.makeVariable("q1"); BooleanFormula q2 = bmgr.makeVariable("q2"); IntegerFormula x1 = imgr.makeVariable("x1"); @@ -699,6 +702,8 @@ public void getProofWithoutProofProductionEnabledTest() @Test public void getBitVectorProofTest() throws InterruptedException, SolverException { requireProofGeneration(); + requireBitvectors(); + BitvectorFormula one = bvmgr.makeBitvector(32, 1); // unsigned char @@ -758,6 +763,7 @@ public void getBitVectorProofTest() throws InterruptedException, SolverException public void getArrayProofTest() throws InterruptedException, SolverException { requireProofGeneration(); requireIntegers(); + requireArrays(); // (arr2 = store(arr1, 4, 2)) & !(select(arr2, 4) = 2) ArrayFormulaType type = From b6a786ccbb6529d28ba10a6e746ea0f591db1ce3 Mon Sep 17 00:00:00 2001 From: BaierD Date: Mon, 26 May 2025 16:54:56 +0200 Subject: [PATCH 125/132] Add an assertion as a hint for a necessary check when traversing Mathsat5 proofs --- src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5Proof.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5Proof.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5Proof.java index f3178f04ac..f1ab0b7c46 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5Proof.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5Proof.java @@ -143,6 +143,7 @@ private Formula generateFormula( msat_proof_get_term(proof)); // For clause-hype, we create the clause using the children } else if (rule.equals(Rule.CLAUSE_HYP)) { + assert msat_proof_get_arity(proof) > 0; long or = msat_proof_get_term(msat_proof_get_child(proof, 0)); for (int i = 1; i < children; i++) { long child = msat_proof_get_term(msat_proof_get_child(proof, i)); From 27e4bb315a68ad62eefd81db2cee5c607d6806de Mon Sep 17 00:00:00 2001 From: BaierD Date: Mon, 26 May 2025 16:55:45 +0200 Subject: [PATCH 126/132] Disable eager BV theory option for proof generation in Mathsat, as it can't produce BV proofs with it enabled --- .../java_smt/solvers/mathsat5/Mathsat5AbstractProver.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5AbstractProver.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5AbstractProver.java index 9fa0469b84..3fa39f08ca 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5AbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5AbstractProver.java @@ -78,7 +78,8 @@ private long buildConfig(Set opts) { Map config = new LinkedHashMap<>(); boolean generateUnsatCore = opts.contains(ProverOptions.GENERATE_UNSAT_CORE) - || opts.contains(ProverOptions.GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS); + || opts.contains(ProverOptions.GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS) + || opts.contains(ProverOptions.GENERATE_PROOFS); config.put("model_generation", opts.contains(ProverOptions.GENERATE_MODELS) ? "true" : "false"); config.put("unsat_core_generation", generateUnsatCore ? "1" : "0"); config.put("proof_generation", opts.contains(ProverOptions.GENERATE_PROOFS) ? "true" : "false"); From 14e4991b99e5a1a4c8a6e4b16860f484bf13dea3 Mon Sep 17 00:00:00 2001 From: BaierD Date: Mon, 26 May 2025 17:09:44 +0200 Subject: [PATCH 127/132] Add more require methods for theories used in proof tests --- src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java index b5983fac01..c273b01674 100644 --- a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java +++ b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java @@ -267,6 +267,8 @@ public void testGetSimpleBooleanProof() throws InterruptedException, SolverExcep public void testGetComplexRationalNumeralAndUFProof() throws InterruptedException, SolverException { requireProofGeneration(); // Ensures proofs are supported + requireRationals(); + // "(declare-fun x1 () Real)" + // "(declare-fun x2 () Real)" + // "(declare-fun x3 () Real)" + From 08f80381b60178014435036a2b7916b602553a3e Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 26 May 2025 18:16:13 +0200 Subject: [PATCH 128/132] MathSAT5: added test in `Mathsat5NativeApiTest` to confirm that an exception is thrown when requestion a proof for asserting `false`. Took MathSAT5 out of `proofOfFalseTest` test. --- .../mathsat5/Mathsat5NativeApiTest.java | 31 +++++++++++++++++++ .../java_smt/test/ProverEnvironmentTest.java | 4 +++ 2 files changed, 35 insertions(+) diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java index 05259d38a9..2f196a4042 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java @@ -9,6 +9,7 @@ package org.sosy_lab.java_smt.solvers.mathsat5; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertThrows; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_assert_formula; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_check_sat; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_create_config; @@ -35,6 +36,7 @@ import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_make_eq; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_make_equal; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_make_exp; +import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_make_false; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_make_log; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_make_not; import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_make_number; @@ -129,6 +131,35 @@ public void proofSharedEnvironmentTest() testProofManager(sharedEnv); } + //MathSAT5 can not produce a msat_manager because there is no proof in this case. See + // ProverEnvironmentTest class + @SuppressWarnings("CheckReturnValue") + @Test + public void testProofOfFalse() throws SolverException, InterruptedException { + assertThrows(IllegalArgumentException.class, () -> { + long cfg = msat_create_config(); + + msat_set_option_checked(cfg, "proof_generation", "true"); + + env = msat_create_env(cfg); + msat_destroy_config(cfg); + long bottom = msat_make_false(env); + + msat_assert_formula(env, bottom); + + boolean isSat = msat_check_sat(env); + + assertThat(isSat).isFalse(); + + long pm = msat_get_proof_manager(env); + + msat_get_proof(pm); + + msat_destroy_proof_manager(pm); + msat_destroy_env(env); + }); + } + @SuppressWarnings("CheckReturnValue") @Test public void api_exampleProofTest() throws SolverException, InterruptedException { diff --git a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java index b5983fac01..616c8b0346 100644 --- a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java +++ b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java @@ -45,6 +45,7 @@ import org.sosy_lab.java_smt.api.SolverException; import org.sosy_lab.java_smt.api.proofs.Proof.Subproof; import org.sosy_lab.java_smt.api.proofs.ProofRule; +import org.sosy_lab.java_smt.basicimpl.AbstractProof.AbstractSubproof; import org.sosy_lab.java_smt.solvers.bitwuzla.BitwuzlaSolverContext; import org.sosy_lab.java_smt.solvers.boolector.BoolectorSolverContext; import org.sosy_lab.java_smt.solvers.cvc4.CVC4SolverContext; @@ -391,9 +392,12 @@ public void proofOfTrueTest() throws InterruptedException, SolverException { } } + //TODO: Mathsat5 does not produce a msat_manager. It adds null to de asserted formulas when + // adding the constraint for false. @Test public void proofOfFalseTest() throws InterruptedException, SolverException { requireProofGeneration(); + assume().that(solverToUse()).isNotEqualTo(MATHSAT5); BooleanFormula bottom = bmgr.makeFalse(); From 61712247ef47664ed9da63926924f6ebef60977f Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 26 May 2025 18:21:25 +0200 Subject: [PATCH 129/132] MathSAT5: now correctly handles the case when no proof manager is available and throw a corresponding Exception. --- .../java_smt/basicimpl/AbstractProof.java | 3 +- .../mathsat5/Mathsat5NativeApiTest.java | 32 ++++++++++--------- .../mathsat5/Mathsat5TheoremProver.java | 11 +++++-- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java index 4fdabd445b..bfccfbef14 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java @@ -116,8 +116,7 @@ protected String proofAsString(int indentLevel) { sb.append(indent).append("Formula: ").append(sFormula).append("\n"); sb.append(indent).append("Rule: ").append(getRule().getName()).append("\n"); - sb - .append(indent) + sb.append(indent) .append("No. Children: ") .append(this.isLeaf() ? 0 : getArguments().size()) .append("\n"); diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java index 2f196a4042..b6e0820301 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApiTest.java @@ -131,33 +131,35 @@ public void proofSharedEnvironmentTest() testProofManager(sharedEnv); } - //MathSAT5 can not produce a msat_manager because there is no proof in this case. See + // MathSAT5 can not produce a msat_manager because there is no proof in this case. See // ProverEnvironmentTest class @SuppressWarnings("CheckReturnValue") @Test public void testProofOfFalse() throws SolverException, InterruptedException { - assertThrows(IllegalArgumentException.class, () -> { - long cfg = msat_create_config(); + assertThrows( + IllegalArgumentException.class, + () -> { + long cfg = msat_create_config(); - msat_set_option_checked(cfg, "proof_generation", "true"); + msat_set_option_checked(cfg, "proof_generation", "true"); - env = msat_create_env(cfg); - msat_destroy_config(cfg); - long bottom = msat_make_false(env); + env = msat_create_env(cfg); + msat_destroy_config(cfg); + long bottom = msat_make_false(env); - msat_assert_formula(env, bottom); + msat_assert_formula(env, bottom); - boolean isSat = msat_check_sat(env); + boolean isSat = msat_check_sat(env); - assertThat(isSat).isFalse(); + assertThat(isSat).isFalse(); - long pm = msat_get_proof_manager(env); + long pm = msat_get_proof_manager(env); - msat_get_proof(pm); + msat_get_proof(pm); - msat_destroy_proof_manager(pm); - msat_destroy_env(env); - }); + msat_destroy_proof_manager(pm); + msat_destroy_env(env); + }); } @SuppressWarnings("CheckReturnValue") diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java index 799a1b95a2..8e4cddc7b0 100644 --- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java +++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5TheoremProver.java @@ -69,10 +69,15 @@ public Subproof getProof() throws SolverException, InterruptedException { checkGenerateProofs(); Mathsat5Proof proof = new Mathsat5Proof(); - - long pm = msat_get_proof_manager(curEnv); + Mathsat5Subproof root; + long pm; + try { + pm = msat_get_proof_manager(curEnv); + } catch (IllegalArgumentException e) { + throw new UnsupportedOperationException("No proof available.", e); + } long msatProof = msat_get_proof(pm); - Mathsat5Subproof root = proof.fromMsatProof(this, msatProof); + root = proof.fromMsatProof(this, msatProof); clausifyResChain(root, context.getFormulaManager().getBooleanFormulaManager()); msat_destroy_proof_manager(pm); From 78f891c628ae9565bc687ac6222ebdeb39ff0407 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Mon, 26 May 2025 18:24:26 +0200 Subject: [PATCH 130/132] Checkstyle --- .../java_smt/solvers/smtinterpol/SmtInterpolProof.java | 3 --- src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java | 3 +-- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProof.java b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProof.java index 15758e916b..4a814bf6c1 100644 --- a/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProof.java +++ b/src/org/sosy_lab/java_smt/solvers/smtinterpol/SmtInterpolProof.java @@ -52,13 +52,10 @@ protected enum Rules implements ProofRule { PIVOT("pivot"); final String name; - Rules(String pDefineFun) { name = pDefineFun; } - - static Rules getFromName(String pName) { if (pName.equals("DEFINE-FUN")) { return DEFINE_FUN; diff --git a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java index e32aee1f6f..392f3e4cee 100644 --- a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java +++ b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java @@ -45,7 +45,6 @@ import org.sosy_lab.java_smt.api.SolverException; import org.sosy_lab.java_smt.api.proofs.Proof.Subproof; import org.sosy_lab.java_smt.api.proofs.ProofRule; -import org.sosy_lab.java_smt.basicimpl.AbstractProof.AbstractSubproof; import org.sosy_lab.java_smt.solvers.bitwuzla.BitwuzlaSolverContext; import org.sosy_lab.java_smt.solvers.boolector.BoolectorSolverContext; import org.sosy_lab.java_smt.solvers.cvc4.CVC4SolverContext; @@ -394,7 +393,7 @@ public void proofOfTrueTest() throws InterruptedException, SolverException { } } - //TODO: Mathsat5 does not produce a msat_manager. It adds null to de asserted formulas when + // TODO: Mathsat5 does not produce a msat_manager. It adds null to de asserted formulas when // adding the constraint for false. @Test public void proofOfFalseTest() throws InterruptedException, SolverException { From 5383562f047df1b2976ebf8de5344d0bf2c8a54e Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Wed, 28 May 2025 17:28:53 +0200 Subject: [PATCH 131/132] OpenSMT: formulas for proofs are stored as strings in each node which then get parsed in `OpenSmtAbstractProver` --- .../solvers/opensmt/OpenSMTProof.java | 82 ++++++++++--------- .../opensmt/OpenSmtAbstractProver.java | 44 +++++++++- .../java_smt/test/ProverEnvironmentTest.java | 8 +- 3 files changed, 85 insertions(+), 49 deletions(-) diff --git a/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSMTProof.java b/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSMTProof.java index 39d2e480b0..5f4641fd15 100644 --- a/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSMTProof.java +++ b/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSMTProof.java @@ -37,9 +37,16 @@ public String getName() { } static class OpenSMTSubproof extends AbstractSubproof { + String sFormula; + protected OpenSMTSubproof(ProofRule rule, Formula formula, AbstractProof proof) { super(rule, formula, proof); } + + protected OpenSMTSubproof(ProofRule rule, AbstractProof proof, String sFormula) { + super(rule, null, proof); + this.sFormula = sFormula; + } } OpenSMTSubproof generateProof(String proof, OpenSmtFormulaCreator creator) { @@ -51,7 +58,6 @@ OpenSMTSubproof generateProof(String proof, OpenSmtFormulaCreator creator) { iterStack.push(rootStack.iterator()); OpenSMTSubproof result = null; - Formula formula = null; String formulaStr = ""; while (!iterStack.isEmpty()) { @@ -73,7 +79,7 @@ OpenSMTSubproof generateProof(String proof, OpenSmtFormulaCreator creator) { throw new IllegalStateException("Expected argument after 'let'"); } Object letArg = currentIter.next(); - handleLet(letArg, nodes, resNodes, creator); + handleLet(letArg, nodes, resNodes, creator, formulaStr); break; case ";": @@ -81,27 +87,9 @@ OpenSMTSubproof generateProof(String proof, OpenSmtFormulaCreator creator) { throw new IllegalStateException("Expected formula string after ';'"); } formulaStr = (String) currentIter.next(); - formula = creator.encapsulate(creator.getEnv().parseFormula(formulaStr)); + // formula = creator.encapsulate(creator.getEnv().parseFormula(formulaStr)); break; - case "res": - String cls1 = (String) currentIter.next(); - String cls2 = (String) currentIter.next(); - String cls3 = (String) currentIter.next(); - - OpenSMTSubproof pre = resNodes.pop(); - pre.setFormula(formula); - this.addEdge(pre, nodes.get(cls1)); - this.addEdge(pre, nodes.get(cls2)); - formula = creator.encapsulate(creator.getEnv().parseFormula(cls3)); - OpenSMTSubproof pivot = - new OpenSMTSubproof(new OpenSMTProofRule("pivot"), formula, this); - nodes.put(cls3, pivot); - this.addEdge(pre, nodes.get(cls3)); - - if (formulaStr.equals("-")) result = pre; - - break; default: break; } @@ -109,7 +97,7 @@ OpenSMTSubproof generateProof(String proof, OpenSmtFormulaCreator creator) { iterStack.push(((Deque) exp).iterator()); } } - + result = resNodes.pop(); assert result != null; return result; } @@ -118,36 +106,50 @@ void handleLet( Object stack, Map nodes, Deque resNodes, - OpenSmtFormulaCreator creator) { + OpenSmtFormulaCreator creator, + String lastSeenFormula) { assert stack instanceof Deque; // no unchecked cast - Object exp = ((Deque) stack).pop(); - if (exp instanceof String) { // first element should be the assigned name + Object expression = ((Deque) stack).pop(); + if (expression instanceof String) { // first element should be the assigned name Object v1 = ((Deque) stack).peek(); if (v1 instanceof Deque) { // then a stack with the formula - Object v2 = ((Deque) stack).peek(); + Object v2 = ((Deque) v1).peek(); if (v2 instanceof String) { if (v2.equals("res")) { - OpenSMTSubproof res = new OpenSMTSubproof(new OpenSMTProofRule("res"), null, this); + ((Deque) v1).pop(); // remove "res" + String cls1 = (String) ((Deque) v1).pop(); + String cls2 = (String) ((Deque) v1).pop(); + String pivot = (String) ((Deque) v1).pop(); + + OpenSMTSubproof res = + new OpenSMTSubproof(new OpenSMTProofRule("res"), this, lastSeenFormula); + this.addEdge(res, nodes.get(cls1)); + this.addEdge(res, nodes.get(cls2)); + + OpenSMTSubproof pivotNode = + new OpenSMTSubproof(new OpenSMTProofRule("pivot"), this, pivot); + this.addEdge(res, pivotNode); + + nodes.putIfAbsent((String) expression, res); resNodes.push(res); - nodes.putIfAbsent((String) exp, res); + } else { + String s = serializeDeque((Deque) v1); + nodes.putIfAbsent( + (String) expression, new OpenSMTSubproof(new OpenSMTProofRule("leaf"), this, s)); } } else { - String formulaStr = serializeDeque((Deque) v1); + String s = serializeDeque((Deque) v1); nodes.putIfAbsent( - (String) exp, - new OpenSMTSubproof( - new OpenSMTProofRule("leaf"), - creator.encapsulate(creator.getEnv().parseFormula(formulaStr)), - this)); + (String) expression, new OpenSMTSubproof(new OpenSMTProofRule("leaf"), this, s)); } } else if (v1 instanceof String) { // or a formula + String f = (String) v1; + nodes.putIfAbsent( + (String) expression, new OpenSMTSubproof(new OpenSMTProofRule("leaf"), this, f)); + } else { // this should handle when no term was assigned to the clause, meaning an empty + // clause was declared nodes.putIfAbsent( - (String) exp, - new OpenSMTSubproof( - new OpenSMTProofRule("leaf"), - creator.encapsulate(creator.getEnv().parseFormula((String) v1)), // this does not - // work right now - this)); + (String) expression, new OpenSMTSubproof(new OpenSMTProofRule("leaf"), this, "-")); } } } diff --git a/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSmtAbstractProver.java b/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSmtAbstractProver.java index 328504afd5..10153d7f5d 100644 --- a/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSmtAbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSmtAbstractProver.java @@ -15,6 +15,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -23,6 +24,7 @@ import org.sosy_lab.common.ShutdownNotifier; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.Evaluator; +import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.FormulaManager; import org.sosy_lab.java_smt.api.Model; import org.sosy_lab.java_smt.api.Model.ValueAssignment; @@ -31,6 +33,7 @@ import org.sosy_lab.java_smt.api.proofs.Proof.Subproof; import org.sosy_lab.java_smt.basicimpl.AbstractProverWithAllSat; import org.sosy_lab.java_smt.basicimpl.ShutdownHook; +import org.sosy_lab.java_smt.solvers.opensmt.OpenSMTProof.OpenSMTSubproof; import org.sosy_lab.java_smt.solvers.opensmt.OpenSmtSolverContext.OpenSMTOptions; import org.sosy_lab.java_smt.solvers.opensmt.api.Logic; import org.sosy_lab.java_smt.solvers.opensmt.api.MainSolver; @@ -47,6 +50,7 @@ public abstract class OpenSmtAbstractProver extends AbstractProverWithAllSat< protected final OpenSmtFormulaCreator creator; protected final MainSolver osmtSolver; protected final SMTConfig osmtConfig; + private final FormulaManager formulaManager; private boolean changedSinceLastSatQuery = false; @@ -64,6 +68,7 @@ protected OpenSmtAbstractProver( // not get garbage collected osmtConfig = pConfig; osmtSolver = new MainSolver(creator.getEnv(), pConfig, "JavaSmt"); + formulaManager = pMgr; // needed for parsing formulas in proofs } protected static SMTConfig getConfigInstance( @@ -287,10 +292,41 @@ public Optional> unsatCoreOverAssumptions( @Override public Subproof getProof() { - throw new UnsupportedOperationException( - "Proof generation is not available for the current solver."); - // OpenSMTProof proof = new OpenSMTProof(); - // return proof.generateProof(osmtSolver.printResolutionProofSMT2(), creator); + // throw new UnsupportedOperationException( + // "Proof generation is not available for the current solver."); + OpenSMTProof proof = new OpenSMTProof(); + System.out.println(osmtSolver.printResolutionProofSMT2()); + OpenSMTSubproof root = proof.generateProof(osmtSolver.printResolutionProofSMT2(), creator); + parseFormulas(root); + return root; + } + + private void parseFormulas(Subproof p) { + ((OpenSMTSubproof) p).setFormula(formulaManager.getBooleanFormulaManager().makeFalse()); + if (!p.isLeaf()) { + LinkedHashSet children = new LinkedHashSet<>(p.getArguments()); + Formula formula; + String formulaString; + for (Subproof child : children) { + formulaString = ((OpenSMTSubproof) child).sFormula; + + if (formulaString.startsWith("(")) { + formula = formulaManager.parse(formulaString); + } else if (formulaString.equals("-")) { + formula = formulaManager.getBooleanFormulaManager().makeFalse(); + } else { + if (formulaManager.isValidName(formulaString)) { + formula = formulaManager.getBooleanFormulaManager().makeVariable(formulaString); + } else { + formula = formulaManager.parse("(" + formulaString + ")"); + } + } + ((OpenSMTSubproof) child).setFormula(formula); + parseFormulas(child); + // System.out.println(formulaString); + // System.out.println(formula); + } + } } @Override diff --git a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java index 392f3e4cee..5e9833eb31 100644 --- a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java +++ b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java @@ -230,11 +230,11 @@ public void testGetSimpleBooleanProof() throws InterruptedException, SolverExcep assertThat(proof.getRule()).isNotNull(); assertThat(proof.getRule()).isInstanceOf(ProofRule.class); - // Test getFormula(), the root should always be false + // Test getFormula() if (solverToUse().equals(SMTINTERPOL)) { assertThat(proof.getFormula()).isNull(); } else { - assertThat(proof.getFormula()).isEqualTo(bmgr.makeFalse()); + assertThat(proof.getFormula()).isNotNull(); } // Test getArguments() @@ -383,7 +383,6 @@ public void proofOfTrueTest() throws InterruptedException, SolverException { boolean isExpected = contextClass.equals(CVC4SolverContext.class) || contextClass.equals(PrincessSolverContext.class) - || contextClass.equals(OpenSmtSolverContext.class) || contextClass.equals(BoolectorSolverContext.class) || contextClass.equals(BitwuzlaSolverContext.class) || contextClass.equals(Yices2SolverContext.class); @@ -417,7 +416,6 @@ public void proofOfFalseTest() throws InterruptedException, SolverException { boolean isExpected = contextClass.equals(CVC4SolverContext.class) || contextClass.equals(PrincessSolverContext.class) - || contextClass.equals(OpenSmtSolverContext.class) || contextClass.equals(BoolectorSolverContext.class) || contextClass.equals(BitwuzlaSolverContext.class) || contextClass.equals(Yices2SolverContext.class); @@ -474,7 +472,7 @@ public void testGetSimpleIntegerProof() throws InterruptedException, SolverExcep boolean isExpected = contextClass.equals(CVC4SolverContext.class) || contextClass.equals(PrincessSolverContext.class) - || contextClass.equals(OpenSmtSolverContext.class) + // || contextClass.equals(OpenSmtSolverContext.class) || contextClass.equals(BoolectorSolverContext.class) || contextClass.equals(BitwuzlaSolverContext.class) || contextClass.equals(Yices2SolverContext.class); From c2b67a9620d74061655e6c9a732df35733fe1fe5 Mon Sep 17 00:00:00 2001 From: Gabriel Carpio Date: Wed, 28 May 2025 19:10:31 +0200 Subject: [PATCH 132/132] OpenSMT: fix incorrect handling of nested applications of the resolution rule in the proof processing. --- .../java_smt/basicimpl/AbstractProof.java | 4 +- .../solvers/opensmt/OpenSMTProof.java | 90 ++++++++++++++++--- .../opensmt/OpenSmtAbstractProver.java | 60 ++++++++----- .../java_smt/test/ProverEnvironmentTest.java | 4 + 4 files changed, 120 insertions(+), 38 deletions(-) diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java index bfccfbef14..02d7bbed0a 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java @@ -60,9 +60,11 @@ protected AbstractSubproof(ProofRule rule, Formula formula, AbstractProof proof) this.proof = proof; } + // TODO: Use Optional instead of nullable + @Nullable @Override public Formula getFormula() { - return formula; + return this.formula; } @Override diff --git a/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSMTProof.java b/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSMTProof.java index 5f4641fd15..816cbb114e 100644 --- a/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSMTProof.java +++ b/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSMTProof.java @@ -116,20 +116,7 @@ void handleLet( Object v2 = ((Deque) v1).peek(); if (v2 instanceof String) { if (v2.equals("res")) { - ((Deque) v1).pop(); // remove "res" - String cls1 = (String) ((Deque) v1).pop(); - String cls2 = (String) ((Deque) v1).pop(); - String pivot = (String) ((Deque) v1).pop(); - - OpenSMTSubproof res = - new OpenSMTSubproof(new OpenSMTProofRule("res"), this, lastSeenFormula); - this.addEdge(res, nodes.get(cls1)); - this.addEdge(res, nodes.get(cls2)); - - OpenSMTSubproof pivotNode = - new OpenSMTSubproof(new OpenSMTProofRule("pivot"), this, pivot); - this.addEdge(res, pivotNode); - + OpenSMTSubproof res = processRes(v1, nodes, resNodes, creator, lastSeenFormula); nodes.putIfAbsent((String) expression, res); resNodes.push(res); } else { @@ -154,6 +141,81 @@ void handleLet( } } + OpenSMTSubproof processRes( + Object expr, + Map nodes, + Deque resNodes, + OpenSmtFormulaCreator creator, + String formulaStr) { + + Deque> stack = new ArrayDeque<>(); + Object current = expr; + OpenSMTSubproof result = null; + + while (true) { + if (!(current instanceof Deque)) { + throw new IllegalArgumentException("Expected Deque in res expression but got: " + current); + } + Deque deque = new ArrayDeque<>((Deque) current); + Object op = deque.pollFirst(); + if (!"res".equals(op)) { + throw new IllegalStateException("Expected 'res' at head, got: " + op); + } + + Object first = deque.pollFirst(); + if (first instanceof String) { + String cls1 = (String) first; + String cls2 = (String) deque.pollFirst(); + Object rawPivot = deque.pollFirst(); + String pivotStr = + rawPivot instanceof String ? (String) rawPivot : serializeDeque((Deque) rawPivot); + + OpenSMTSubproof left = nodes.get(cls1); + OpenSMTSubproof right = nodes.get(cls2); + OpenSMTSubproof pivotNode = + new OpenSMTSubproof(new OpenSMTProofRule("pivot"), this, pivotStr); + + OpenSMTSubproof res = + new OpenSMTSubproof( + new OpenSMTProofRule("res"), this, stack.isEmpty() ? formulaStr : null); + addEdge(res, left); + addEdge(res, right); + addEdge(res, pivotNode); + result = res; + break; + + } else if (first instanceof Deque) { + stack.push(deque); + current = first; + } else { + throw new IllegalStateException("Unexpected operand type in res: " + first); + } + } + + while (!stack.isEmpty()) { + Deque tokens = stack.pop(); + String cls2 = (String) tokens.pollFirst(); + Object rawPivot = tokens.pollFirst(); + String pivotStr = + rawPivot instanceof String ? (String) rawPivot : serializeDeque((Deque) rawPivot); + + OpenSMTSubproof right = nodes.get(cls2); + OpenSMTSubproof pivotNode = + new OpenSMTSubproof(new OpenSMTProofRule("pivot"), this, pivotStr); + + boolean isOuter = stack.isEmpty(); + OpenSMTSubproof parent = + new OpenSMTSubproof(new OpenSMTProofRule("res"), this, isOuter ? formulaStr : null); + + addEdge(parent, result); + addEdge(parent, right); + addEdge(parent, pivotNode); + result = parent; + } + + return result; + } + private String serializeDeque(Deque deque) { StringBuilder sb = new StringBuilder(); serializeHelper(deque, sb); diff --git a/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSmtAbstractProver.java b/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSmtAbstractProver.java index 10153d7f5d..d76524fed4 100644 --- a/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSmtAbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/opensmt/OpenSmtAbstractProver.java @@ -12,10 +12,11 @@ import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; +import java.util.Deque; import java.util.HashMap; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -290,41 +291,54 @@ public Optional> unsatCoreOverAssumptions( throw new UnsupportedOperationException("OpenSMT does not support solving with assumptions."); } + // TODO perform resolution throughout the DAG to calculate formulas that might not be present. @Override public Subproof getProof() { // throw new UnsupportedOperationException( // "Proof generation is not available for the current solver."); OpenSMTProof proof = new OpenSMTProof(); - System.out.println(osmtSolver.printResolutionProofSMT2()); + // System.out.println(osmtSolver.printResolutionProofSMT2()); OpenSMTSubproof root = proof.generateProof(osmtSolver.printResolutionProofSMT2(), creator); parseFormulas(root); return root; } - private void parseFormulas(Subproof p) { - ((OpenSMTSubproof) p).setFormula(formulaManager.getBooleanFormulaManager().makeFalse()); - if (!p.isLeaf()) { - LinkedHashSet children = new LinkedHashSet<>(p.getArguments()); + // TODO: the parse method is asigning true as the formula always. This should not be. + private void parseFormulas(Subproof root) { + Deque stack = new ArrayDeque<>(); + stack.push(root); + + while (!stack.isEmpty()) { + Subproof subproof = stack.pop(); Formula formula; - String formulaString; - for (Subproof child : children) { - formulaString = ((OpenSMTSubproof) child).sFormula; - - if (formulaString.startsWith("(")) { - formula = formulaManager.parse(formulaString); - } else if (formulaString.equals("-")) { - formula = formulaManager.getBooleanFormulaManager().makeFalse(); + String formulaString = ((OpenSMTSubproof) subproof).sFormula; + // System.out.println(formulaString); + + if (formulaString.startsWith("(")) { + formula = formulaManager.parse(formulaString); + // System.out.println(formula); + ((OpenSMTSubproof) subproof).setFormula(formula); + } else if (formulaString.equals("-")) { + formula = formulaManager.getBooleanFormulaManager().makeFalse(); + ((OpenSMTSubproof) subproof).setFormula(formula); + } else { + if (formulaManager.isValidName(formulaString)) { + formula = formulaManager.getBooleanFormulaManager().makeVariable(formulaString); + ((OpenSMTSubproof) subproof).setFormula(formula); } else { - if (formulaManager.isValidName(formulaString)) { - formula = formulaManager.getBooleanFormulaManager().makeVariable(formulaString); - } else { - formula = formulaManager.parse("(" + formulaString + ")"); - } + formula = formulaManager.parse("(" + formulaString + ")"); + ((OpenSMTSubproof) subproof).setFormula(formula); + } + } + + // ((OpenSMTSubproof) subproof).setFormula(formula); + // System.out.println("."); + // System.out.println(subproof.getFormula()); + if (!subproof.isLeaf()) { + Subproof[] children = subproof.getArguments().toArray(new Subproof[0]); + for (int i = children.length - 1; i >= 0; i--) { + stack.push(children[i]); } - ((OpenSMTSubproof) child).setFormula(formula); - parseFormulas(child); - // System.out.println(formulaString); - // System.out.println(formula); } } } diff --git a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java index 5e9833eb31..e0458437c6 100644 --- a/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java +++ b/src/org/sosy_lab/java_smt/test/ProverEnvironmentTest.java @@ -464,6 +464,10 @@ public void testGetSimpleIntegerProof() throws InterruptedException, SolverExcep assertThat(leaf).isNotNull(); assertThat(leaf.isLeaf()).isTrue(); + // if (solverToUse().equals(OPENSMT)) { + // System.out.println(((AbstractSubproof) proof).proofAsString()); + // } + } catch (UnsupportedOperationException e) { assertThat(e) .hasMessageThat()