You are here: Home Decision Procedures Resources Exercise 7 - LraSolverRationals.java

Exercise 7 - LraSolverRationals.java

Plain Text icon LraSolverRationals.java — Plain Text, 8 kB (8977 bytes)

File contents

//package de.uni_freiburg.informatik.ultimate.smtinterpol.smtlib2;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;
import java.math.BigDecimal;
import java.math.BigInteger;

import org.apache.log4j.Logger;
import org.apache.log4j.SimpleLayout;
import org.apache.log4j.WriterAppender;

import de.uni_freiburg.informatik.ultimate.logic.ApplicationTerm;
import de.uni_freiburg.informatik.ultimate.logic.ConstantTerm;
import de.uni_freiburg.informatik.ultimate.logic.NoopScript;
import de.uni_freiburg.informatik.ultimate.logic.SMTLIBException;
import de.uni_freiburg.informatik.ultimate.logic.Sort;
import de.uni_freiburg.informatik.ultimate.logic.Term;
import de.uni_freiburg.informatik.ultimate.smtinterpol.Config;
import de.uni_freiburg.informatik.ultimate.logic.Rational;

public class LraSolverRationals extends NoopScript {

	private Logger m_Logger;
	private SimpleLayout m_Layout;
	private WriterAppender m_Appender;
	private PrintWriter m_Err = new PrintWriter(System.err);

	ArrayList<String> basics = new ArrayList<String>();
	ArrayList<String> nonBasics = null;
	
	HashMap<String,Rational> bs = new HashMap<String,Rational>();
	
	Rational[][] tab;
	Rational[] basicValues;
	Rational[] nonBasicValues;
	
	int varNr = 0;
	HashMap<String,Integer> variableOrdering = new HashMap<String,Integer>();
	
	String helpVarId = "%%y";//may not occur as (part of a) variable name in the SMTLIB file
	
	ArrayList<Rational[]> tableau = new ArrayList<Rational[]>();
	
	public LraSolverRationals(Logger logger) {
		m_Logger = logger;
		m_Layout = new SimpleLayout();
		m_Appender = new WriterAppender(m_Layout, m_Err);
		m_Logger.addAppender(m_Appender);
		m_Logger.setLevel(Config.DEFAULT_LOG_LEVEL);
        reset();
	}

	@Override
	public void declareFun(String fun, Sort[] paramSorts, Sort resultSort)
			throws SMTLIBException {
		assert resultSort.toString().equals("Real") && paramSorts.length == 0;
		variableOrdering.put(fun, varNr++);
		super.declareFun(fun, paramSorts, resultSort);
	}

	@Override
	public LBool assertTerm(Term term) throws SMTLIBException {
		if (nonBasics == null) {
			nonBasics = new ArrayList<String>(variableOrdering.size());
			for (int i = 0; i < variableOrdering.size(); i++) {
				nonBasics.add("");
			}
			for (Entry<String,Integer> en : variableOrdering.entrySet()) {
				nonBasics.set(en.getValue(), en.getKey());
			}
		}
		
		assert term instanceof ApplicationTerm && 
			((ApplicationTerm) term).getParameters().length == 2;
		
		ApplicationTerm at = (ApplicationTerm) term;

		assert at.getFunction().getName() == "<="; 
		assert at.getParameters()[0] instanceof ApplicationTerm;

		Rational[] tableauLine = new Rational[nonBasics.size()];
		
		BoundConstr bound = readLeqTerm((ApplicationTerm) at.getParameters()[0], at.getParameters()[1]);
		String newY = helpVarId + basics.size();
		variableOrdering.put(newY, varNr++);
		basics.add(newY);
		
		for (int i = 0; i < bound.linearTerm.coefficients.size(); i++) {
			tableauLine[variableOrdering.get(bound.linearTerm.variables.get(i))] = 
					bound.linearTerm.coefficients.get(i);
		}
		
		tableau.add(tableauLine);
		bs.put(newY,bound.bound);
		
		return super.assertTerm(term);
	}

	private BoundConstr readLeqTerm(ApplicationTerm linTerm, Term constant) {
		LinearTerm aft = new LinearTerm();
		if (linTerm.getParameters().length == 0) {
			aft.addSummand(Rational.ONE, linTerm.toString());
		} else if (linTerm.getFunction().getName() == "-" && linTerm.getParameters().length == 1) {
			aft.addSummand(Rational.MONE, linTerm.getParameters()[0].toString());
		} else if (linTerm.getFunction().getName() == "+") {
			for (Term summand : linTerm.getParameters()) {
				if (summand instanceof ApplicationTerm) {
					ApplicationTerm smnd = (ApplicationTerm) summand;
					if(smnd.getFunction().getName() == "*" && smnd.getParameters().length == 2 &&
							((ApplicationTerm) smnd.getParameters()[1]).getParameters().length == 0) {
						aft.addSummand(readRationalFromTerm(smnd.getParameters()[0]), smnd.getParameters()[1].toString());
					} else if (smnd.getFunction().getName() == "-" && smnd.getParameters().length == 1 && 
							smnd.getParameters()[0] instanceof ApplicationTerm && 
							((ApplicationTerm) smnd.getParameters()[0]).getParameters().length == 0) {
						aft.addSummand(Rational.MONE, smnd.getParameters()[0].toString());
					} else if (smnd.getParameters().length == 0) {
						aft.addSummand(Rational.ONE, smnd.toString());
					} else
						assert false;
				} else
					assert false;
			}
		} else {
			assert false;
		}
		return new BoundConstr(aft, readRationalFromTerm(constant));
	}

	private Rational readRationalFromTerm(Term term) {
		Rational toReturn = Rational.ZERO;
		if (term instanceof ConstantTerm) {
			Object value = ((ConstantTerm) term).getValue();
			if (value instanceof Rational)
				toReturn = (Rational) ((ConstantTerm) term).getValue();
			else if (value instanceof BigInteger)
				toReturn = Rational.ONE.mul((BigInteger) value);
			else if (value instanceof BigDecimal) 
				toReturn = Rational.ONE.mul(((BigDecimal) value).unscaledValue())
						.div(Rational.ONE.mul(BigInteger.TEN.pow(((BigDecimal) value).scale())));
			else
				assert false;
		} else if (term instanceof ApplicationTerm) {
			ApplicationTerm aterm = (ApplicationTerm) term;
			String func = aterm.getFunction().getName();
			if (func.equals("+")) 
				for (Term t : aterm.getParameters()) 
					toReturn = toReturn.add(readRationalFromTerm(t));
			else if (func.equals("-")) 
				for (Term t : aterm.getParameters()) 
					toReturn = toReturn.sub(readRationalFromTerm(t));
			else 
				assert false;
		} else {
			assert false;
		}
		return toReturn;
	}

	@Override
	public LBool checkSat() {
		//LBool is the return type
		//use
		// LBool.SAT
		// LBool.UNSAT
		// in their obvious meaning
		
		int n = nonBasics.size();
		int m = basics.size();
		
		String[] nba = new String[n]; 
		String[] ba = new String[m];
		nonBasics.toArray(nba);
		basics.toArray(ba);
		
		tab = new Rational[m][n];
		for (int i = 0; i < m; i++)
			for (int j = 0; j < n; j++)
				tab[i][j] = tableau.get(i)[j] == null ? Rational.ZERO : tableau.get(i)[j];
		
		nonBasicValues = new Rational[n];
		for (int i = 0; i < n; i++) 
			nonBasicValues[i] = Rational.ZERO;

		basicValues = new Rational[m];
		for (int i = 0; i < m; i++) 
			basicValues[i] = Rational.ZERO;
		
		//at this point all the values from the constraints 
		//are stored in the initial tableau "tab"
		//the ArrayLists<String> "nonBasics"/"basics" contain the variable names
		//for each column/line
		//for their values there are arrays (non)BasicValues 
		//the HashMap<String,Double> "bs" contains the bound for each initially basic variable 
		//in the matrix (i.e. the pairs (y_i,b_i) in the lecture's notation)
		//all these data structures and helper methods are supposed to be for your convenience, you may change them
		//if you do not like them
		
		//Note: should you run into an assertion Error in your execution, probably the smt2-file contains
		// some syntax which can not (yet) be parsed -> either stick to the given syntax or just add
		// the case in the above code.
		
		
		//TODO: add decision procedure
		
		return LBool.UNKNOWN;
	}
	
	private boolean isInitiallyBasic(String var) {
		if(var.startsWith(helpVarId))
			return true;
		else
			return false;
	}

	public String printTableau(ArrayList<Rational[]> tableau) {
		StringBuilder toReturn = new StringBuilder();
		
		for (Rational[] line : tableau) {
			for (int i = 0; i < line.length; i++) {
				toReturn.append(line[i] + "\t");
			}
			toReturn.append("\n");
		}
		
		return toReturn.toString();
	}
	
	public String printTableau(Rational[][] tableau) {
		StringBuilder toReturn = new StringBuilder();
		
		for (int i = 0; i < tableau.length; i++) {
			Rational[] line = tableau[i];
			for (int j = 0; j < line.length; j++) {
				toReturn.append(/*trimRational(*/line[j] + "\t");
			}
			toReturn.append("\n");
		}
		
		return toReturn.toString();
	}
	
	public String printArray(Rational[] array) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < array.length; i++) {
			sb.append(array[i] + " ");
		}
		return sb.toString();
	}
	
	class LinearTerm {
		
		ArrayList<Rational> coefficients = new ArrayList<Rational>();
		ArrayList<String> variables = new ArrayList<String>();
		
		public LinearTerm() {
			
		}
		
		public void addSummand(Rational coefficient, String variable) {
			coefficients.add(coefficient);
			variables.add(variable);
		}
		
		public String toString() {
			String toReturn = "";
			for (int i = 0; i < coefficients.size(); i++) {
				toReturn += coefficients.get(i) + "*" + variables.get(i) + " ";
			}
			return toReturn;
		}
	}
	
	class BoundConstr {
		LinearTerm linearTerm;
		Rational bound;

		public BoundConstr(LinearTerm affineTerm, Rational bound) {
			super();
			this.linearTerm = affineTerm;
			this.bound = bound;
		}
	}
}