/*
* Copyright (C) 2009-2012 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 de.uni_freiburg.informatik.ultimate.logic.Rational;
import de.uni_freiburg.informatik.ultimate.logic.Sort;
import de.uni_freiburg.informatik.ultimate.logic.Term;
import de.uni_freiburg.informatik.ultimate.smtinterpol.dpll.IAnnotation;
import de.uni_freiburg.informatik.ultimate.smtinterpol.theory.cclosure.CCTerm;
import de.uni_freiburg.informatik.ultimate.smtinterpol.theory.linar.LinVar;
public class SharedTerm {
private final Clausifier mClausifier;
private final Term mTerm;
private final IAnnotation mAnnot;
// fields for theory.cclosure (Congruence Closure)
CCTerm mCCterm;
// fields for theory.linar (Linear Arithmetic)
LinVar mLinVar;
Rational mFactor, mOffset;
private Term mRealTerm = null;
public SharedTerm(Clausifier clausifier, Term term) {
mClausifier = clausifier;
mTerm = term;
if (clausifier.getEngine().isProofGenerationEnabled()) {
mAnnot = mClausifier.getAnnotation();
} else {
mAnnot = null;
}
}
public void setLinVar(Rational factor, LinVar linvar, Rational offset) {
mFactor = factor;
mLinVar = linvar;
mOffset = offset;
}
public void share() {
if (mClausifier.getLogger().isInfoEnabled()) {
mClausifier.getLogger().info("Sharing term: " + this);
}
assert (mCCterm != null && mOffset != null);
mClausifier.getLASolver().share(this);
mCCterm.share(mClausifier.getCClosure(), this);
}
public void shareWithLinAr() {
if (mOffset != null) {
return;
}
assert getSort().isNumericSort() : "Sharing non-numeric sort?";
if (mTerm instanceof SMTAffineTerm) {
mClausifier.getLASolver().generateSharedVar(
this, mClausifier.createMutableAffinTerm(
(SMTAffineTerm) mTerm),
mClausifier.getStackLevel());
} else {
final boolean isint = getSort().getName().equals("Int");
mLinVar = mClausifier.getLASolver().addVar(this, isint,
mClausifier.getStackLevel());
mFactor = Rational.ONE;
mOffset = Rational.ZERO;
}
mClausifier.addUnshareLA(this);
if (mCCterm != null) {
share();
}
}
public EqualityProxy createEquality(SharedTerm other) {
return mClausifier.createEqualityProxy(this, other);
}
public void unshareLA() {
mFactor = null;
mLinVar = null;
mOffset = null;
}
public void unshareCC() {
mCCterm = null;
}
public LinVar getLinVar() {
return mLinVar;
}
public Rational getOffset() {
return mOffset;
}
public Rational getFactor() {
return mFactor;
}
public boolean validShared() {
return mCCterm != null && mOffset != null;
}
public Sort getSort() {
return mTerm.getSort();
}
public Term getTerm() {
return mTerm;
}
/**
* Get a term that can be used outside of SMTInterpol. The result is equal
* to {@link #getTerm()} unless this function returns a
* {@link SMTAffineTerm}. In this case, the result equals the application
* of {@link SMTAffineTerm#cleanup(Term)} applied to {@link #getTerm()}.
* @return A cleaned up term.
*/
public Term getRealTerm() {
if (mRealTerm == null) {
mRealTerm = SMTAffineTerm.cleanup(mTerm);
}
return mRealTerm;
}
public IAnnotation getAnnotation() {
return mAnnot;
}
public Clausifier getClausifier() {
return mClausifier;
}
public CCTerm getCCTerm() {
return mCCterm;
}
@Override
public int hashCode() {
return mTerm.hashCode();
}
@Override
public String toString() {
return SMTAffineTerm.cleanup(mTerm).toString();
}
void setCCTerm(CCTerm ccterm) {
assert(mCCterm == null);
mCCterm = ccterm;
mClausifier.addUnshareCC(this);
if (mOffset != null) {
share();
}
}
}