package org.ut.cmldep.Optimj;

public final class LPsolution_GLPK_MT 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_MT(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 var int[] S[int i : TotalNumOfInstanceTypesInRegions] in 0 .. X[i];

	// /////////////////////////Constraints/////////////////////////////////////////
	{
		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;
	}

	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 initDim0 = N.length;
				final int[] array0 = new int[initDim0];
				Nresult = array0;
				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]));
				}

				/*
				 * Sresult = new int[S.length]; for(int i = 0 ; i < S.length;
				 * i++) { Sresult[i] = this.value(this.S[i]);
				 * System.out.println("S" + i + " = " + this.value(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, (numOfRegions - 1))) {
			{
				_j = 0; /*
						 * sum{int j : ((int [])(indexOfRegions))[i] .. (((int
						 * [])(indexOfRegions))[i+1] - 1)} {((int [])(N))[j] *
						 * ((int [])(processingPower))[j]} >= ((int [])(Wr))[i]
						 */
				for (int j : new optimj.util.Range(
						((int[]) (indexOfRegions))[i],
						(((int[]) (indexOfRegions))[i + 1] - 1))) {
					{
						if (_j >= _row.length) {
							double[] freshVariable0 = new double[_j * 2];
							java.lang.System.arraycopy(_row, 0, freshVariable0,
									0, _j);
							_row = freshVariable0;
							int[] freshVariable1 = new int[_j * 2];
							java.lang.System.arraycopy(_colno, 0,
									freshVariable1, 0, _j);
							_colno = freshVariable1;
						}
						_colno[_j] = ((int[]) (N))[j];
						_row[_j++] = ((int[]) (processingPower))[j] * (1);
					}
				}
				int constantPart0 = ((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, constantPart0);

				_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)}{((int [])(N))[j]} <=
						 * ((int [])(CCr))[i]
						 */
				for (int j : new optimj.util.Range(
						((int[]) (indexOfRegions))[i],
						(((int[]) (indexOfRegions))[i + 1] - 1))) {
					{
						if (_j >= _row.length) {
							double[] freshVariable2 = new double[_j * 2];
							java.lang.System.arraycopy(_row, 0, freshVariable2,
									0, _j);
							_row = freshVariable2;
							int[] freshVariable3 = new int[_j * 2];
							java.lang.System.arraycopy(_colno, 0,
									freshVariable3, 0, _j);
							_colno = freshVariable3;
						}
						_colno[_j] = ((int[]) (N))[j];
						_row[_j++] = 1;
					}
				}
				int constantPart2 = ((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, constantPart2);

				_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])}
				 */
		for (int i : new optimj.util.Range(0,
				(TotalNumOfInstanceTypesInRegions - 1))) {
			{
				if (_j >= _row.length) {
					double[] freshVariable4 = new double[_j * 2];
					java.lang.System.arraycopy(_row, 0, freshVariable4, 0, _j);
					_row = freshVariable4;
					int[] freshVariable5 = new int[_j * 2];
					java.lang.System
							.arraycopy(_colno, 0, freshVariable5, 0, _j);
					_colno = freshVariable5;
				}
				_colno[_j] = ((int[]) (N))[i];
				_row[_j++] = ((double[]) (costPerTBInstanceTypes))[i]
						* ((totalNumOftimeUnits + ((int[]) (startTimeInstanceTypes))[i]) * (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;
	}
}
