9
9
package org .sosy_lab .java_smt .solvers .bitwuzla ;
10
10
11
11
import static com .google .common .base .Preconditions .checkArgument ;
12
+ import static org .sosy_lab .common .collect .Collections3 .transformedImmutableSetCopy ;
12
13
13
14
import com .google .common .base .Preconditions ;
14
15
import com .google .common .collect .HashBasedTable ;
15
16
import com .google .common .collect .ImmutableList ;
16
- import com .google .common .collect .ImmutableSet ;
17
- import com .google .common .collect .Maps ;
18
- import com .google .common .collect .Sets ;
19
17
import com .google .common .collect .Table ;
20
18
import java .math .BigInteger ;
19
+ import java .util .ArrayDeque ;
21
20
import java .util .ArrayList ;
21
+ import java .util .Collection ;
22
+ import java .util .Deque ;
22
23
import java .util .HashMap ;
23
24
import java .util .Iterator ;
25
+ import java .util .LinkedHashSet ;
24
26
import java .util .List ;
25
27
import java .util .Map ;
26
28
import java .util .Map .Entry ;
@@ -60,7 +62,8 @@ public class BitwuzlaFormulaCreator extends FormulaCreator<Term, Sort, Void, Bit
60
62
private final Table <String , Sort , Term > formulaCache = HashBasedTable .create ();
61
63
62
64
/**
63
- * Maps symbols from fp-to-bv casts to their defining equation.
65
+ * This mapping stores symbols and their constraints, such as from fp-to-bv casts with their
66
+ * defining equation.
64
67
*
65
68
* <p>Bitwuzla does not support casts from floating-point to bitvector natively. The reason given
66
69
* is that the value is undefined for NaN and that the SMT-LIB standard also does not include such
@@ -72,7 +75,7 @@ public class BitwuzlaFormulaCreator extends FormulaCreator<Term, Sort, Void, Bit
72
75
* the newly introduced variable symbols and the values are the defining equations as mentioned
73
76
* above.
74
77
*/
75
- private final Map <String , Term > variableCasts = new HashMap <>();
78
+ private final Map <String , Term > constraintsForVariables = new HashMap <>();
76
79
77
80
protected BitwuzlaFormulaCreator (TermManager pTermManager ) {
78
81
super (null , pTermManager .mk_bool_sort (), null , null , null , null );
@@ -593,52 +596,34 @@ public Object convertValue(Term term) {
593
596
throw new AssertionError ("Unknown value type." );
594
597
}
595
598
596
- /** Add a side-condition from a fp-to-bv to the set . */
597
- public void addVariableCast (String newVariable , Term equal ) {
598
- variableCasts .put (newVariable , equal );
599
+ /** Add a constraint that is pushed onto the prover stack whenever the variable is used . */
600
+ public void addConstraintForVariable (String variable , Term constraint ) {
601
+ constraintsForVariables .put (variable , constraint );
599
602
}
600
603
601
604
/**
602
- * Returns a set of side-conditions that are needed to handle the variable casts in the terms.
605
+ * Returns a set of additional constraints (side-conditions) that are needed to use some variables
606
+ * from the given term, such as utility variables from casts.
603
607
*
604
608
* <p>Bitwuzla does not support fp-to-bv conversion natively. We have to use side-conditions as a
605
609
* workaround. When a term containing fp-to-bv casts is added to the assertion stack these
606
610
* side-conditions need to be collected by calling this method and then also adding them to the
607
611
* assertion stack.
608
612
*/
609
- public Iterable <Term > getVariableCasts (Iterable <Term > pTerms ) {
610
- // Build the transition function from the side-conditions. We map the variables on the left
611
- // side of the defining equation to the set of variables on the right side.
612
- // f.ex __CAST_TO_BV_0 -> fp.to_fp(CAST_TO_BV_0) = (+ a b)
613
- // becomes
614
- // Map.of(__CAST_TO_BV, Set.of(__CAST_TO_BV, a b))
615
- Map <String , Set <String >> transitions =
616
- Maps .transformValues (
617
- variableCasts ,
618
- term ->
619
- Sets .intersection (
620
- variableCasts .keySet (), extractVariablesAndUFs (term , false ).keySet ()));
621
-
622
- // Calculate the initial set of symbols from the terms in the argument
623
- ImmutableSet .Builder <String > initBuilder = ImmutableSet .builder ();
624
- for (Term term : pTerms ) {
625
- initBuilder .addAll (extractVariablesAndUFs (term , false ).keySet ());
626
- }
627
- ImmutableSet <String > initialSet = initBuilder .build ();
628
-
629
- Set <String > r0 = ImmutableSet .of ();
630
- Set <String > r1 = Sets .intersection (initialSet , transitions .keySet ());
631
- // Calculate the fixpoint for the transition function
632
- while (!r0 .equals (r1 )) {
633
- r0 = r1 ;
634
- // Iterate the transition function
635
- ImmutableSet .Builder <String > builder = ImmutableSet .builder ();
636
- for (String var : r0 ) {
637
- builder .addAll (transitions .get (var ));
613
+ public Collection <Term > getConstraintsForTerm (Term pTerm ) {
614
+ final Set <String > usedConstraintVariables = new LinkedHashSet <>();
615
+ final Deque <String > waitlist = new ArrayDeque <>(extractVariablesAndUFs (pTerm , false ).keySet ());
616
+ while (!waitlist .isEmpty ()) {
617
+ String current = waitlist .pop ();
618
+ if (constraintsForVariables .containsKey (current )) { // ignore variables without constraints
619
+ if (usedConstraintVariables .add (current )) {
620
+ // if we found a new variable with constraint, get transitive variables from constraint
621
+ Term constraint = constraintsForVariables .get (current );
622
+ waitlist .addAll (extractVariablesAndUFs (constraint , false ).keySet ());
623
+ }
638
624
}
639
- r1 = builder .build ();
640
625
}
641
626
642
- return Maps . filterKeys ( variableCasts , r0 :: contains ). values ( );
627
+ return transformedImmutableSetCopy ( usedConstraintVariables , constraintsForVariables :: get );
643
628
}
644
629
}
0 commit comments