package org.ut.cmldep.Optimj;

public final class LPsolution_GLPK_Opt extends LPsolutionParam implements
		LPsolution {
	private com.ateji.optimj.MatrixGlpk4_36 _solver = new com.ateji.optimj.MatrixGlpk4_36(
			0);
	private org.gnu.glpk.glp_prob matrix;
	private boolean _isMIP;
	private int _nextFreeColum = 1;
	double _row[] = new double[_nextFreeColum];
	int _colno[] = new int[_nextFreeColum];
	int _j = 0;
	final double[] costPerTBInstanceTypes;
	final int[] startTimeInstanceTypes;
	final double[] bck;
	final double[] bcr;
	final int[] processingPower;
	final int[] Wr;
	final int[] CCr;
	final int[] indexOfRegions;
	final int[] indexOfInstanceTypesInRegions;
	int[] Nresult;
	int[] Sresult;

	public LPsolution_GLPK_Opt(int numOfRegions, int totalNumOftimeUnits,
			int totalNumOfCurrentTimeBags,
			int TotalNumOfInstanceTypesInRegions, int[] X,
			double[] costPerTBInstanceTypes, int[] startTimeInstanceTypes,
			double[] bck, double[] bcr, int[] processingPower,
			int[] maxNumOfEachInstanceType, int[] Wr, int[] CCr,
			int[] indexOfRegions, int[] indexOfInstanceTypesInRegions) {

		super(numOfRegions, totalNumOftimeUnits, totalNumOfCurrentTimeBags,
				TotalNumOfInstanceTypesInRegions, maxNumOfEachInstanceType, X);
		this.costPerTBInstanceTypes = costPerTBInstanceTypes;
		this.startTimeInstanceTypes = startTimeInstanceTypes;
		this.bck = bck;
		this.bcr = bcr;
		this.processingPower = processingPower;
		this.Wr = Wr;
		this.CCr = CCr;
		this.indexOfRegions = indexOfRegions;
		this.indexOfInstanceTypesInRegions = indexOfInstanceTypesInRegions;

	}

	// /////////////////////////Variables/////////////////////////////////////////
	private java.util.Set<java.lang.Integer> isAVarInt = new java.util.HashSet<java.lang.Integer>();
	final int[] N;
	{
		final int initDim = TotalNumOfInstanceTypesInRegions;
		final int[] array = new int[initDim];
		for (int i = 0; i < initDim; i++) {
			int freshVariable = _nextFreeColum++;
			{
				_solver.addColumnex(0, new double[] { 0.0 }, new int[] { 1 });
				_solver.setColName(freshVariable, "N" + "_" + i);
				{
					_solver.setInt(freshVariable, true);
					isAVarInt.add(freshVariable);
				}
				_solver.setBounds(freshVariable, 0,
						((int[]) (maxNumOfEachInstanceType))[i]);
			}
			array[i] = freshVariable;
		}
		N = array;
	}
	final int[] S;

	// /////////////////////////Constraints/////////////////////////////////////////
	{
		final int initDim0 = totalNumOfCurrentTimeBags;
		final int[] array0 = new int[initDim0];
		for (int i = 0; i < initDim0; i++) {
			int freshVariable0 = _nextFreeColum++;
			{
				_solver.addColumnex(0, new double[] { 0.0 }, new int[] { 1 });
				_solver.setColName(freshVariable0, "S" + "_" + i);
				{
					_solver.setInt(freshVariable0, true);
					isAVarInt.add(freshVariable0);
				}
				_solver.setBounds(freshVariable0, 0, ((int[]) (X))[i]);
			}
			array0[i] = freshVariable0;
		}
		S = array0;
	}

	public void resolve() {

		com.ateji.optimj.glpklib.LibraryLoader.load();
		System.out.println("totalNumOfCurrentTimeBags:"
				+ totalNumOfCurrentTimeBags);

		long t1 = System.currentTimeMillis();
		try {
			this.extract();
			if (this.solve()) {

				System.out.println("solution found");

				final int initDim1 = N.length;
				final int[] array1 = new int[initDim1];
				Nresult = array1;
				for (int i = 0; i < N.length; i++) {
					((int[]) (Nresult))[i] = this
							.valueInt(((int[]) (this.N))[i]);
					System.out.println("N" + i + " = "
							+ this.valueInt(((int[]) (this.N))[i]));
				}

				final int initDim2 = S.length;
				final int[] array2 = new int[initDim2];
				Sresult = array2;
				for (int i = 0; i < S.length; i++) {
					((int[]) (Sresult))[i] = this
							.valueInt(((int[]) (this.S))[i]);
					System.out.println("S" + i + " = "
							+ this.valueInt(((int[]) (this.S))[i]));
				}

				System.out.println("Minimal Cost:" + this.objValue());

				System.out.println("Execution Time(ms):"
						+ (System.currentTimeMillis() - t1));
			} else {
				System.out.println("No solution.");
			}
		} finally {
			this.dispose();

		}

	}

	public int[] getN() {

		return Nresult;

	}

	public int[] getS() {

		return Sresult;

	}

	public void extract() throws com.ateji.optimj.SolverException {
		extractWasCalled = true;
		;
		for (int i : new optimj.util.Range(0, (totalNumOfCurrentTimeBags - 1))) {
			{
				_j = 0; /* ((int [])(S))[i] <= ((int [])(X))[i] */
				if (_j >= _row.length) {
					double[] freshVariable1 = new double[_j * 2];
					java.lang.System.arraycopy(_row, 0, freshVariable1, 0, _j);
					_row = freshVariable1;
					int[] freshVariable2 = new int[_j * 2];
					java.lang.System
							.arraycopy(_colno, 0, freshVariable2, 0, _j);
					_colno = freshVariable2;
				}
				_colno[_j] = ((int[]) (S))[i];
				_row[_j++] = 1;
				int constantPart = ((int[]) (X))[i];
				_j = com.ateji.optimj.Lpsolve.canonicalRepresentation(_j, _row,
						_colno);/*
								 * merge row values which have the same colno
								 * value
								 */
				_solver.addConstraintex(_j, _row, _colno,
						com.ateji.optimj.MatrixGlpk4_36.LE, constantPart);
				_solver.setRowName(_solver.getNrows(), "R" + _solver.getNrows());
			}
		}
		for (int i : new optimj.util.Range(0, (numOfRegions - 1))) {
			{
				_j = 0; /*
						 * sum{int j : ((int [])(indexOfRegions))[i] .. (((int
						 * [])(indexOfRegions))[i+1] - 1)} {(sum{int k : ((int
						 * [])(indexOfInstanceTypesInRegions))[j] .. (((int
						 * [])(indexOfInstanceTypesInRegions))[j+1] - 1)}{((int
						 * [])(X))[k]} + ((int [])(N))[j] - sum{int k : ((int
						 * [])(indexOfInstanceTypesInRegions))[j] .. (((int
						 * [])(indexOfInstanceTypesInRegions))[j+1] - 1)}{((int
						 * [])(S))[k]}) * ((int [])(processingPower))[j]} >=
						 * ((int [])(Wr))[i]
						 */
				double constantPart2 = 0;
				for (int j : new optimj.util.Range(
						((int[]) (indexOfRegions))[i],
						(((int[]) (indexOfRegions))[i + 1] - 1))) {
					{
						int freshVariable17;
						{
							freshVariable17 = (((int[]) (processingPower))[j] * (1));
						}
						int toBeReturned = 0;
						for (int k : new optimj.util.Range(
								((int[]) (indexOfInstanceTypesInRegions))[j],
								(((int[]) (indexOfInstanceTypesInRegions))[j + 1] - 1))) {
							toBeReturned += ((int[]) (X))[k];
						}
						int constantPart0 = -(freshVariable17 * (toBeReturned));
						if (_j >= _row.length) {
							double[] freshVariable3 = new double[_j * 2];
							java.lang.System.arraycopy(_row, 0, freshVariable3,
									0, _j);
							_row = freshVariable3;
							int[] freshVariable4 = new int[_j * 2];
							java.lang.System.arraycopy(_colno, 0,
									freshVariable4, 0, _j);
							_colno = freshVariable4;
						}
						_colno[_j] = ((int[]) (N))[j];
						_row[_j++] = ((int[]) (processingPower))[j] * (1);
						for (int k : new optimj.util.Range(
								((int[]) (indexOfInstanceTypesInRegions))[j],
								(((int[]) (indexOfInstanceTypesInRegions))[j + 1] - 1))) {
							{
								if (_j >= _row.length) {
									double[] freshVariable5 = new double[_j * 2];
									java.lang.System.arraycopy(_row, 0,
											freshVariable5, 0, _j);
									_row = freshVariable5;
									int[] freshVariable6 = new int[_j * 2];
									java.lang.System.arraycopy(_colno, 0,
											freshVariable6, 0, _j);
									_colno = freshVariable6;
								}
								_colno[_j] = ((int[]) (S))[k];
								_row[_j++] = -(((int[]) (processingPower))[j] * (1));
							}
						}
						constantPart2 += (constantPart0);
					}
				}
				int constantPart3 = ((int[]) (Wr))[i];
				_j = com.ateji.optimj.Lpsolve.canonicalRepresentation(_j, _row,
						_colno);/*
								 * merge row values which have the same colno
								 * value
								 */
				_solver.addConstraintex(_j, _row, _colno,
						com.ateji.optimj.MatrixGlpk4_36.GE, (constantPart2)
								+ constantPart3);

				_solver.setRowName(_solver.getNrows(), "R" + _solver.getNrows());
			}
		}
		for (int i : new optimj.util.Range(0, (numOfRegions - 1))) {
			{
				_j = 0; /*
						 * sum{int j : ((int [])(indexOfRegions))[i] .. (((int
						 * [])(indexOfRegions))[i+1] - 1)} {(sum{int k : ((int
						 * [])(indexOfInstanceTypesInRegions))[j] .. (((int
						 * [])(indexOfInstanceTypesInRegions))[j+1] - 1)}{((int
						 * [])(X))[k]} + ((int [])(N))[j] - sum{int k : ((int
						 * [])(indexOfInstanceTypesInRegions))[j] .. (((int
						 * [])(indexOfInstanceTypesInRegions))[j+1] - 1)}{((int
						 * [])(S))[k]})} <= ((int [])(CCr))[i]
						 */
				double constantPart6 = 0;
				for (int j : new optimj.util.Range(
						((int[]) (indexOfRegions))[i],
						(((int[]) (indexOfRegions))[i + 1] - 1))) {
					{
						int freshVariable18;
						{
							freshVariable18 = (1);
						}
						int toBeReturned0 = 0;
						for (int k : new optimj.util.Range(
								((int[]) (indexOfInstanceTypesInRegions))[j],
								(((int[]) (indexOfInstanceTypesInRegions))[j + 1] - 1))) {
							toBeReturned0 += ((int[]) (X))[k];
						}
						int constantPart4 = -(freshVariable18 * (toBeReturned0));
						if (_j >= _row.length) {
							double[] freshVariable7 = new double[_j * 2];
							java.lang.System.arraycopy(_row, 0, freshVariable7,
									0, _j);
							_row = freshVariable7;
							int[] freshVariable8 = new int[_j * 2];
							java.lang.System.arraycopy(_colno, 0,
									freshVariable8, 0, _j);
							_colno = freshVariable8;
						}
						_colno[_j] = ((int[]) (N))[j];
						_row[_j++] = 1;
						for (int k : new optimj.util.Range(
								((int[]) (indexOfInstanceTypesInRegions))[j],
								(((int[]) (indexOfInstanceTypesInRegions))[j + 1] - 1))) {
							{
								if (_j >= _row.length) {
									double[] freshVariable9 = new double[_j * 2];
									java.lang.System.arraycopy(_row, 0,
											freshVariable9, 0, _j);
									_row = freshVariable9;
									int[] freshVariable10 = new int[_j * 2];
									java.lang.System.arraycopy(_colno, 0,
											freshVariable10, 0, _j);
									_colno = freshVariable10;
								}
								_colno[_j] = ((int[]) (S))[k];
								_row[_j++] = -(1);
							}
						}
						constantPart6 += (constantPart4);
					}
				}
				int constantPart7 = ((int[]) (CCr))[i];
				_j = com.ateji.optimj.Lpsolve.canonicalRepresentation(_j, _row,
						_colno);/*
								 * merge row values which have the same colno
								 * value
								 */
				_solver.addConstraintex(_j, _row, _colno,
						com.ateji.optimj.MatrixGlpk4_36.LE, (constantPart6)
								+ constantPart7);

				_solver.setRowName(_solver.getNrows(), "R" + _solver.getNrows());
			}
		}
		_j = 0; /*
				 * sum{int i : 0 .. (TotalNumOfInstanceTypesInRegions -
				 * 1)}{(((int [])(N))[i] * ((double
				 * [])(costPerTBInstanceTypes))[i]) * (totalNumOftimeUnits +
				 * ((int [])(startTimeInstanceTypes))[i])} + sum{int j : 0 ..
				 * (totalNumOfCurrentTimeBags - 1)}{((int [])(S))[j] * ((double
				 * [])(bck))[j]} - sum{int k : 0 .. (totalNumOfCurrentTimeBags -
				 * 1)}{(((int [])(S))[k]) * ((double [])(bcr))[k]}
				 */
		for (int i : new optimj.util.Range(0,
				(TotalNumOfInstanceTypesInRegions - 1))) {
			{
				if (_j >= _row.length) {
					double[] freshVariable11 = new double[_j * 2];
					java.lang.System.arraycopy(_row, 0, freshVariable11, 0, _j);
					_row = freshVariable11;
					int[] freshVariable12 = new int[_j * 2];
					java.lang.System.arraycopy(_colno, 0, freshVariable12, 0,
							_j);
					_colno = freshVariable12;
				}
				_colno[_j] = ((int[]) (N))[i];
				_row[_j++] = ((double[]) (costPerTBInstanceTypes))[i]
						* ((totalNumOftimeUnits + ((int[]) (startTimeInstanceTypes))[i]) * (1));
			}
		}
		for (int j : new optimj.util.Range(0, (totalNumOfCurrentTimeBags - 1))) {
			{
				if (_j >= _row.length) {
					double[] freshVariable13 = new double[_j * 2];
					java.lang.System.arraycopy(_row, 0, freshVariable13, 0, _j);
					_row = freshVariable13;
					int[] freshVariable14 = new int[_j * 2];
					java.lang.System.arraycopy(_colno, 0, freshVariable14, 0,
							_j);
					_colno = freshVariable14;
				}
				_colno[_j] = ((int[]) (S))[j];
				_row[_j++] = ((double[]) (bck))[j] * (1);
			}
		}
		for (int k : new optimj.util.Range(0, (totalNumOfCurrentTimeBags - 1))) {
			{
				if (_j >= _row.length) {
					double[] freshVariable15 = new double[_j * 2];
					java.lang.System.arraycopy(_row, 0, freshVariable15, 0, _j);
					_row = freshVariable15;
					int[] freshVariable16 = new int[_j * 2];
					java.lang.System.arraycopy(_colno, 0, freshVariable16, 0,
							_j);
					_colno = freshVariable16;
				}
				_colno[_j] = ((int[]) (S))[k];
				_row[_j++] = ((double[]) (bcr))[k] * (-(1));
			}
		}
		_j = com.ateji.optimj.Lpsolve.canonicalRepresentation(_j, _row, _colno);/*
																				 * merge
																				 * row
																				 * values
																				 * which
																				 * have
																				 * the
																				 * same
																				 * colno
																				 * value
																				 */
		_solver.setObjFnex(_j, _row, _colno);
		_solver.setMinim();
		;
		matrix = _solver.createGLPK();
		_isMIP = _solver.isMIP();
		_solver.clean();
	}

	private boolean extractWasCalled = false;

	public boolean solve() throws com.ateji.optimj.SolverException {
		try {
			if (!extractWasCalled)
				throw new com.ateji.optimj.SolverException(
						"extract() must be called before calling solve().");
			org.gnu.glpk.GLPK.glp_simplex(matrix, null);
			if (_isMIP)
				org.gnu.glpk.GLPK.glp_intopt(matrix, null);
			return org.gnu.glpk.GLPK.glp_get_status(matrix) == org.gnu.glpk.GLPKConstants.GLP_OPT;
		} catch (com.ateji.optimj.SolverException e) {
			throw new com.ateji.optimj.SolverException(e);
		}
	}

	public int solverStatus() {
		return org.gnu.glpk.GLPK.glp_get_status(matrix);
	}

	private java.util.Map<java.lang.Integer, java.lang.Object> decoder = new java.util.HashMap<java.lang.Integer, java.lang.Object>();

	public double valueDouble(int column) {
		try {
			if (_isMIP)
				return org.gnu.glpk.GLPK.glp_mip_col_val(matrix, column);
			else
				return org.gnu.glpk.GLPK.glp_get_col_prim(matrix, column);
		} catch (com.ateji.optimj.SolverException e) {
			throw new com.ateji.optimj.SolverException(e);
		}
	}

	public int valueInt(int column) {
		return (int) java.lang.Math.round(valueDouble(column));
	}

	public boolean valueBoolean(int column) {
		return valueInt(column) == 1 ? true : false;
	}

	@java.lang.SuppressWarnings("unchecked")
	public <__atejiTypeParameterT> __atejiTypeParameterT valueT(int column) {
		return (__atejiTypeParameterT) decoder.get(valueInt(column));
	}

	public double objValue() throws com.ateji.optimj.SolverException {
		if (_isMIP)
			return org.gnu.glpk.GLPK.glp_mip_obj_val(matrix);
		else
			return org.gnu.glpk.GLPK.glp_get_obj_val(matrix);
	}

	public double lower(int column) {
		try {
			return org.gnu.glpk.GLPK.glp_get_col_lb(matrix, column);
		} catch (com.ateji.optimj.SolverException e) {
			throw new com.ateji.optimj.SolverException(e);
		}
	}

	public double lowerBound(int column) {
		try {
			return org.gnu.glpk.GLPK.glp_get_col_lb(matrix, column);
		} catch (com.ateji.optimj.SolverException e) {
			throw new com.ateji.optimj.SolverException(e);
		}
	}

	public double upperBound(int column) {
		try {
			return org.gnu.glpk.GLPK.glp_get_col_ub(matrix, column);
		} catch (com.ateji.optimj.SolverException e) {
			throw new com.ateji.optimj.SolverException(e);
		}
	}

	public double upper(int column) {
		try {
			return org.gnu.glpk.GLPK.glp_get_col_ub(matrix, column);
		} catch (com.ateji.optimj.SolverException e) {
			throw new com.ateji.optimj.SolverException(e);
		}
	}

	public double reducedCost(int column)
			throws com.ateji.optimj.SolverException {
		return org.gnu.glpk.GLPK.glp_get_col_dual(matrix, column);
	}

	public double sensitivity(int row) throws com.ateji.optimj.SolverException {
		return org.gnu.glpk.GLPK.glp_get_row_dual(matrix, row);
	}

	public int column(int variable) {
		return variable;
	}

	public int row(int variable) {
		return variable;
	}

	public org.gnu.glpk.glp_prob solver() {
		return matrix;
	}

	public void dispose() {
		if (matrix != null)
			matrix.delete();
		matrix = null;
		_solver = null;
	}
}
