CNF and related support

git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@1404 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
sjfink 2007-07-10 14:50:20 +00:00
parent 56cda5a9e2
commit 078deea908
5 changed files with 739 additions and 43 deletions

View File

@ -0,0 +1,30 @@
/*******************************************************************************
* Copyright (c) 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.logic;
import com.ibm.wala.logic.ILogicConstants.BinaryConnective;
public abstract class AbstractBinaryFormula implements IFormula {
protected AbstractBinaryFormula() {
super();
}
public final Kind getKind() {
return Kind.BINARY;
}
public abstract BinaryConnective getConnective();
public abstract IFormula getF1();
public abstract IFormula getF2();
}

View File

@ -16,7 +16,7 @@ import java.util.Iterator;
import com.ibm.wala.logic.ILogicConstants.BinaryConnective;
import com.ibm.wala.util.collections.HashSetFactory;
public class BinaryFormula implements IFormula {
public class BinaryFormula extends AbstractBinaryFormula {
private final IFormula f1;
private final IFormula f2;
@ -30,10 +30,6 @@ public class BinaryFormula implements IFormula {
this.f2 = f2;
}
public Kind getKind() {
return Kind.BINARY;
}
public static IFormula and(Collection<IFormula> clauses) throws IllegalArgumentException {
if (clauses == null) {
throw new IllegalArgumentException("clauses is null");
@ -85,14 +81,17 @@ public class BinaryFormula implements IFormula {
return new BinaryFormula(BinaryConnective.IMPLIES, f1, f2);
}
@Override
public BinaryConnective getConnective() {
return b;
}
@Override
public IFormula getF1() {
return f1;
}
@Override
public IFormula getF2() {
return f2;
}
@ -113,13 +112,13 @@ public class BinaryFormula implements IFormula {
public String prettyPrint(ILogicDecorator d) {
StringBuffer result = new StringBuffer();
result.append("(");
result.append(" ( ");
result.append(f1.prettyPrint(d));
result.append(") ");
result.append(" ) ");
result.append(d.prettyPrint(b));
result.append(" (");
result.append(" ( ");
result.append(f2.prettyPrint(d));
result.append(")");
result.append(" )");
return result.toString();
}

View File

@ -0,0 +1,367 @@
/*******************************************************************************
* Copyright (c) 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.logic;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import com.ibm.wala.logic.ILogicConstants.BinaryConnective;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.debug.Assertions;
/**
* A formula in conjunctive normal form.
*
* @author sjfink
*/
public class CNFFormula extends AbstractBinaryFormula {
private static final boolean DEBUG = true;
// invariant: size >= 1
private final Collection<Disjunction> disjunctions;
private CNFFormula(Collection<Disjunction> clauses) {
assert !clauses.isEmpty();
this.disjunctions = clauses;
}
public Collection<? extends IConstant> getConstants() {
Collection<IConstant> result = HashSetFactory.make();
for (IFormula f : disjunctions) {
result.addAll(f.getConstants());
}
return result;
}
public Collection<Variable> getFreeVariables() {
Collection<Variable> result = HashSetFactory.make();
for (IFormula f : disjunctions) {
result.addAll(f.getFreeVariables());
}
return result;
}
public boolean isAtomic() {
return false;
}
public String prettyPrint(ILogicDecorator d) {
if (disjunctions.size() == 1) {
return getF1().prettyPrint(d);
} else {
StringBuffer result = new StringBuffer();
result.append(" ( ");
result.append(getF1().prettyPrint(d));
result.append(" ) ");
result.append(d.prettyPrint(getConnective()));
result.append(" ( ");
result.append(getF2().prettyPrint(d));
result.append(" )");
return result.toString();
}
}
public static CNFFormula make(IFormula f) {
if (DEBUG) {
System.err.println("make CNF " + f);
}
if (f instanceof CNFFormula) {
return (CNFFormula) f;
} else {
switch (f.getKind()) {
case RELATION:
case QUANTIFIED:
case CONSTANT:
Disjunction single = Disjunction.make(Collections.singleton(f));
Collection<Disjunction> clauses = Collections.singleton(single);
return new CNFFormula(clauses);
case BINARY:
f = eliminateArrows(f);
if (DEBUG) {
System.err.println("after eliminate arrows " + f);
}
f = pushNegations(f);
if (DEBUG) {
System.err.println("after pushNegations " + f);
}
f = distribute(f);
if (DEBUG) {
System.err.println("after distribute " + f);
}
if (f instanceof AbstractBinaryFormula) {
AbstractBinaryFormula b = (AbstractBinaryFormula) f;
assert (b.getConnective().equals(BinaryConnective.AND));
return new CNFFormula(collectClauses(b));
} else {
return CNFFormula.make(f);
}
case NEGATION:
default:
Assertions.UNREACHABLE(f + " " + f.getKind());
return null;
}
}
}
private static Collection<Disjunction> collectClauses(AbstractBinaryFormula b) {
assert (b.getConnective().equals(BinaryConnective.AND));
Collection<Disjunction> result = HashSetFactory.make();
IFormula f1 = b.getF1();
if (f1 instanceof AbstractBinaryFormula) {
AbstractBinaryFormula b1 = (AbstractBinaryFormula) f1;
if (b1.getConnective().equals(BinaryConnective.AND)) {
result.addAll(collectClauses(b1));
} else {
result.add(toDisjunction(b1));
}
} else {
result.add(toDisjunction(f1));
}
IFormula f2 = b.getF2();
if (f2 instanceof AbstractBinaryFormula) {
AbstractBinaryFormula b2 = (AbstractBinaryFormula) f2;
if (b2.getConnective().equals(BinaryConnective.AND)) {
result.addAll(collectClauses(b2));
} else {
result.add(toDisjunction(b2));
}
} else {
result.add(toDisjunction(f2));
}
return result;
}
private static Disjunction toDisjunction(IFormula f) {
switch (f.getKind()) {
case BINARY:
AbstractBinaryFormula b = (AbstractBinaryFormula) f;
if (b.getConnective().equals(BinaryConnective.OR)) {
IFormula f1 = b.getF1();
Disjunction d2 = toDisjunction(b.getF2());
Collection<IFormula> c = HashSetFactory.make();
c.add(f1);
c.addAll(d2.getClauses());
return Disjunction.make(c);
} else {
Assertions.UNREACHABLE(b);
return null;
}
case CONSTANT:
case QUANTIFIED:
case RELATION:
return Disjunction.make(Collections.singleton(f));
case NEGATION:
default:
Assertions.UNREACHABLE(f.getKind());
return null;
}
}
/**
* move all conjunctions outside disjunctions using distributive laws.
*
* (a AND b) OR c -> (a OR c) AND (b OR c)
*
* a OR (b AND c) -> (a OR b) AND (a OR c)
*/
private static IFormula distribute(IFormula f) {
switch (f.getKind()) {
case BINARY:
return distribute((AbstractBinaryFormula) f);
case CONSTANT:
case QUANTIFIED:
case RELATION:
return f;
case NEGATION:
default:
Assertions.UNREACHABLE(f.getKind());
return null;
}
}
/**
* move all conjunctions outside disjunctions using distributive laws.
*
* (a AND b) OR c -> (a OR c) AND (b OR c)
*
* a OR (b AND c) -> (a OR b) AND (a OR c)
*/
private static IFormula distribute(AbstractBinaryFormula b) {
IFormula f1 = b.getF1();
IFormula f2 = b.getF2();
f1 = distribute(f1);
f2 = distribute(f2);
switch (b.getConnective()) {
case OR:
if (f1 instanceof AbstractBinaryFormula && ((AbstractBinaryFormula) f1).getConnective().equals(BinaryConnective.AND)) {
AbstractBinaryFormula c1 = (AbstractBinaryFormula) f1;
IFormula af = c1.getF1();
IFormula bf = c1.getF2();
IFormula x = BinaryFormula.and(BinaryFormula.or(af, f2), BinaryFormula.or(bf, f2));
// distribute again; case 2 may apply
return distribute(x);
}
if (f2 instanceof AbstractBinaryFormula && ((AbstractBinaryFormula) f2).getConnective().equals(BinaryConnective.AND)) {
AbstractBinaryFormula c2 = (AbstractBinaryFormula) f2;
IFormula bf = c2.getF1();
IFormula cf = c2.getF2();
IFormula x = BinaryFormula.and(BinaryFormula.or(f1, bf), BinaryFormula.or(f1, cf));
return x;
}
return BinaryFormula.make(b.getConnective(), f1, f2);
case AND:
return BinaryFormula.make(b.getConnective(), f1, f2);
case BICONDITIONAL:
case IMPLIES:
default:
Assertions.UNREACHABLE(b.getConnective());
return null;
}
}
/**
* push NOT operators into the formula using double complement and De Morgan's
* laws.
*/
private static IFormula pushNegations(IFormula f) {
switch (f.getKind()) {
case BINARY:
AbstractBinaryFormula b = (AbstractBinaryFormula) f;
IFormula f1 = b.getF1();
IFormula f2 = b.getF2();
f1 = pushNegations(f1);
f2 = pushNegations(f2);
return BinaryFormula.make(b.getConnective(), f1, f2);
case CONSTANT:
case RELATION:
case QUANTIFIED:
return f;
case NEGATION:
default:
Assertions.UNREACHABLE(f.getKind());
return null;
}
}
/**
* eliminate all IMPLIES and BICONDITIONALS
*/
private static IFormula eliminateArrows(IFormula f) {
switch (f.getKind()) {
case BINARY:
AbstractBinaryFormula b = (AbstractBinaryFormula) f;
return eliminateArrows(b);
case CONSTANT:
case RELATION:
case QUANTIFIED:
return f;
case NEGATION:
default:
Assertions.UNREACHABLE(f.getKind());
return null;
}
}
/**
* eliminate all IMPLIES and BICONDITIONALS
*/
private static IFormula eliminateArrows(AbstractBinaryFormula b) {
IFormula f1 = b.getF1();
IFormula f2 = b.getF2();
f1 = eliminateArrows(f1);
f2 = eliminateArrows(f2);
Collection<Disjunction> emptyTheory = Collections.emptySet();
switch (b.getConnective()) {
case BICONDITIONAL:
if (Simplifier.isTautology(f1, emptyTheory)) {
return f2;
} else if (Simplifier.isContradiction(f1, emptyTheory)) {
return BooleanConstantFormula.FALSE;
} else {
IFormula not1 = NotFormula.make(f1);
IFormula not2 = NotFormula.make(f2);
return BinaryFormula.or(BinaryFormula.and(f1, f2), BinaryFormula.and(not1, not2));
}
case AND:
case OR:
return BinaryFormula.make(b.getConnective(), f1, f2);
case IMPLIES:
default:
Assertions.UNREACHABLE(b);
return null;
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((disjunctions == null) ? 0 : disjunctions.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final CNFFormula other = (CNFFormula) obj;
if (disjunctions == null) {
if (other.disjunctions != null)
return false;
} else if (!disjunctions.equals(other.disjunctions))
return false;
return true;
}
@Override
public BinaryConnective getConnective() {
return BinaryConnective.AND;
}
@Override
public IFormula getF1() {
return disjunctions.iterator().next();
}
@Override
public IFormula getF2() {
// if clauses.size() == 1, we fake this by saying we are getF1() AND true
if (disjunctions.size() == 1) {
return BooleanConstantFormula.TRUE;
} else {
Collection<Disjunction> c = new HashSet<Disjunction>(disjunctions);
c.remove(getF1());
return new CNFFormula(c);
}
}
@Override
public String toString() {
return prettyPrint(DefaultDecorator.instance());
}
public Collection<? extends Disjunction> getDisjunctions() {
return Collections.unmodifiableCollection(disjunctions);
}
public static CNFFormula make(Collection<Disjunction> d) {
return new CNFFormula(d);
}
}

View File

@ -0,0 +1,139 @@
/*******************************************************************************
* Copyright (c) 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.logic;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import com.ibm.wala.logic.ILogicConstants.BinaryConnective;
import com.ibm.wala.util.collections.HashSetFactory;
/**
* A disjunction of formulae
*
* @author sjfink
*/
public class Disjunction extends AbstractBinaryFormula {
// invariant: size >= 1
private final Collection<? extends IFormula> clauses;
private Disjunction(Collection<? extends IFormula> clauses) {
this.clauses = clauses;
}
public Collection<? extends IConstant> getConstants() {
Collection<IConstant> result = HashSetFactory.make();
for (IFormula f : clauses) {
result.addAll(f.getConstants());
}
return result;
}
public Collection<Variable> getFreeVariables() {
Collection<Variable> result = HashSetFactory.make();
for (IFormula f : clauses) {
result.addAll(f.getFreeVariables());
}
return result;
}
public boolean isAtomic() {
return false;
}
public String prettyPrint(ILogicDecorator d) {
if (clauses.size() == 1) {
return getF1().prettyPrint(d);
} else {
StringBuffer result = new StringBuffer();
result.append(" ( ");
result.append(getF1().prettyPrint(d));
result.append(" ) ");
result.append(d.prettyPrint(getConnective()));
result.append(" ( ");
result.append(getF2().prettyPrint(d));
result.append(" )");
return result.toString();
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((clauses == null) ? 0 : clauses.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final Disjunction other = (Disjunction) obj;
if (clauses == null) {
if (other.clauses != null)
return false;
} else if (!clauses.equals(other.clauses))
return false;
return true;
}
@Override
public BinaryConnective getConnective() {
return BinaryConnective.OR;
}
@Override
public IFormula getF1() {
return clauses.iterator().next();
}
@Override
public IFormula getF2() {
// if clauses.size() == 1, we fake this by saying we are getF1() OR false
if (clauses.size() == 1) {
return BooleanConstantFormula.FALSE;
} else {
Collection<IFormula> c = new HashSet<IFormula>(clauses);
c.remove(getF1());
return make(c);
}
}
public static Disjunction make(Collection<? extends IFormula> clauses) {
for (IFormula c: clauses) {
assert !(c instanceof Disjunction);
}
return new Disjunction(clauses);
}
public Collection<? extends IFormula> getClauses() {
return Collections.unmodifiableCollection(clauses);
}
public static Disjunction make(BooleanConstantFormula f) {
Collection<? extends IFormula> c = Collections.singleton(f);
return new Disjunction(c);
}
@Override
public String toString() {
return prettyPrint(DefaultDecorator.instance());
}
}

View File

@ -29,6 +29,12 @@ import com.ibm.wala.util.intset.IntPair;
*/
public class Simplifier {
private final static boolean DEBUG = true;
/**
* Eliminate quantifiers, by substituting every possible constant value for a
* quantified variable
*/
public static ITheory eliminateQuantifiers(ITheory t) {
if (t == null) {
throw new IllegalArgumentException("t is null");
@ -40,6 +46,10 @@ public class Simplifier {
return BasicTheory.make(t.getVocabulary(), sentences);
}
/**
* Eliminate quantifiers, by substituting every possible constant value for a
* quantified variable
*/
private static Collection<? extends IFormula> eliminateQuantifiers(IFormula s) {
if (s.getKind().equals(IFormula.Kind.QUANTIFIED)) {
Collection<IFormula> result = HashSetFactory.make();
@ -79,7 +89,7 @@ public class Simplifier {
while (changed) {
changed = false;
Collection<IFormula> alreadyUsed = HashSetFactory.make();
Pair<ITerm, ITerm> substitution = getNextSubCandidate(s, t, alreadyUsed);
Pair<ITerm, ITerm> substitution = getNextEqualitySubstitution(s, t, alreadyUsed);
while (substitution != null) {
Collection<IFormula> temp = HashSetFactory.make();
for (IFormula f : s) {
@ -94,35 +104,129 @@ public class Simplifier {
}
}
s = temp;
substitution = getNextSubCandidate(s, t, alreadyUsed);
substitution = getNextEqualitySubstitution(s, t, alreadyUsed);
}
}
return trivialDecision(s);
return propositionalSimplify(s, t.getSentences());
}
/**
* Check simple satisfiability rules for each formula in a collection. Replace
* tautologies with "true" and contradictions with false.
* Simplify the set s based on simple propositional logic.
*/
private static Collection<IFormula> trivialDecision(Collection<IFormula> s) {
public static Collection<IFormula> propositionalSimplify(Collection<IFormula> s, Collection<? extends IFormula> t) {
debug1(s, t);
Collection<CNFFormula> cs = toCNF(s);
Collection<CNFFormula> ct = toCNF(t);
debug2(cs, ct);
Collection<Disjunction> facts = collectClauses(ct);
Collection<IFormula> result = HashSetFactory.make();
for (IFormula f : s) {
if (isTautology(f)) {
result.add(BooleanConstantFormula.TRUE);
} else if (isContradiction(f)) {
result.add(BooleanConstantFormula.FALSE);
for (CNFFormula f : cs) {
Collection<Disjunction> d = simplifyCNF(f.getDisjunctions(), facts);
if (d.size() == 1) {
Disjunction x = d.iterator().next();
Collection<? extends IFormula> y = x.getClauses();
if (y.size() == 1) {
result.add(y.iterator().next());
} else {
result.add(CNFFormula.make(d));
}
} else {
result.add(f);
result.add(CNFFormula.make(d));
}
}
return result;
}
private static Collection<Disjunction> simplifyCNF(Collection<? extends Disjunction> s, Collection<Disjunction> facts) {
Collection<Disjunction> result = HashSetFactory.make();
for (Disjunction d : s) {
if (isContradiction(d, facts)) {
return Collections.singleton(Disjunction.make(BooleanConstantFormula.FALSE));
} else if (isTautology(d, facts)) {
// do nothing.
} else {
result.add(d);
}
}
if (result.isEmpty()) {
return Collections.singleton(Disjunction.make(BooleanConstantFormula.TRUE));
}
return result;
}
private static Collection<Disjunction> collectClauses(Collection<CNFFormula> s) {
Collection<Disjunction> result = HashSetFactory.make();
for (CNFFormula f : s) {
result.addAll(f.getDisjunctions());
}
return result;
}
private static void debug2(Collection<CNFFormula> cs, Collection<CNFFormula> ct) {
if (DEBUG) {
System.err.println("--cs--");
for (IFormula f : cs) {
System.err.println(f);
}
System.err.println("--ct--");
for (IFormula f : ct) {
System.err.println(f);
}
}
}
private static void debug1(Collection<IFormula> s, Collection<? extends IFormula> t) {
if (DEBUG) {
System.err.println("--s--");
for (IFormula f : s) {
System.err.println(f);
}
System.err.println("--t--");
for (IFormula f : t) {
System.err.println(f);
}
}
}
private static Collection<CNFFormula> toCNF(Collection<? extends IFormula> s) {
Collection<CNFFormula> result = HashSetFactory.make();
for (IFormula f : s) {
result.add(CNFFormula.make(f));
}
return result;
}
/**
* @param facts
* formulae that can be treated as axioms
* @return true if we can easily prove f is a contradiction
*/
private static boolean isContradiction(IFormula f) {
if (f.getKind().equals(IFormula.Kind.RELATION)) {
public static boolean isContradiction(IFormula f, Collection<Disjunction> facts) {
for (Disjunction d : facts) {
if (contradicts(d, f)) {
return true;
}
}
switch (f.getKind()) {
case BINARY:
AbstractBinaryFormula b = (AbstractBinaryFormula) f;
if (b.getConnective().equals(BinaryConnective.AND)) {
if (isContradiction(b.getF1(), facts) || isContradiction(b.getF2(), facts)) {
return true;
}
} else if (b.getConnective().equals(BinaryConnective.OR)) {
if (isContradiction(b.getF1(), facts) && isContradiction(b.getF2(), facts)) {
return true;
}
}
break;
case CONSTANT:
BooleanConstantFormula bc = (BooleanConstantFormula) f;
return bc.equals(BooleanConstantFormula.FALSE);
case NEGATION:
case QUANTIFIED:
case RELATION:
RelationFormula r = (RelationFormula) f;
if (r.getRelation().equals(BinaryRelation.EQUALS)) {
ITerm lhs = r.getTerms().get(0);
@ -133,22 +237,76 @@ public class Simplifier {
}
}
}
} else if (f.getKind().equals(IFormula.Kind.BINARY)) {
BinaryFormula b = (BinaryFormula) f;
if (b.getConnective().equals(BinaryConnective.AND)) {
if (isContradiction(b.getF1()) || isContradiction(b.getF2())) {
return true;
}
break;
}
return false;
}
private static boolean contradicts(Disjunction axiom, IFormula f) {
IFormula notF = NotFormula.make(f);
return implies(axiom, notF);
}
private static boolean implies(Disjunction axiom, IFormula f) {
Collection<? extends IFormula> c = axiom.getClauses();
if (c.size() == 1) {
IFormula a = c.iterator().next();
if (a.equals(f)) {
return true;
}
}
if (f instanceof Disjunction) {
Disjunction d = (Disjunction) f;
Collection<? extends IFormula> dc = d.getClauses();
if (sameValue(c, dc)) {
return true;
}
}
return false;
}
private static boolean sameValue(Collection<?> a, Collection<?> b) {
if (a.size() != b.size()) {
return false;
}
for (Object x : a) {
if (!b.contains(x)) {
return false;
}
}
return true;
}
/**
* @param facts
* formulae that can be treated as axioms
* @return true if we can easily prove f is a tautology
*/
private static boolean isTautology(IFormula f) {
if (f.getKind().equals(IFormula.Kind.RELATION)) {
public static boolean isTautology(IFormula f, Collection<Disjunction> facts) {
for (Disjunction d : facts) {
if (implies(d, f)) {
return true;
}
}
switch (f.getKind()) {
case BINARY:
AbstractBinaryFormula b = (AbstractBinaryFormula) f;
if (b.getConnective().equals(BinaryConnective.AND)) {
if (isTautology(b.getF1(), facts) && isTautology(b.getF2(), facts)) {
return true;
}
}
break;
case CONSTANT:
Assertions.UNREACHABLE();
break;
case NEGATION:
Assertions.UNREACHABLE();
break;
case QUANTIFIED:
Assertions.UNREACHABLE();
break;
case RELATION:
RelationFormula r = (RelationFormula) f;
if (r.getRelation().equals(BinaryRelation.EQUALS)) {
ITerm lhs = r.getTerms().get(0);
@ -159,17 +317,14 @@ public class Simplifier {
}
}
}
} else if (f.getKind().equals(IFormula.Kind.BINARY)) {
BinaryFormula b = (BinaryFormula) f;
if (b.getConnective().equals(BinaryConnective.AND)) {
if (isTautology(b.getF1()) && isTautology(b.getF2())) {
return true;
}
}
break;
}
return false;
}
/**
* Is f of the form t = rhs?
*/
private static boolean defines(IFormula f, ITerm t) {
if (f.getKind().equals(IFormula.Kind.RELATION)) {
RelationFormula r = (RelationFormula) f;
@ -180,13 +335,19 @@ public class Simplifier {
return false;
}
private static Pair<ITerm, ITerm> getNextSubCandidate(Collection<IFormula> s, ITheory t, Collection<IFormula> alreadyUsed) {
/**
* does the structure of some formula f suggest an immediate substitution to
* simplify the system, based on theory of equality?
*
* @return a pair (p1, p2) meaning "substitute p2 for p1"
*/
private static Pair<ITerm, ITerm> getNextEqualitySubstitution(Collection<IFormula> s, ITheory t, Collection<IFormula> alreadyUsed) {
Collection<IFormula> candidates = HashSetFactory.make();
candidates.addAll(s);
candidates.addAll(t.getSentences());
for (IFormula f : candidates) {
if (!alreadyUsed.contains(f)) {
Pair<ITerm, ITerm> substitution = suggestsSubstitution(f);
Pair<ITerm, ITerm> substitution = equalitySuggestsSubsitution(f);
if (substitution != null) {
alreadyUsed.add(f);
return substitution;
@ -198,11 +359,11 @@ public class Simplifier {
/**
* does the structure of formula f suggest an immediate substitution to
* simplify the system?
* simplify the system, based on theory of equality?
*
* @return a pair (p1, p2) meaning "substitute p2 for p1"
*/
private static Pair<ITerm, ITerm> suggestsSubstitution(IFormula f) {
private static Pair<ITerm, ITerm> equalitySuggestsSubsitution(IFormula f) {
switch (f.getKind()) {
case RELATION:
RelationFormula r = (RelationFormula) f;
@ -239,7 +400,7 @@ public class Simplifier {
}
switch (formula.getKind()) {
case BINARY:
BinaryFormula b = (BinaryFormula) formula;
AbstractBinaryFormula b = (AbstractBinaryFormula) formula;
return BinaryFormula.make(b.getConnective(), substitute(b.getF1(), t1, t2), substitute(b.getF2(), t1, t2));
case NEGATION:
NotFormula n = (NotFormula) formula;