All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javax.constraints.impl.Problem Maven / Gradle / Ivy

Go to download

This is a JSR331 interface for SSC (Software for the Calculation of the Simplex) is a java library for solving linear programming problems v. 3.0.1. SSC was designed and developed by Stefano Scarioli.

The newest version!
package javax.constraints.impl;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Vector;

import javax.constraints.ConstrainedVariable;
import javax.constraints.Constraint;
import javax.constraints.Solver;
import javax.constraints.Var;
import javax.constraints.VarBool;
import javax.constraints.VarReal;
import javax.constraints.linear.LinearSolver;
import javax.constraints.linear.LinearSolverFactory;
import javax.constraints.linear.NonLinearProblemException;

import org.slf4j.LoggerFactory;

public class Problem extends AbstractProblem {
    
    ArrayList integerConstraints; 
    ArrayList realConstraints;
	
	static public final String JSR331_LINEAR_VERSION = "JSR-331 Implementation with SSC Linear Solver";
	
	int numberOfScalProducts;

	public Problem() {
		this("LinearProblem");
	}
	
	public Problem(String name) {
		super(name);
		numberOfScalProducts = 0;
		integerConstraints = new ArrayList();
		realConstraints = new ArrayList();
	}
	
	@Override
	public Constraint postElement(int[] array, Var indexVar, String oper, int value) {
		throw new NonLinearProblemException("postElement(int[] coefficients, Var indexVar, String oper, int value)");
	}

	@Override
	public Constraint postElement(int[] array, Var indexVar, String oper, Var var) {
		throw new NonLinearProblemException("postElement(int[] coefficients, Var indexVar, String oper, Var var)");
	}

	@Override
	public Constraint postElement(Var[] vars, Var indexVar, String oper, int value) {
		throw new NonLinearProblemException("postElement(Var[] vars, Var indexVar, String oper, int value) ");
	}

	@Override
	public Constraint postElement(Var[] vars, Var indexVar, String oper, Var var) {
		throw new NonLinearProblemException("postElement(Var[] vars, Var indexVar, String oper, Var var)");
	}

	@Override
	public Constraint post(int[] coefficients, Var[] vars, String oper, int value) {
		if (coefficients.length != vars.length)
			throw new RuntimeException("Arrays of coefficients and vars should have the same length");
		
		integerConstraints.add(new LinearIntConstraint(coefficients,vars,oper,value));
		return null;
//		javax.constraints.impl.Constraint constraint = new javax.constraints.impl.Constraint(this);
//		constraint.setCoefficients(coefficients);
//		constraint.setVars(vars);
//		constraint.setOper(oper);
//		constraint.setValue(value);
//		add(constraint);
//		return constraint;
	}

	@Override
	public Constraint post(int[] coefficients, Var[] vars, String oper, Var var) {
		if (coefficients.length != vars.length)
			throw new RuntimeException("Arrays of coefficients and vars should have the same length");
		integerConstraints.add(new LinearIntConstraint(coefficients,vars,oper,var));
        return null;
//		Var[] vars1 = new Var[vars.length+1];
//		int[] coefs = new int[vars.length+1];
//		for (int i = 0; i < vars.length; i++) {
//			vars1[i] = vars[i];
//			coefs[i] = coefficients[i];
//		}
//		vars1[vars.length] = var;
//		coefs[vars.length]= -1; 
//		int value = 0;
//		return post(coefs,vars1,oper,value);
	}
	
	@Override
	public Constraint post(Var[] vars, String oper, int value) {
		int[] coefs = new int[vars.length];
		for (int i = 0; i < vars.length; i++) {
			coefs[i] = 1;
		}
		return post(coefs,vars,oper,value); 
	}

	@Override
	public Constraint post(Var[] vars, String oper, Var var) {
		Var[] vars1 = new Var[vars.length+1];
		int[] coefs = new int[vars.length+1];
		for (int i = 0; i < vars.length; i++) {
			vars1[i] = vars[i];
			coefs[i] = 1;
		}
		vars1[vars.length] = var;
		coefs[vars.length]= -1; 
		int value = 0;
		return post(coefs,vars1,oper,value);
	}

	@Override
	public Constraint post(Var var, String oper, int value) {
		Var[] vars = { var };
		return post(vars,oper,value);
	}

	@Override
	public Constraint post(Var var1, String oper, Var var2) {
		Var[] vars = { var1, var2 };
		int[] coefficients = { 1, -1 };
		int value = 0;
		return post(coefficients, vars, oper, value);
	}

	@Override
	public Constraint linear(Var var, String oper, int value) {
		//throw new NonLinearProblemException("linear(Var var, String oper, int value)");
		javax.constraints.impl.Constraint constraint = new javax.constraints.impl.Constraint(this);
		constraint.setCoefficients(new int[]{1});
		constraint.setVars(new Var[]{var});
		constraint.setOper(oper);
		constraint.setValue(value);
		return constraint;
	}

	@Override
	public Constraint linear(Var var1, String oper, Var var2) {
		//throw new NonLinearProblemException("linear(Var var1, String oper, Var var2)");
		javax.constraints.impl.Constraint constraint = new javax.constraints.impl.Constraint(this);
		constraint.setCoefficients(new int[]{1,-1});
		constraint.setVars(new Var[]{var1,var2});
		constraint.setOper(oper);
		constraint.setValue(0);
		return constraint;
	}
	
	/**
	 * Creates and posts a constraint: array*vars 'oper' value
	 * for an "array: of real coefficients to be multiplied by an array "vars"
	 * of integer constrained variables 
	 * @throws RuntimeException if the posting fails
	 * @return a newly created constraint
	 */
	public Constraint post(double[] coefficients, Var[] vars, String oper, double value) {
		return post(coefficients, (ConstrainedVariable[])vars, oper, value);
	}
	
	@Override
	public Constraint post(double[] coefficients, VarReal[] vars, String oper, double value) {
	    
	    realConstraints.add(new LinearRealConstraint(coefficients,vars,oper,value));
        return null;
		//return post(coefficients, (ConstrainedVariable[])vars, oper, value);
	}
	
	@Override
	public Constraint post(double[] coefficients, ConstrainedVariable[] vars, String oper, double value) {
		if (coefficients.length != vars.length)
			throw new RuntimeException("Arrays of coefficients and vars should have the same length");
		VarReal[] realVars = new VarReal[vars.length];
		for (int i = 0; i < realVars.length; i++) {
            realVars[i] = (VarReal) vars[i];
        }
		return post(coefficients,realVars,oper,value);
//		javax.constraints.impl.Constraint constraint = new javax.constraints.impl.Constraint(this);
//		constraint.setCoefficients(coefficients); 
//		constraint.setVars(vars);
//		constraint.setOper(oper);
//		constraint.setValue(value);
//		add(constraint);
//		return constraint;
	}

	@Override
	public Constraint post(double[] coefficients, VarReal[] vars, String oper, VarReal var) {
		if (coefficients.length != vars.length)
			throw new RuntimeException("Arrays of coefficients and vars should have the same length");
		realConstraints.add(new LinearRealConstraint(coefficients, vars, oper, var));
		return null;
//		VarReal[] vars1 = new VarReal[vars.length+1];
//		double[] coefs = new double[vars.length+1];
//		for (int i = 0; i < vars.length; i++) {
//			vars1[i] = vars[i];
//			coefs[i] = coefficients[i];
//		}
//		vars1[vars.length] = var;
//		coefs[vars.length]= -1; 
//		int value = 0;
//		return post(coefs,vars1,oper,value);
	}

	public Constraint post(double[] coefficients, ConstrainedVariable[] vars, String oper, ConstrainedVariable var) {
		if (coefficients.length != vars.length)
			throw new RuntimeException("Arrays of coefficients and vars should have the same length");
		VarReal[] realVars = new VarReal[vars.length];
        for (int i = 0; i < realVars.length; i++) {
            realVars[i] = (VarReal) vars[i];
        }
        return post(coefficients,realVars,oper,(VarReal)var);
	}
	
	@Override
	public Constraint post(VarReal[] vars, String oper, double value) {
		double[] coefs = new double[vars.length];
		for (int i = 0; i < vars.length; i++) {
			coefs[i] = 1;
		}
		return post(coefs,vars,oper,value); 
	}	
	
//	@Override
    public Constraint post(VarReal[] vars, String oper, int value) {
        return post(vars,oper,(double)value); 
    }   
	

//	@Override
	public Constraint post(VarReal[] vars, String oper, VarReal var) {
		VarReal[] vars1 = new VarReal[vars.length+1];
		double[] coefs = new double[vars.length+1];
		for (int i = 0; i < vars.length; i++) {
			vars1[i] = vars[i];
			coefs[i] = 1;
		}
		vars1[vars.length] = var;
		coefs[vars.length]= -1; 
		double value = 0;
		return post(coefs,vars1,oper,value);
	}
	
	@Override
	public Constraint post(VarReal var, String oper, double value) {
		VarReal[] vars = { var };
		return post(vars,oper,value);
	}
	
	@Override
    public Constraint post(VarReal var, String oper, int value) {
        return post(var,oper,(double)value);
    }

	@Override
	public Constraint post(VarReal var1, String oper, VarReal var2) {
		VarReal[] vars = { var1, var2 };
		double[] coefficients = { 1, -1 };
		double value = 0;
		return post(coefficients, vars, oper, value);
	}

	@Override
	public Constraint post(VarReal var1, String oper, Var var2) {
		return post(var1,oper,var2.asReal());
	}

	@Override
	public Constraint post(Var var1, String oper, VarReal var2) {
		return post(var1.asReal(),oper,var2);
	}
	

	
	/**
	 * Creates and posts a constraint: var "oper" scalProd(arrayOfValues,arrayOfVariables)
	 * @param var the constraint variable
	 * @param oper an operator
	 * @param coefficients the array of values
	 * @param vars the array of variables
	 * @return a constraint 
	 */
//	public Constraint postScalProd(Var var, String oper, int[] coefficients, Var[] vars) {
//		if (coefficients.length != vars.length)
//			throw new RuntimeException("postScalProd: arrays of coefficients and vars should have the same length");
//		
//		int[] coefPlus1 = new int[coefficients.length+1];
//		Var[] varsPlus1 = new Var[vars.length+1];
//		for (int i = 0; i < vars.length; i++) {
//			coefPlus1[i] = coefficients[i];
//			varsPlus1[i] = vars[i];
//		}
//		coefPlus1[coefficients.length] = -1;
//		varsPlus1[vars.length] = var;
//		javax.constraints.impl.Constraint c = 
//				(javax.constraints.impl.Constraint)post(coefPlus1,varsPlus1,oper,0);
//		c.setDerivedVar(var);
//		return c;
//	}

	@Override
	public Var scalProd(int[] coefficients, Var[] vars) {
		if (coefficients.length != vars.length)
			throw new RuntimeException("Arrays of coefficients and vars should have the same length");
		
		int positiveMin = 0;
		int positiveMax = 0;
		int maxPositiveValue = 0;
		boolean areNegatives = false;
		for (int i = 0; i < vars.length; i++) {
			if (coefficients[i] < 0)
				areNegatives = true;
			if (vars[i].getMin() < 0)
				areNegatives = true;
			int prod = Math.abs(coefficients[i]*vars[i].getMax());
			if (maxPositiveValue < prod)
				maxPositiveValue = prod;
			positiveMin += vars[i].getMin()*coefficients[i];
			positiveMax += vars[i].getMax()*coefficients[i];
		}
		
		int min = positiveMin;
		int max = positiveMax;
		if (areNegatives == true) {
			max = maxPositiveValue*vars.length;
			min = -max;
		}
		//Var derivedVar = createVariable("_ScalProd"+(n+1)); //, min, max);
//		int min = Integer.MIN_VALUE+1;
//		int max = Integer.MAX_VALUE-1;
		int n = getConstraints().length;
		numberOfScalProducts++;
		Var derivedVar = createVariable("_ScalProd"+numberOfScalProducts, min, max);
		postScalProd(derivedVar, "=", coefficients, vars);
		remove("_ScalProd");
		// This variable needs to be added to the problem manually to avoid an uncompleted mps-file
		// add(derivedVar);
		return derivedVar;
	}
	
	@Override
	public Var scalProd(String name, int[] coefficients, Var[] vars) {
		if (coefficients.length != vars.length)
			throw new RuntimeException("Arrays of coefficients and vars should have the same length");
		
		int positiveMin = 0;
		int positiveMax = 0;
		int maxPositiveValue = 0;
		boolean areNegatives = false;
		for (int i = 0; i < vars.length; i++) {
			if (coefficients[i] < 0)
				areNegatives = true;
			if (vars[i].getMin() < 0)
				areNegatives = true;
			int prod = Math.abs(coefficients[i]*vars[i].getMax());
			if (maxPositiveValue < prod)
				maxPositiveValue = prod;
			positiveMin += vars[i].getMin()*coefficients[i];
			positiveMax += vars[i].getMax()*coefficients[i];
		}
		
		int min = positiveMin;
		int max = positiveMax;
		if (areNegatives == true) {
			max = maxPositiveValue*vars.length;
			min = -max;
		}
		int n = getConstraints().length;
		Var derivedVar = createVariable(name, min, max);
		add(name,derivedVar);
		postScalProd(derivedVar, "=", coefficients, vars);
		return derivedVar;
	}

	
	/**
	 * Returns a real constrained variable equal to the scalar product of an array of values "arrayOfValues"
	 *         and an array of variables "arrayOfVariables".
	 * @param arrayOfValues the array of values.
	 * @param arrayOfVariables the array of variables.
	 * @return a constrained variable equal to the scalar product of an array of values "arrayOfValues"
	 *         and an array of variables "arrayOfVariables".
	 */
	@Override
	public VarReal scalProd(double[] arrayOfValues, VarReal[] arrayOfVariables) {
		if (arrayOfValues.length != arrayOfVariables.length)
			throw new RuntimeException("Arrays of coefficients and vars should have the same length");
		
		double positiveMin = 0;
		double positiveMax = 0;
		double maxPositiveValue = 0;
		boolean areNegatives = false;
		double[] coefPlus1 = new double[arrayOfValues.length+1];
		VarReal[] varsPlus1 = new VarReal[arrayOfVariables.length+1];
		for (int i = 0; i < arrayOfVariables.length; i++) {
			coefPlus1[i] = arrayOfValues[i];
			varsPlus1[i] = arrayOfVariables[i];
			
			if (arrayOfValues[i] < 0)
				areNegatives = true;
			if (arrayOfVariables[i].getMin() < 0)
				areNegatives = true;
			double prod = Math.abs(arrayOfValues[i]*arrayOfVariables[i].getMax());
			if (maxPositiveValue < prod)
				maxPositiveValue = prod;
			positiveMin += arrayOfVariables[i].getMin()*arrayOfValues[i];
			positiveMax += arrayOfVariables[i].getMax()*arrayOfValues[i];
		}
		
		double min = positiveMin;
		double max = positiveMax;
		if (areNegatives == true) {
			max = maxPositiveValue*arrayOfVariables.length;
			min = -max;
		}
		
		for (int i = 0; i < arrayOfVariables.length; i++) {
			coefPlus1[i] = arrayOfValues[i];
			varsPlus1[i] = arrayOfVariables[i];
		}
		coefPlus1[arrayOfValues.length] = -1;
		int n = getConstraints().length;
		numberOfScalProducts++;
		VarReal derivedVar = createVariableReal("_ScalProd"+numberOfScalProducts,min,max);
		varsPlus1[arrayOfVariables.length] = derivedVar;
		javax.constraints.impl.Constraint c = 
				(javax.constraints.impl.Constraint)post(coefPlus1,varsPlus1,"=",0);
		c.setDerivedVar((AbstractConstrainedVariable)derivedVar);
		return derivedVar;
	}
	
	public VarReal scalProd(double[] arrayOfValues, ConstrainedVariable[] arrayOfVariables) {
		if (arrayOfValues.length != arrayOfVariables.length)
			throw new RuntimeException("Arrays of coefficients and vars should have the same length");
		
		double[] coefPlus1 = new double[arrayOfValues.length+1];
		ConstrainedVariable[] varsPlus1 = new ConstrainedVariable[arrayOfVariables.length+1];
		for (int i = 0; i < arrayOfVariables.length; i++) {
			//ConstrainedVariable var = arrayOfVariables[i];
			coefPlus1[i] = arrayOfValues[i];
			varsPlus1[i] = arrayOfVariables[i];
		}
		coefPlus1[arrayOfValues.length] = -1;
		int n = getConstraints().length;
		numberOfScalProducts++;
		VarReal derivedVar = createVariableReal("_ScalProd"+numberOfScalProducts);
		varsPlus1[arrayOfVariables.length] = derivedVar;
		javax.constraints.impl.Constraint c = 
				(javax.constraints.impl.Constraint)post(coefPlus1,varsPlus1,"=",0);
		c.setDerivedVar((AbstractConstrainedVariable)derivedVar);
		return derivedVar;
	}
	
	@Override
	public Var sum(Var[] vars) {
		if (vars.length==0) {
			log("Attempt to find a sum of an empty array");
			return variable(0,0);
		}
		int min = 0;
		int max = 0;
		for (int i = 0; i < vars.length; i++) {
			min += vars[i].getMin();
			max += vars[i].getMax();
		}
		AbstractProblem p = (AbstractProblem) vars[0].getProblem();
		Var sumVar = p.variable("_sum_", min, max);
		p.post(vars, "=", sumVar);
		int[] coefficients = new int[vars.length];
		for (int i = 0; i < coefficients.length; i++) {
			coefficients[i] = 1;
		}
		postScalProd(sumVar,"=",coefficients,vars);
		p.remove("_sum_");
		return sumVar;
	}
	
	@Override
	public Var sum(String name,Var[] vars) {
		if (vars.length==0) {
			log("Attempt to find a sum of an empty array");
			return variable(0,0);
		}
		int min = 0;
		int max = 0;
		for (int i = 0; i < vars.length; i++) {
			min += vars[i].getMin();
			max += vars[i].getMax();
		}
		AbstractProblem p = (AbstractProblem) vars[0].getProblem();
		Var sumVar = p.variable(name, min, max);
//		p.post(vars, "=", sumVar);
		int[] coefficients = new int[vars.length];
		for (int i = 0; i < coefficients.length; i++) {
			coefficients[i] = 1;
		}
		postScalProd(sumVar,"=",coefficients,vars);
		return sumVar;
	}
	
	@Override
	public VarReal sum(VarReal[] vars) {
		double[] coefficients = new double[vars.length];
		for (int i = 0; i < coefficients.length; i++) {
			coefficients[i] = 1.0;
		}
		return scalProd(coefficients,vars);
	}
		
	public boolean isDerivedVar(AbstractConstrainedVariable var) {
		Constraint[] constraints = getConstraints();
		for (int i = 0; i < constraints.length; i++) {
			javax.constraints.impl.Constraint c = 
					(javax.constraints.impl.Constraint) constraints[i];
			if (var == c.getDerivedVar())
				return true;
		}
		return false;
	}
	
//	public boolean isDerivedVar(VarReal var) {
//		Constraint[] constraints = getConstraints();
//		for (int i = 0; i < constraints.length; i++) {
//			javax.constraints.impl.Constraint c = 
//					(javax.constraints.impl.Constraint) constraints[i];
//			if (var == c.getDerivedVar())
//				return true;
//		}
//		return false;
//	}
	
	public javax.constraints.impl.Constraint[] constraintsWithDerivedVars() {
		Vector vector = 
				new Vector();
		Constraint[] constraints = getConstraints();
		for (int i = 0; i < constraints.length; i++) {
			javax.constraints.impl.Constraint c = 
					(javax.constraints.impl.Constraint) constraints[i];
			if (c.getDerivedVar() != null)
				vector.add(c);
		}
		if (vector.isEmpty())
			return null;
		javax.constraints.impl.Constraint[] result = 
				new javax.constraints.impl.Constraint[vector.size()];
		for (int i = 0; i < result.length; i++) {
			result[i] = vector.get(i);
		}
		return result;		
	}
	
	public javax.constraints.impl.Constraint findConstraintForVariable(String name) {
		Constraint[] constraints = getConstraints();
		for (int i = 0; i < constraints.length; i++) {
			javax.constraints.impl.Constraint c = 
					(javax.constraints.impl.Constraint) constraints[i];
			if (c.getDerivedVar() != null && name.equals(c.getDerivedVar().getName()))
				return c;
		}
		return null;		
	}

	@Override
	public Constraint allDiff(Var[] vars) {
		throw new NonLinearProblemException("allDiff(Var[] vars)");
	}

	@Override
	public Constraint postCardinality(Var[] vars, int cardValue, String oper, int value) {
		throw new NonLinearProblemException("postCardinality(Var[] vars, int cardValue, String oper, int value)");
	}

	@Override
	public Constraint postCardinality(Var[] vars, int cardValue, String oper, Var var) {
		throw new NonLinearProblemException("postCardinality(Var[] vars, int cardValue, String oper, Var var)");
	}

	@Override
	public String getImplVersion() {
		return JSR331_LINEAR_VERSION;
	}

	@Override
	public Var createVariable(String name, int min, int max) {
		javax.constraints.impl.Var var = new javax.constraints.impl.Var(this,name);
		var.setMin(min);
		var.setMax(max);
		return var;
	}
	
	public Var createVariable(String name) {
		javax.constraints.impl.Var var = new javax.constraints.impl.Var(this,name);
		return var;
	}
	
	public VarReal createVariableReal(String name, double min, double max) {
		javax.constraints.impl.VarReal var = new javax.constraints.impl.VarReal(this,name);
		var.setMin(min);
		var.setMax(max);
		add(name,var);
		return var;
	}
	
	public VarReal createVariableReal(String name) {
		javax.constraints.impl.VarReal var = new javax.constraints.impl.VarReal(this,name);
		return var;
	}

	@Override
	public VarBool variableBool(String name) {
		return (VarBool)variable(name,0,1);
	}

	@Override
	public void post(Constraint constraint) {
		//throw new NonLinearProblemException("post(Constraint constraint) is not used for a linear problem");
		add(constraint);
	}

	@Override
	protected Solver createSolver() {
		LinearSolver solver = LinearSolverFactory.newLinearSolver(this);
		log("Solve problem using " + solver.getVersion());
		return solver;
	}

	private static org.slf4j.Logger logger = LoggerFactory.getLogger("javax.constraints");
	
	@Override
	public void log(String text) {
		logger.info(text);
	}

	@Override
	public void debug(String text) {
		logger.debug(text);
	}

	@Override
	public void error(String text) {
		logger.error(text);
	}
	
	@Override
	public void loadFromXML(InputStream in) throws Exception {
		throw new RuntimeException("loadFromXML is not implemented");
	}

	@Override
	public void storeToXML(OutputStream os, String comment) throws Exception {
		throw new RuntimeException("storeToXML is not implemented");
	}

    public ArrayList getIntegerConstraints() {
        return integerConstraints;
    }

    public void setIntegerConstraints(ArrayList integerConstraints) {
        this.integerConstraints = integerConstraints;
    }

    public ArrayList getRealConstraints() {
        return realConstraints;
    }

    public void setRealConstraints(ArrayList realConstraints) {
        this.realConstraints = realConstraints;
    }
	
//	public void add(AbstractConstrainedVariable var) {
//		add(var);
//	}

	
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy