optimized substitution routines to not allocate unnecessarily

git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@2684 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
msridhar1 2008-03-05 22:19:27 +00:00
parent cd23bac3bc
commit a2c6cad49e
1 changed files with 204 additions and 171 deletions

View File

@ -14,7 +14,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@ -33,8 +32,7 @@ public class Simplifier {
private final static boolean DEBUG = false;
/**
* Eliminate quantifiers, by substituting every possible constant value for a
* quantified variable
* Eliminate quantifiers, by substituting every possible constant value for a quantified variable
*/
public static ITheory eliminateQuantifiers(ITheory t, Collection<? extends IFormula> constraints) {
if (t == null) {
@ -48,8 +46,7 @@ public class Simplifier {
}
/**
* Eliminate quantifiers, by substituting every possible constant value for a
* quantified variable
* Eliminate quantifiers, by substituting every possible constant value for a quantified variable
*/
private static Collection<? extends IFormula> eliminateQuantifiers(IFormula s) {
Assertions.UNREACHABLE("implement me");
@ -72,8 +69,7 @@ public class Simplifier {
}
/**
* Eliminate quantifiers, by substituting every possible constant value for a
* quantified variable
* Eliminate quantifiers, by substituting every possible constant value for a quantified variable
*/
public static Collection<? extends IFormula> eliminateQuantifiers(Collection<? extends IFormula> s) {
if (s == null) {
@ -87,8 +83,7 @@ public class Simplifier {
}
/**
* this is uglified a little to avoid tail recursion, which leads to stack
* overflow.
* this is uglified a little to avoid tail recursion, which leads to stack overflow.
*
* This is inefficient.
*/
@ -145,11 +140,11 @@ public class Simplifier {
}
return result;
}
/**
* Simplify the set s based on simple propositional logic.
*/
public static IFormula propositionalSimplify(IFormula f, Collection<? extends IFormula> t,
ISemiDecisionProcedure dec) {
public static IFormula propositionalSimplify(IFormula f, Collection<? extends IFormula> t, ISemiDecisionProcedure dec) {
Collection<IFormula> result = propositionalSimplify(Collections.singleton(f), t, dec);
return result.iterator().next();
}
@ -317,7 +312,8 @@ public class Simplifier {
// *
// * @return a pair (p1, p2) meaning "substitute p2 for p1"
// */
// private static Pair<ITerm, ITerm> getNextEqualitySubstitution(Collection<IFormula> s, Collection<? extends IFormula> theory,
// private static Pair<ITerm, ITerm> getNextEqualitySubstitution(Collection<IFormula> s, Collection<? extends
// IFormula> theory,
// Collection<IFormula> alreadyUsed) {
// Collection<IFormula> candidates = HashSetFactory.make();
// candidates.addAll(s);
@ -391,8 +387,7 @@ public class Simplifier {
/**
* in formula f, substitute the term t2 for all free occurrences of t1
*
* @throws IllegalArgumentException
* if formula is null
* @throws IllegalArgumentException if formula is null
*/
public static IFormula substitute(IFormula formula, ITerm t1, ITerm t2) {
if (formula == null) {
@ -401,25 +396,50 @@ public class Simplifier {
switch (formula.getKind()) {
case BINARY:
AbstractBinaryFormula b = (AbstractBinaryFormula) formula;
return BinaryFormula.make(b.getConnective(), substitute(b.getF1(), t1, t2), substitute(b.getF2(), t1, t2));
// TODO separate out cases for CNFFormula and Disjunction?
IFormula F1 = b.getF1();
IFormula subF1 = substitute(F1, t1, t2);
IFormula F2 = b.getF2();
IFormula subF2 = substitute(F2, t1, t2);
if (F1 != subF1 || F2 != subF2) {
return BinaryFormula.make(b.getConnective(), subF1, subF2);
} else {
return formula;
}
case NEGATION:
NotFormula n = (NotFormula) formula;
return NotFormula.make(substitute(n.getFormula(), t1, t2));
IFormula F = n.getFormula();
IFormula subF = substitute(F, t1, t2);
return F != subF ? NotFormula.make(subF) : formula;
case QUANTIFIED:
QuantifiedFormula q = (QuantifiedFormula) formula;
if (q.getBoundVar().equals(t1)) {
return q;
} else {
return QuantifiedFormula.make(q.getQuantifier(), q.getBoundVar(), substitute(q.getFormula(), t1, t2));
IFormula body = q.getFormula();
IFormula subBody = substitute(body, t1, t2);
if (body != subBody) {
return QuantifiedFormula.make(q.getQuantifier(), q.getBoundVar(), subBody);
} else {
return formula;
}
}
case RELATION:
RelationFormula r = (RelationFormula) formula;
List<ITerm> terms = new LinkedList<ITerm>();
for (ITerm t : r.getTerms()) {
List<ITerm> rTerms = r.getTerms();
List<ITerm> terms = new ArrayList<ITerm>(rTerms.size());
boolean someChange = false;
for (ITerm t : rTerms) {
Map<Wildcard, ITerm> binding = HashMapFactory.make();
terms.add(substitute(t, t1, t2, binding));
ITerm subTerm = substituteInTerm(t, t1, t2, binding);
terms.add(subTerm);
someChange = someChange || t != subTerm;
}
if (someChange) {
return RelationFormula.make(r.getRelation(), terms);
} else {
return formula;
}
case CONSTANT:
return formula;
default:
@ -431,7 +451,7 @@ public class Simplifier {
/**
* in term t, substitute t2 for free occurrences of t1
*/
public static ITerm substitute(ITerm t, ITerm t1, ITerm t2, Map<Wildcard, ITerm> binding) {
public static ITerm substituteInTerm(ITerm t, ITerm t1, ITerm t2, Map<Wildcard, ITerm> binding) {
assert t != null;
assert t1 != null;
assert t2 != null;
@ -445,11 +465,19 @@ public class Simplifier {
return t;
case FUNCTION:
FunctionTerm f = (FunctionTerm) t;
List<ITerm> terms = new LinkedList<ITerm>();
for (ITerm p : f.getParameters()) {
terms.add(substitute(p, t1, t2, binding));
List<ITerm> parameters = f.getParameters();
List<ITerm> terms = new ArrayList<ITerm>(parameters.size());
boolean someChange = false;
for (ITerm p : parameters) {
ITerm subTerm = substituteInTerm(p, t1, t2, binding);
terms.add(subTerm);
someChange = someChange || p != subTerm;
}
if (someChange) {
return FunctionTerm.make(f.getFunction(), terms);
} else {
return t;
}
case VARIABLE:
if (t1.equals(t)) {
return t2;
@ -481,10 +509,17 @@ public class Simplifier {
case FUNCTION:
FunctionTerm ft = (FunctionTerm) t;
List<ITerm> terms = new ArrayList<ITerm>();
boolean someChange = false;
for (ITerm p : ft.getParameters()) {
terms.add(bindingOf(p, binding));
ITerm bindingOfP = bindingOf(p, binding);
terms.add(bindingOfP);
someChange = someChange || p != bindingOfP;
}
if (someChange) {
return FunctionTerm.make(ft.getFunction(), terms);
} else {
return t;
}
default:
Assertions.UNREACHABLE(t);
return null;
@ -492,9 +527,8 @@ public class Simplifier {
}
/**
* Does the term t1 match the pattern t2? Note that this deals with wildcards.
* Records bindings from Wildcards to Terms in the binding map ... modified as
* a side effect.
* Does the term t1 match the pattern t2? Note that this deals with wildcards. Records bindings from Wildcards to
* Terms in the binding map ... modified as a side effect.
*/
private static boolean termsMatch(ITerm t1, ITerm t2, Map<Wildcard, ITerm> binding) {
if (t1.equals(t2)) {
@ -552,8 +586,7 @@ public class Simplifier {
* Attempt to distribute the NOT from a NotFormula
*
* @return the original formula if the distribution is unsuccessful
* @throws IllegalArgumentException
* if f == null
* @throws IllegalArgumentException if f == null
*/
public static IFormula distributeNot(NotFormula f) throws IllegalArgumentException {
if (f == null) {