/*
* Copyright (C) 2013 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.convert;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import de.uni_freiburg.informatik.ultimate.logic.ApplicationTerm;
import de.uni_freiburg.informatik.ultimate.logic.FunctionSymbol;
import de.uni_freiburg.informatik.ultimate.logic.Rational;
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.logic.TermTransformer;
import de.uni_freiburg.informatik.ultimate.logic.Theory;
import de.uni_freiburg.informatik.ultimate.util.datastructures.ScopedHashMap;
public class ArithDelay extends InternTermTransformer {
private final ScopedHashMap<Rational, Term> mArithConsts =
new ScopedHashMap<Rational, Term>();
private Term replace(Rational constant, Theory t, Sort s) {
Term replacement = mArithConsts.get(constant);
if (replacement == null) {
final String rep = "@" + constant.toString();
FunctionSymbol fsym = t.getFunction(rep);
if (fsym == null) {
fsym = t.declareFunction(rep, Script.EMPTY_SORT_ARRAY, s);
}
replacement = t.term(fsym);
mArithConsts.put(constant, replacement);
}
return replacement;
}
@Override
public void convertApplicationTerm(
ApplicationTerm appTerm, Term[] newArgs) {
final Theory t = appTerm.getTheory();
if (appTerm.getFunction().getName().equals("<=")) {
final SMTAffineTerm arg0 = (SMTAffineTerm) newArgs[0];
if (arg0.getConstant().compareTo(Rational.ZERO) != 0) {
final Rational constant = arg0.getConstant();
final Term replacement = replace(constant, t, arg0.getSort());
final Map<Term, Rational> summands =
new HashMap<Term, Rational>(arg0.getSummands());
summands.put(replacement, Rational.ONE);
final SMTAffineTerm res = SMTAffineTerm.create(
summands, Rational.ZERO, arg0.getSort());
setResult(t.term(appTerm.getFunction(), res, newArgs[1]));
return;
}
} else if (appTerm.getFunction().getName().equals("=")) {
Term[] args = newArgs;
for (int i = 0; i < newArgs.length; ++i) {
if (args[i] instanceof SMTAffineTerm) {
final SMTAffineTerm arg = (SMTAffineTerm) args[i];
if (arg.isConstant()) {
if (newArgs == args) {
args = newArgs.clone();
}
args[i] = replace(arg.getConstant(), t, arg.getSort());
}
}
}
setResult(t.term(appTerm.getFunction(), args));
return;
}
super.convertApplicationTerm(appTerm, newArgs);
}
public Iterable<Term> getReplacedEqs() {
return new Iterable<Term>() {
@Override
public Iterator<Term> iterator() {
return new Iterator<Term>() {
private final Iterator<Map.Entry<Rational, Term>> mIt =
mArithConsts.entrySet().iterator();
@Override
public boolean hasNext() {
return mIt.hasNext();
}
@Override
public Term next() {
final Map.Entry<Rational, Term> me = mIt.next();
final Term val = me.getValue();
final Theory t = val.getTheory();
return t.term("=",
me.getKey().toTerm(val.getSort()), val);
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
};
}
public TermTransformer getReverter() {
final HashMap<Term, Term> reverted = new HashMap<Term, Term>();
for (final Map.Entry<Rational, Term> me : mArithConsts.entrySet()) {
final Term nkey = me.getValue();
reverted.put(nkey, me.getKey().toTerm(nkey.getSort()));
}
return new InternTermTransformer() {
@Override
public void convertApplicationTerm(ApplicationTerm appTerm,
Term[] newArgs) {
final Term rep = reverted.get(appTerm);
if (rep == null) {
super.convertApplicationTerm(appTerm, newArgs);
} else {
setResult(rep);
}
}
};
}
public boolean isEmpty() {
return mArithConsts.isEmpty();
}
public void push() {
mArithConsts.beginScope();
}
public void pop() {
mArithConsts.endScope();
}
}