/*
* Copyright (C) 2014 University of Freiburg
*
* This file is part of SMTInterpol.
*
* SMTInterpol is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SMTInterpol is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with SMTInterpol. If not, see <http://www.gnu.org/licenses/>.
*/
package de.uni_freiburg.informatik.ultimate.smtinterpol.delta;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
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.FunctionSymbol;
import de.uni_freiburg.informatik.ultimate.logic.LetTerm;
import de.uni_freiburg.informatik.ultimate.logic.NonRecursive;
import de.uni_freiburg.informatik.ultimate.logic.QuantifiedFormula;
import de.uni_freiburg.informatik.ultimate.logic.Rational;
import de.uni_freiburg.informatik.ultimate.logic.Term;
import de.uni_freiburg.informatik.ultimate.logic.TermVariable;
import de.uni_freiburg.informatik.ultimate.logic.Theory;
public class NeutralDetector extends NonRecursive {
private static class NeutralWalker extends TermWalker {
public NeutralWalker(Term term) {
super(term);
}
@Override
public void walk(NonRecursive walker, ConstantTerm term) {
// Nothing to do
}
@Override
public void walk(NonRecursive walker, AnnotatedTerm term) {
walker.enqueueWalker(new NeutralWalker(term.getSubterm()));
}
@Override
public void walk(NonRecursive walker, ApplicationTerm term) {
final NeutralDetector detector = (NeutralDetector) walker;
final FunctionSymbol fsym = term.getFunction();
final Theory t = fsym.getTheory();
final Term[] params = term.getParameters();
if (fsym == t.mAnd || fsym == t.mOr) {
final Term neutral = fsym == t.mAnd ? t.mTrue : t.mFalse;
for (int i = 0; i < params.length; ++i) {
if (params[i] == neutral) {
detector.mNeutrals.add(new Neutral(term, i));
} else {
detector.enqueueWalker(new NeutralWalker(params[i]));
}
}
} else if (fsym.getName().equals("+") || fsym.getName().equals("-")) {
final int start = fsym.getName().equals("+") ? 0 : 1;
for (int i = start; i < params.length; ++i) {
if (isZero(params[i])) {
detector.mNeutrals.add(new Neutral(term, i));
} else {
detector.enqueueWalker(new NeutralWalker(params[i]));
}
}
} else {
for (final Term p : params) {
detector.enqueueWalker(new NeutralWalker(p));
}
}
}
@Override
public void walk(NonRecursive walker, LetTerm term) {
for (final Term t : term.getValues()) {
walker.enqueueWalker(new NeutralWalker(t));
}
walker.enqueueWalker(new NeutralWalker(term.getSubTerm()));
}
@Override
public void walk(NonRecursive walker, QuantifiedFormula term) {
walker.enqueueWalker(new NeutralWalker(term.getSubformula()));
}
@Override
public void walk(NonRecursive walker, TermVariable term) {
// Nothing to do
}
}
private final ArrayList<Neutral> mNeutrals = new ArrayList<Neutral>();
private static boolean isZero(Term t) {
if (t instanceof ConstantTerm) {
final ConstantTerm ct = (ConstantTerm) t;
final Object val = ct.getValue();
if (val instanceof BigInteger) {
return BigInteger.ZERO.equals(val);
}
if (val instanceof BigDecimal) {
// Bugfix: Don't use equals since it requires equal scale!
return BigDecimal.ZERO.compareTo((BigDecimal) val) == 0;
}
if (val instanceof Rational) {
return Rational.ZERO.equals(val);
}
}
return false;
}
public List<Neutral> detect(Term t) {
run(new NeutralWalker(t));
return mNeutrals;
}
}