// Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.geocities.com/kpdus/jad.html
// Decompiler options: packimports(3) fieldsfirst 
// Source File Name:   solve.java

package lp;

import java.io.PrintStream;
import java.util.Random;
import java.util.StringTokenizer;

// Referenced classes of package lp:
//			matrec, Ref, constant, lprec, 
//			Util

public class solve
	implements constant
{

	lprec Lp;
	int Rows;
	int Columns;
	int Sum;
	int Non_zeros;
	int Level;
	matrec Mat[];
	int Col_no[];
	int Col_end[];
	int Row_end[];
	double Orig_rh[];
	double Rh[];
	double Rhs[];
	int Must_be_int[];
	double Orig_upbo[];
	double Orig_lowbo[];
	double Upbo[];
	double Lowbo[];
	int Bas[];
	int Basis[];
	int Lower[];
	int Eta_alloc;
	int Eta_size;
	double Eta_value[];
	int Eta_row_nr[];
	int Eta_col_end[];
	int Num_inv;
	double Solution[];
	double Best_solution[];
	double Infinite;
	double Epsilon;
	double Epsb;
	double Epsd;
	double Epsel;
	double TREJ;
	double TINV;
	int Maximise;
	int Floor_first;
	double Extrad;
	int Warn_count;
	int JustInverted;
	int Status;
	int Doiter;
	int DoInvert;
	int Break_bb;

	void inc_mat_space(lprec lprec1, int i)
	{
		if(lprec1.non_zeros + i > lprec1.mat_alloc)
		{
			lprec1.mat_alloc = lprec1.non_zeros + i;
			matrec amatrec[] = lprec1.mat;
			lprec1.mat = new matrec[lprec1.mat_alloc];
			for(int j = amatrec.length; j < lprec1.mat.length; j++)
				lprec1.mat[j] = new matrec(0, 0.0D);

			System.arraycopy(amatrec, 0, lprec1.mat, 0, amatrec.length);
			int ai[] = lprec1.col_no;
			lprec1.col_no = new int[lprec1.mat_alloc];
			System.arraycopy(ai, 0, lprec1.col_no, 0, ai.length);
			if(lprec1.active != 0)
			{
				Mat = lprec1.mat;
				Col_no = lprec1.col_no;
			}
		}
	}

	void inc_row_space(lprec lprec1)
	{
		if(lprec1.rows > lprec1.rows_alloc)
		{
			lprec1.rows_alloc = lprec1.rows + 10;
			lprec1.sum_alloc = lprec1.rows_alloc + lprec1.columns_alloc;
			double ad[] = lprec1.orig_rh;
			lprec1.orig_rh = new double[lprec1.rows_alloc + 1];
			System.arraycopy(ad, 0, lprec1.orig_rh, 0, ad.length);
			ad = lprec1.rh;
			lprec1.rh = new double[lprec1.rows_alloc + 1];
			System.arraycopy(ad, 0, lprec1.rh, 0, ad.length);
			ad = lprec1.rhs;
			lprec1.rhs = new double[lprec1.rows_alloc + 1];
			System.arraycopy(ad, 0, lprec1.rhs, 0, ad.length);
			ad = lprec1.orig_upbo;
			lprec1.orig_upbo = new double[lprec1.sum_alloc + 1];
			System.arraycopy(ad, 0, lprec1.orig_upbo, 0, ad.length);
			ad = lprec1.upbo;
			lprec1.upbo = new double[lprec1.sum_alloc + 1];
			System.arraycopy(ad, 0, lprec1.upbo, 0, ad.length);
			ad = lprec1.orig_lowbo;
			lprec1.orig_lowbo = new double[lprec1.sum_alloc + 1];
			System.arraycopy(ad, 0, lprec1.orig_lowbo, 0, ad.length);
			ad = lprec1.lowbo;
			lprec1.lowbo = new double[lprec1.sum_alloc + 1];
			System.arraycopy(ad, 0, lprec1.lowbo, 0, ad.length);
			ad = lprec1.solution;
			lprec1.solution = new double[lprec1.sum_alloc + 1];
			System.arraycopy(ad, 0, lprec1.solution, 0, ad.length);
			ad = lprec1.best_solution;
			lprec1.best_solution = new double[lprec1.sum_alloc + 1];
			System.arraycopy(ad, 0, lprec1.best_solution, 0, ad.length);
			int ai[] = lprec1.row_end;
			lprec1.row_end = new int[lprec1.rows_alloc + 1];
			System.arraycopy(ai, 0, lprec1.row_end, 0, ai.length);
			int aword0[] = lprec1.basis;
			lprec1.basis = new int[lprec1.sum_alloc + 1];
			System.arraycopy(aword0, 0, lprec1.basis, 0, aword0.length);
			aword0 = lprec1.lower;
			lprec1.lower = new int[lprec1.sum_alloc + 1];
			System.arraycopy(aword0, 0, lprec1.lower, 0, aword0.length);
			aword0 = lprec1.must_be_int;
			lprec1.must_be_int = new int[lprec1.sum_alloc + 1];
			System.arraycopy(aword0, 0, lprec1.must_be_int, 0, aword0.length);
			ai = lprec1.bas;
			lprec1.bas = new int[lprec1.rows_alloc + 1];
			System.arraycopy(ai, 0, lprec1.bas, 0, ai.length);
			ad = lprec1.duals;
			lprec1.duals = new double[lprec1.rows_alloc + 1];
			System.arraycopy(ad, 0, lprec1.duals, 0, ad.length);
			aword0 = lprec1.ch_sign;
			lprec1.ch_sign = new int[lprec1.rows_alloc + 1];
			System.arraycopy(aword0, 0, lprec1.ch_sign, 0, aword0.length);
			ai = lprec1.eta_col_end;
			lprec1.eta_col_end = new int[lprec1.rows_alloc + lprec1.max_num_inv];
			System.arraycopy(ai, 0, lprec1.eta_col_end, 0, ai.length);
			if(lprec1.names_used != 0)
			{
				String as[] = lprec1.row_name;
				lprec1.row_name = new String[lprec1.rows_alloc + 1];
				System.arraycopy(as, 0, lprec1.row_name, 0, as.length);
			}
			if(lprec1.scaling_used != 0)
			{
				double ad1[] = lprec1.scale;
				lprec1.scale = new double[lprec1.sum_alloc + 1];
				System.arraycopy(ad1, 0, lprec1.scale, 0, ad1.length);
			}
			if(lprec1.active != 0)
				set_globals(lprec1);
		}
	}

	void inc_col_space(lprec lprec1)
	{
		if(lprec1.columns >= lprec1.columns_alloc)
		{
			lprec1.columns_alloc = lprec1.columns + 10;
			lprec1.sum_alloc = lprec1.rows_alloc + lprec1.columns_alloc;
			int aword0[] = lprec1.must_be_int;
			lprec1.must_be_int = new int[lprec1.sum_alloc + 1];
			System.arraycopy(aword0, 0, lprec1.must_be_int, 0, aword0.length);
			double ad[] = lprec1.orig_upbo;
			lprec1.orig_upbo = new double[lprec1.sum_alloc + 1];
			System.arraycopy(ad, 0, lprec1.orig_upbo, 0, ad.length);
			ad = lprec1.upbo;
			lprec1.upbo = new double[lprec1.sum_alloc + 1];
			System.arraycopy(ad, 0, lprec1.upbo, 0, ad.length);
			ad = lprec1.orig_lowbo;
			lprec1.orig_lowbo = new double[lprec1.sum_alloc + 1];
			System.arraycopy(ad, 0, lprec1.orig_lowbo, 0, ad.length);
			ad = lprec1.lowbo;
			lprec1.lowbo = new double[lprec1.sum_alloc + 1];
			System.arraycopy(ad, 0, lprec1.lowbo, 0, ad.length);
			ad = lprec1.solution;
			lprec1.solution = new double[lprec1.sum_alloc + 1];
			System.arraycopy(ad, 0, lprec1.solution, 0, ad.length);
			ad = lprec1.best_solution;
			lprec1.best_solution = new double[lprec1.sum_alloc + 1];
			System.arraycopy(ad, 0, lprec1.best_solution, 0, ad.length);
			aword0 = lprec1.basis;
			lprec1.basis = new int[lprec1.sum_alloc + 1];
			System.arraycopy(aword0, 0, lprec1.basis, 0, aword0.length);
			aword0 = lprec1.lower;
			lprec1.lower = new int[lprec1.sum_alloc + 1];
			System.arraycopy(aword0, 0, lprec1.lower, 0, aword0.length);
			if(lprec1.names_used != 0)
			{
				String as[] = lprec1.col_name;
				lprec1.col_name = new String[lprec1.columns_alloc + 1];
				System.arraycopy(as, 0, lprec1.col_name, 0, as.length);
			}
			if(lprec1.scaling_used != 0)
			{
				double ad1[] = lprec1.scale;
				lprec1.scale = new double[lprec1.sum_alloc + 1];
				System.arraycopy(ad1, 0, lprec1.scale, 0, ad1.length);
			}
			int ai[] = lprec1.col_end;
			lprec1.col_end = new int[lprec1.columns_alloc + 1];
			System.arraycopy(ai, 0, lprec1.col_end, 0, ai.length);
			if(lprec1.active != 0)
				set_globals(lprec1);
		}
	}

	public void set_mat(lprec lprec1, int i, int j, double d)
	{
		if(i > lprec1.rows || i < 0)
			System.err.print("Row out of range");
		if(j > lprec1.columns || j < 1)
			System.err.print("Column out of range");
		if(lprec1.scaling_used != 0)
			d *= lprec1.scale[i] * lprec1.scale[lprec1.rows + j];
		if(lprec1.basis[j] == 1 && i > 0)
			lprec1.basis_valid = 0;
		lprec1.eta_valid = 0;
		int k;
		for(k = lprec1.col_end[j - 1]; k < lprec1.col_end[j] && lprec1.mat[k].row_nr != i; k++);
		if(k != lprec1.col_end[j] && lprec1.mat[k].row_nr == i)
		{
			if(lprec1.scaling_used != 0)
			{
				if(lprec1.ch_sign[i] != 0)
					lprec1.mat[k].value = -d * lprec1.scale[i] * lprec1.scale[j];
				else
					lprec1.mat[k].value = d * lprec1.scale[i] * lprec1.scale[j];
			} else
			if(lprec1.ch_sign[i] != 0)
				lprec1.mat[k].value = -d;
			else
				lprec1.mat[k].value = d;
		} else
		{
			inc_mat_space(lprec1, 1);
			int l = lprec1.non_zeros;
			for(int i1 = l; i1 > k; i1--)
				lprec1.mat[i1] = lprec1.mat[i1 - 1];

			for(int j1 = j; j1 <= lprec1.columns; j1++)
				lprec1.col_end[j1]++;

			lprec1.mat[k].row_nr = i;
			if(lprec1.scaling_used != 0)
			{
				if(lprec1.ch_sign[i] != 0)
					lprec1.mat[k].value = -d * lprec1.scale[i] * lprec1.scale[j];
				else
					lprec1.mat[k].value = d * lprec1.scale[i] * lprec1.scale[j];
			} else
			if(lprec1.ch_sign[i] != 0)
				lprec1.mat[k].value = -d;
			else
				lprec1.mat[k].value = d;
			lprec1.row_end_valid = 0;
			lprec1.non_zeros++;
			if(lprec1.active != 0)
				Non_zeros = lprec1.non_zeros;
		}
	}

	public void set_obj_fn(lprec lprec1, double ad[])
	{
		for(int i = 1; i <= lprec1.columns; i++)
			set_mat(lprec1, 0, i, ad[i]);

	}

	public void str_set_obj_fn(lprec lprec1, String s)
	{
		double ad[] = new double[lprec1.columns + 1];
		int i = 0;
		for(StringTokenizer stringtokenizer = new StringTokenizer(s); stringtokenizer.hasMoreTokens() && i < lprec1.columns;)
		{
			i++;
			ad[i] = Double.valueOf(stringtokenizer.nextToken()).doubleValue();
		}

		if(i < lprec1.columns)
		{
			System.err.println("Not enough numbers in the string in str_set_obj_fn");
			System.exit(-1);
		}
		set_obj_fn(lprec1, ad);
	}

	public void add_constraint(lprec lprec1, double ad[], int word0, double d)
	{
		int aword0[] = new int[lprec1.columns + 1];
		for(int i = 1; i <= lprec1.columns; i++)
			if(ad[i] != 0.0D)
			{
				aword0[i] = 1;
				lprec1.non_zeros++;
			} else
			{
				aword0[i] = 0;
			}

		matrec amatrec[] = new matrec[lprec1.non_zeros];
		for(int j = 0; j < amatrec.length; j++)
			amatrec[j] = new matrec(0, 0.0D);

		inc_mat_space(lprec1, 0);
		lprec1.rows++;
		lprec1.sum++;
		inc_row_space(lprec1);
		if(lprec1.scaling_used != 0)
		{
			for(int k = lprec1.sum; k > lprec1.rows; k--)
				lprec1.scale[k] = lprec1.scale[k - 1];

			lprec1.scale[lprec1.rows] = 1.0D;
		}
		if(lprec1.names_used != 0)
			lprec1.row_name[lprec1.rows] = new String("r_" + lprec1.rows);
		if(lprec1.scaling_used != 0 && lprec1.columns_scaled != 0)
		{
			for(int l = 1; l <= lprec1.columns; l++)
				ad[l] *= lprec1.scale[lprec1.rows + l];

		}
		if(word0 == 2)
			lprec1.ch_sign[lprec1.rows] = 1;
		else
			lprec1.ch_sign[lprec1.rows] = 0;
		int i2 = 0;
		int j2 = 0;
		for(int i1 = 1; i1 <= lprec1.columns; i1++)
		{
			for(int l1 = j2; l1 < lprec1.col_end[i1]; l1++)
			{
				amatrec[i2].row_nr = lprec1.mat[l1].row_nr;
				amatrec[i2].value = lprec1.mat[l1].value;
				i2++;
			}

			if(aword0[i1] != 0)
			{
				if(lprec1.ch_sign[lprec1.rows] != 0)
					amatrec[i2].value = -ad[i1];
				else
					amatrec[i2].value = ad[i1];
				amatrec[i2].row_nr = lprec1.rows;
				i2++;
			}
			j2 = lprec1.col_end[i1];
			lprec1.col_end[i1] = i2;
		}

		lprec1.mat = amatrec;
		for(int j1 = lprec1.sum; j1 > lprec1.rows; j1--)
		{
			lprec1.orig_upbo[j1] = lprec1.orig_upbo[j1 - 1];
			lprec1.orig_lowbo[j1] = lprec1.orig_lowbo[j1 - 1];
			lprec1.basis[j1] = lprec1.basis[j1 - 1];
			lprec1.lower[j1] = lprec1.lower[j1 - 1];
			lprec1.must_be_int[j1] = lprec1.must_be_int[j1 - 1];
		}

		for(int k1 = 1; k1 <= lprec1.rows; k1++)
			if(lprec1.bas[k1] >= lprec1.rows)
				lprec1.bas[k1]++;

		if(word0 == 0 || word0 == 2)
			lprec1.orig_upbo[lprec1.rows] = lprec1.infinite;
		else
		if(word0 == 1)
		{
			lprec1.orig_upbo[lprec1.rows] = 0.0D;
		} else
		{
			System.err.print("Wrong constraint type\n");
			System.exit(-1);
		}
		lprec1.orig_lowbo[lprec1.rows] = 0.0D;
		if(word0 == 2 && d != 0.0D)
			lprec1.orig_rh[lprec1.rows] = -d;
		else
			lprec1.orig_rh[lprec1.rows] = d;
		lprec1.row_end_valid = 0;
		lprec1.bas[lprec1.rows] = lprec1.rows;
		lprec1.basis[lprec1.rows] = 1;
		lprec1.lower[lprec1.rows] = 1;
		if(lprec1.active != 0)
			set_globals(lprec1);
		lprec1.eta_valid = 0;
	}

	public void str_add_constraint(lprec lprec1, String s, int word0, double d)
	{
		int i = 0;
		double ad[] = new double[lprec1.columns + 1];
		for(StringTokenizer stringtokenizer = new StringTokenizer(s); stringtokenizer.hasMoreTokens() && i < lprec1.columns;)
		{
			i++;
			ad[i] = Double.valueOf(stringtokenizer.nextToken()).doubleValue();
		}

		add_constraint(lprec1, ad, word0, d);
	}

	public void del_constraint(lprec lprec1, int i)
	{
		if(i < 1 || i > lprec1.rows)
		{
			System.err.println("There is no constraint nr. " + i);
			System.exit(-1);
		}
		int k1 = 0;
		int l1 = 0;
		for(int j = 1; j <= lprec1.columns; j++)
		{
			for(int j1 = l1; j1 < lprec1.col_end[j]; j1++)
				if(lprec1.mat[j1].row_nr != i)
				{
					lprec1.mat[k1] = lprec1.mat[j1];
					if(lprec1.mat[k1].row_nr > i)
						lprec1.mat[k1].row_nr--;
					k1++;
				} else
				{
					lprec1.non_zeros--;
				}

			l1 = lprec1.col_end[j];
			lprec1.col_end[j] = k1;
		}

		for(int k = i; k < lprec1.rows; k++)
		{
			lprec1.orig_rh[k] = lprec1.orig_rh[k + 1];
			lprec1.ch_sign[k] = lprec1.ch_sign[k + 1];
			lprec1.bas[k] = lprec1.bas[k + 1];
			if(lprec1.names_used != 0)
				lprec1.row_name[k] = lprec1.row_name[k + 1];
		}

		for(int l = 1; l < lprec1.rows; l++)
			if(lprec1.bas[l] > i)
				lprec1.bas[l]--;

		for(int i1 = i; i1 < lprec1.sum; i1++)
		{
			lprec1.lower[i1] = lprec1.lower[i1 + 1];
			lprec1.basis[i1] = lprec1.basis[i1 + 1];
			lprec1.orig_upbo[i1] = lprec1.orig_upbo[i1 + 1];
			lprec1.orig_lowbo[i1] = lprec1.orig_lowbo[i1 + 1];
			lprec1.must_be_int[i1] = lprec1.must_be_int[i1 + 1];
			if(lprec1.scaling_used != 0)
				lprec1.scale[i1] = lprec1.scale[i1 + 1];
		}

		lprec1.rows--;
		lprec1.sum--;
		lprec1.row_end_valid = 0;
		if(lprec1.active != 0)
			set_globals(lprec1);
		lprec1.eta_valid = 0;
		lprec1.basis_valid = 0;
	}

	public void add_lag_con(lprec lprec1, double ad[], int word0, double d)
	{
		double d1 = 0.0D;
		if(word0 == 0 || word0 == 1)
			d1 = 1.0D;
		else
		if(word0 == 2)
			d1 = -1D;
		else
			System.err.print("con_type not implemented\n");
		lprec1.nr_lagrange++;
		if(lprec1.nr_lagrange == 1)
		{
			lprec1.lag_row = new double[lprec1.nr_lagrange][];
			lprec1.lag_rhs = new double[lprec1.nr_lagrange];
			lprec1.lambda = new double[lprec1.nr_lagrange];
			lprec1.lag_con_type = new int[lprec1.nr_lagrange];
			for(int i = 0; i < lprec1.nr_lagrange; i++)
			{
				lprec1.lag_rhs[i] = 0.0D;
				lprec1.lambda[i] = 0.0D;
				lprec1.lag_con_type[i] = 0;
			}

		} else
		{
			double ad1[][] = lprec1.lag_row;
			lprec1.lag_row = new double[lprec1.nr_lagrange][];
			System.arraycopy(ad1, 0, lprec1.lag_row, 0, ad1.length);
			double ad2[] = lprec1.lag_rhs;
			lprec1.lag_rhs = new double[lprec1.nr_lagrange];
			System.arraycopy(ad2, 0, lprec1.lag_rhs, 0, ad2.length);
			ad2 = lprec1.lambda;
			lprec1.lambda = new double[lprec1.nr_lagrange];
			System.arraycopy(ad2, 0, lprec1.lambda, 0, ad2.length);
			int aword0[] = lprec1.lag_con_type;
			lprec1.lag_con_type = new int[lprec1.nr_lagrange];
			System.arraycopy(aword0, 0, lprec1.lag_con_type, 0, aword0.length);
		}
		lprec1.lag_row[lprec1.nr_lagrange - 1] = new double[lprec1.columns + 1];
		lprec1.lag_rhs[lprec1.nr_lagrange - 1] = d * d1;
		for(int j = 1; j <= lprec1.columns; j++)
			lprec1.lag_row[lprec1.nr_lagrange - 1][j] = ad[j] * d1;

		lprec1.lambda[lprec1.nr_lagrange - 1] = 0.0D;
		lprec1.lag_con_type[lprec1.nr_lagrange - 1] = word0 == 1 ? 1 : 0;
	}

	public void str_add_lag_con(lprec lprec1, String s, int word0, double d)
	{
		int i = 0;
		double ad[] = new double[lprec1.columns + 1];
		for(StringTokenizer stringtokenizer = new StringTokenizer(s); stringtokenizer.hasMoreTokens() && i < lprec1.columns;)
		{
			i++;
			ad[i] = Double.valueOf(stringtokenizer.nextToken()).doubleValue();
		}

		if(i < lprec1.columns)
		{
			System.err.println("not enough value for str_add_lag_con");
			System.exit(-1);
		}
		add_lag_con(lprec1, ad, word0, d);
	}

	public void add_column(lprec lprec1, double ad[])
	{
		lprec1.columns++;
		lprec1.sum++;
		inc_col_space(lprec1);
		inc_mat_space(lprec1, lprec1.rows + 1);
		if(lprec1.scaling_used != 0)
		{
			for(int i = 0; i <= lprec1.rows; i++)
				ad[i] *= lprec1.scale[i];

			lprec1.scale[lprec1.sum] = 1.0D;
		}
		int k = lprec1.col_end[lprec1.columns - 1];
		for(int j = 0; j <= lprec1.rows; j++)
			if(ad[j] != 0.0D)
			{
				lprec1.mat[k].row_nr = j;
				if(lprec1.ch_sign[j] != 0)
					lprec1.mat[k].value = -ad[j];
				else
					lprec1.mat[k].value = ad[j];
				lprec1.non_zeros++;
				k++;
			}

		lprec1.col_end[lprec1.columns] = k;
		lprec1.orig_lowbo[lprec1.sum] = 0.0D;
		lprec1.orig_upbo[lprec1.sum] = lprec1.infinite;
		lprec1.lower[lprec1.sum] = 1;
		lprec1.basis[lprec1.sum] = 0;
		lprec1.must_be_int[lprec1.sum] = 0;
		if(lprec1.names_used != 0)
			lprec1.col_name[lprec1.columns] = new String("var_" + lprec1.columns);
		lprec1.row_end_valid = 0;
		if(lprec1.active != 0)
		{
			Sum = lprec1.sum;
			Columns = lprec1.columns;
			Non_zeros = lprec1.non_zeros;
		}
	}

	public void str_add_column(lprec lprec1, String s)
	{
		int i = 0;
		double ad[] = new double[lprec1.rows + 1];
		for(StringTokenizer stringtokenizer = new StringTokenizer(s); stringtokenizer.hasMoreTokens() && i < lprec1.rows;)
		{
			i++;
			ad[i] = Double.valueOf(stringtokenizer.nextToken()).doubleValue();
		}

		if(i < lprec1.rows)
		{
			System.err.println("Bad String in str_add_column");
			System.exit(-1);
		}
		add_column(lprec1, ad);
	}

	public void del_column(lprec lprec1, int i)
	{
		if(i > lprec1.columns || i < 1)
			System.err.print("Column out of range in del_column");
		for(int j = 1; j <= lprec1.rows; j++)
			if(lprec1.bas[j] == lprec1.rows + i)
				lprec1.basis_valid = 0;
			else
			if(lprec1.bas[j] > lprec1.rows + i)
				lprec1.bas[j]--;

		for(int k = lprec1.rows + i; k < lprec1.sum; k++)
		{
			if(lprec1.names_used != 0)
				lprec1.col_name[k - lprec1.rows] = lprec1.col_name[(k - lprec1.rows) + 1];
			lprec1.must_be_int[k] = lprec1.must_be_int[k + 1];
			lprec1.orig_upbo[k] = lprec1.orig_upbo[k + 1];
			lprec1.orig_lowbo[k] = lprec1.orig_lowbo[k + 1];
			lprec1.upbo[k] = lprec1.upbo[k + 1];
			lprec1.lowbo[k] = lprec1.lowbo[k + 1];
			lprec1.basis[k] = lprec1.basis[k + 1];
			lprec1.lower[k] = lprec1.lower[k + 1];
			if(lprec1.scaling_used != 0)
				lprec1.scale[k] = lprec1.scale[k + 1];
		}

		for(int l = 0; l < lprec1.nr_lagrange; l++)
		{
			for(int k1 = i; k1 <= lprec1.columns; k1++)
				lprec1.lag_row[l][k1] = lprec1.lag_row[l][k1 + 1];

		}

		int i2 = lprec1.col_end[i - 1];
		int l1 = lprec1.col_end[i];
		int j2 = l1 - i2;
		for(int i1 = l1; i1 < lprec1.non_zeros; i1++)
		{
			lprec1.mat[i2] = lprec1.mat[i1];
			i2++;
		}

		for(int j1 = i; j1 < lprec1.columns; j1++)
			lprec1.col_end[j1] = lprec1.col_end[j1 + 1] - j2;

		lprec1.non_zeros -= j2;
		lprec1.row_end_valid = 0;
		lprec1.eta_valid = 0;
		lprec1.sum--;
		lprec1.columns--;
		if(lprec1.active != 0)
			set_globals(lprec1);
	}

	public void set_upbo(lprec lprec1, int i, double d)
	{
		if(i > lprec1.columns || i < 1)
			System.err.print("Column out of range");
		if(lprec1.scaling_used != 0)
			d /= lprec1.scale[lprec1.rows + i];
		if(d < lprec1.orig_lowbo[lprec1.rows + i])
			System.err.print("Upperbound must be >= lowerbound");
		lprec1.eta_valid = 0;
		lprec1.orig_upbo[lprec1.rows + i] = d;
	}

	public void set_lowbo(lprec lprec1, int i, double d)
	{
		if(i > lprec1.columns || i < 1)
			System.err.print("Column out of range");
		if(lprec1.scaling_used != 0)
			d /= lprec1.scale[lprec1.rows + i];
		if(d > lprec1.orig_upbo[lprec1.rows + i])
			System.err.print("Upperbound must be >= lowerbound");
		lprec1.eta_valid = 0;
		lprec1.orig_lowbo[lprec1.rows + i] = d;
	}

	public void set_int(lprec lprec1, int i, int word0)
	{
		if(i > lprec1.columns || i < 1)
			System.err.print("Column out of range");
		lprec1.must_be_int[lprec1.rows + i] = word0;
		if(word0 == 1 && lprec1.columns_scaled != 0)
			unscale_columns(lprec1);
	}

	public void set_rh(lprec lprec1, int i, double d)
	{
		if(i > lprec1.rows || i < 0)
			System.err.print("Row out of Range");
		if(i == 0)
		{
			System.err.println("Warning: attempt to set RHS of objective function, ignored");
			return;
		}
		if(lprec1.scaling_used != 0)
		{
			if(lprec1.ch_sign[i] != 0)
				lprec1.orig_rh[i] = -d * lprec1.scale[i];
			else
				lprec1.orig_rh[i] = d * lprec1.scale[i];
		} else
		if(lprec1.ch_sign[i] != 0)
			lprec1.orig_rh[i] = -d;
		else
			lprec1.orig_rh[i] = d;
		lprec1.eta_valid = 0;
	}

	public void set_rh_vec(lprec lprec1, double ad[])
	{
		if(lprec1.scaling_used != 0)
		{
			for(int i = 1; i <= lprec1.rows; i++)
				if(lprec1.ch_sign[i] != 0)
					lprec1.orig_rh[i] = -ad[i] * lprec1.scale[i];
				else
					lprec1.orig_rh[i] = ad[i] * lprec1.scale[i];

		} else
		{
			for(int j = 1; j <= lprec1.rows; j++)
				if(lprec1.ch_sign[j] != 0)
					lprec1.orig_rh[j] = -ad[j];
				else
					lprec1.orig_rh[j] = ad[j];

		}
		lprec1.eta_valid = 0;
	}

	public void str_set_rh_vec(lprec lprec1, String s)
	{
		int i = 0;
		double ad[] = new double[lprec1.rows + 1];
		for(StringTokenizer stringtokenizer = new StringTokenizer(s); stringtokenizer.hasMoreTokens() && i < lprec1.rows;)
		{
			i++;
			ad[i] = Double.valueOf(stringtokenizer.nextToken()).doubleValue();
		}

		set_rh_vec(lprec1, ad);
	}

	public void set_maxim(lprec lprec1)
	{
		if(lprec1.maximise == 0)
		{
			for(int i = 0; i < lprec1.non_zeros; i++)
				if(lprec1.mat[i].row_nr == 0)
					lprec1.mat[i].value *= -1D;

			lprec1.eta_valid = 0;
		}
		lprec1.maximise = 1;
		lprec1.ch_sign[0] = 1;
		if(lprec1.active != 0)
			Maximise = 1;
	}

	public void set_minim(lprec lprec1)
	{
		if(lprec1.maximise == 1)
		{
			for(int i = 0; i < lprec1.non_zeros; i++)
				if(lprec1.mat[i].row_nr == 0)
					lprec1.mat[i].value = -lprec1.mat[i].value;

			lprec1.eta_valid = 0;
		}
		lprec1.maximise = 0;
		lprec1.ch_sign[0] = 0;
		if(lprec1.active != 0)
			Maximise = 0;
	}

	public void set_constr_type(lprec lprec1, int i, int word0)
	{
		if(i > lprec1.rows || i < 1)
			System.err.print("Row out of Range");
		if(word0 == 1)
		{
			lprec1.orig_upbo[i] = 0.0D;
			lprec1.basis_valid = 0;
			if(lprec1.ch_sign[i] != 0)
			{
				for(int j = 0; j < lprec1.non_zeros; j++)
					if(lprec1.mat[j].row_nr == i)
						lprec1.mat[j].value *= -1D;

				lprec1.eta_valid = 0;
				lprec1.ch_sign[i] = 0;
				if(lprec1.orig_rh[i] != 0.0D)
					lprec1.orig_rh[i] *= -1D;
			}
		} else
		if(word0 == 0)
		{
			lprec1.orig_upbo[i] = lprec1.infinite;
			lprec1.basis_valid = 0;
			if(lprec1.ch_sign[i] != 0)
			{
				for(int k = 0; k < lprec1.non_zeros; k++)
					if(lprec1.mat[k].row_nr == i)
						lprec1.mat[k].value *= -1D;

				lprec1.eta_valid = 0;
				lprec1.ch_sign[i] = 0;
				if(lprec1.orig_rh[i] != 0.0D)
					lprec1.orig_rh[i] *= -1D;
			}
		} else
		if(word0 == 2)
		{
			lprec1.orig_upbo[i] = lprec1.infinite;
			lprec1.basis_valid = 0;
			if(lprec1.ch_sign[i] == 0)
			{
				for(int l = 0; l < lprec1.non_zeros; l++)
					if(lprec1.mat[l].row_nr == i)
						lprec1.mat[l].value *= -1D;

				lprec1.eta_valid = 0;
				lprec1.ch_sign[i] = 1;
				if(lprec1.orig_rh[i] != 0.0D)
					lprec1.orig_rh[i] *= -1D;
			}
		} else
		{
			System.err.print("Constraint type not (yet) implemented");
		}
	}

	public double mat_elm(lprec lprec1, int i, int j)
	{
		if(i < 0 || i > lprec1.rows)
			System.err.print("Row out of range in mat_elm");
		if(j < 1 || j > lprec1.columns)
			System.err.print("Column out of range in mat_elm");
		double d = 0.0D;
		int k;
		for(k = lprec1.col_end[j - 1]; lprec1.mat[k].row_nr != i && k < lprec1.col_end[j]; k++);
		if(k != lprec1.col_end[j])
		{
			d = lprec1.mat[k].value;
			if(lprec1.ch_sign[i] != 0)
				d = -d;
			if(lprec1.scaling_used != 0)
				d /= lprec1.scale[i] * lprec1.scale[lprec1.rows + j];
		}
		return d;
	}

	public void get_row(lprec lprec1, int i, double ad[])
	{
		if(i < 0 || i > lprec1.rows)
			System.err.print("Row nr. out of range in get_row");
		for(int j = 1; j <= lprec1.columns; j++)
		{
			ad[j] = 0.0D;
			for(int l = lprec1.col_end[j - 1]; l < lprec1.col_end[j]; l++)
				if(lprec1.mat[l].row_nr == i)
					ad[j] = lprec1.mat[l].value;

			if(lprec1.scaling_used != 0)
				ad[j] /= lprec1.scale[lprec1.rows + j] * lprec1.scale[i];
		}

		if(lprec1.ch_sign[i] != 0)
		{
			for(int k = 0; k <= lprec1.columns; k++)
				if(ad[k] != 0.0D)
					ad[k] = -ad[k];

		}
	}

	public void get_column(lprec lprec1, int i, double ad[])
	{
		if(i < 1 || i > lprec1.columns)
			System.err.print("Col. nr. out of range in get_column");
		for(int j = 0; j <= lprec1.rows; j++)
			ad[j] = 0.0D;

		for(int k = lprec1.col_end[i - 1]; k < lprec1.col_end[i]; k++)
			ad[lprec1.mat[k].row_nr] = lprec1.mat[k].value;

		for(int l = 0; l <= lprec1.rows; l++)
			if(ad[l] != 0.0D)
			{
				if(lprec1.ch_sign[l] != 0)
					ad[l] *= -1D;
				if(lprec1.scaling_used != 0)
					ad[l] /= lprec1.scale[l] * lprec1.scale[lprec1.rows + i];
			}

	}

	public void get_reduced_costs(lprec lprec1, double ad[])
	{
		if(lprec1.basis_valid == 0)
			System.err.print("Not a valid basis in get_reduced_costs");
		set_globals(lprec1);
		if(lprec1.eta_valid == 0)
			invert();
		for(int j = 1; j <= lprec1.sum; j++)
			ad[j] = 0.0D;

		ad[0] = 1.0D;
		btran(ad);
		for(int k = 1; k <= lprec1.columns; k++)
		{
			int i = lprec1.rows + k;
			if(Basis[i] == 0 && Upbo[i] > 0.0D)
			{
				double d = 0.0D;
				for(int i1 = Col_end[k - 1]; i1 < Col_end[k]; i1++)
					d += ad[Mat[i1].row_nr] * Mat[i1].value;

				ad[i] = d;
			}
		}

		for(int l = 1; l <= Sum; l++)
			ad[l] = Util.round(ad[l], Epsd);

	}

	int is_feasible(lprec lprec1, double ad[])
	{
		if(lprec1.scaling_used != 0)
		{
			for(int i = lprec1.rows + 1; i <= lprec1.sum; i++)
				if(ad[i - lprec1.rows] < lprec1.orig_lowbo[i] * lprec1.scale[i] || ad[i - lprec1.rows] > lprec1.orig_upbo[i] * lprec1.scale[i])
					return 0;

		} else
		{
			for(int j = lprec1.rows + 1; j <= lprec1.sum; j++)
				if(ad[j - lprec1.rows] < lprec1.orig_lowbo[j] || ad[j - lprec1.rows] > lprec1.orig_upbo[j])
					return 0;

		}
		double ad1[] = new double[lprec1.rows + 1];
		for(int k = 0; k <= lprec1.rows; k++)
			ad1[k] = 0.0D;

		for(int l = 1; l <= lprec1.columns; l++)
		{
			for(int j1 = lprec1.col_end[l - 1]; j1 < lprec1.col_end[l]; j1++)
				ad1[lprec1.mat[j1].row_nr] += lprec1.mat[j1].value * ad[l];

		}

		for(int i1 = 1; i1 <= lprec1.rows; i1++)
		{
			double d = lprec1.orig_rh[i1] - ad1[i1];
			d = Util.round(d, 0.001D);
			if(lprec1.orig_upbo[i1] == 0.0D && d != 0.0D || d < 0.0D)
				return 0;
		}

		return 1;
	}

	int column_in_lp(lprec lprec1, double ad[])
	{
		if(lprec1.scaling_used != 0)
		{
			for(int i = 1; i <= lprec1.columns; i++)
			{
				boolean flag = true;
				for(int k = lprec1.col_end[i - 1]; flag && k < lprec1.col_end[i]; k++)
				{
					double d = lprec1.mat[k].value;
					if(lprec1.ch_sign[lprec1.mat[k].row_nr] != 0)
						d = -d;
					d /= lprec1.scale[lprec1.rows + i];
					d /= lprec1.scale[lprec1.mat[k].row_nr];
					d -= ad[lprec1.mat[k].row_nr];
					if(Math.abs(d) > 0.001D)
						flag = false;
				}

				if(flag)
					return 1;
			}

		} else
		{
			for(int j = 1; j <= lprec1.columns; j++)
			{
				boolean flag1 = true;
				for(int l = lprec1.col_end[j - 1]; flag1 && l < lprec1.col_end[j]; l++)
				{
					double d1 = lprec1.mat[l].value;
					if(lprec1.ch_sign[lprec1.mat[l].row_nr] != 0)
						d1 *= -1D;
					d1 -= ad[lprec1.mat[l].row_nr];
					if(Math.abs(d1) > 0.001D)
						flag1 = false;
				}

				if(flag1)
					return 1;
			}

		}
		return 0;
	}

	public void print_lp(lprec lprec1)
	{
		double ad[] = new double[(lprec1.rows + 1) * lprec1.columns];
		for(int i = 0; i < ad.length; i++)
			ad[i] = 0.0D;

		for(int j = 1; j <= lprec1.columns; j++)
		{
			for(int l1 = lprec1.col_end[j - 1]; l1 < lprec1.col_end[j]; l1++)
				ad[(j - 1) * (lprec1.rows + 1) + lprec1.mat[l1].row_nr] = lprec1.mat[l1].value;

		}

		System.out.println("problem name: " + lprec1.lp_name);
		System.out.print("          ");
		for(int i2 = 1; i2 <= lprec1.columns; i2++)
			if(lprec1.names_used != 0)
				System.out.print(lprec1.col_name[i2]);
			else
				System.out.print("Var[" + i2 + "] ");

		if(lprec1.maximise != 0)
		{
			System.out.print("\nMaximise  ");
			for(int j2 = 0; j2 < lprec1.columns; j2++)
				System.out.print(" " + -ad[j2 * (lprec1.rows + 1)] + " ");

		} else
		{
			System.out.print("\nMinimize  ");
			for(int k2 = 0; k2 < lprec1.columns; k2++)
				System.out.print(" " + ad[k2 * (lprec1.rows + 1)] + " ");

		}
		System.out.print("\n");
		for(int k = 1; k <= lprec1.rows; k++)
		{
			if(lprec1.names_used != 0)
				System.out.print(lprec1.row_name[k]);
			else
				System.out.print("Row[" + k + "]  ");
			for(int l2 = 0; l2 < lprec1.columns; l2++)
				if(lprec1.ch_sign[k] != 0 && ad[l2 * (lprec1.rows + 1) + k] != 0.0D)
					System.out.print(-ad[l2 * (lprec1.rows + 1) + k] + " ");
				else
					System.out.print(ad[l2 * (lprec1.rows + 1) + k] + " ");

			if(lprec1.orig_upbo[k] == lprec1.infinite)
			{
				if(lprec1.ch_sign[k] != 0)
					System.out.print(">= ");
				else
					System.out.print("<= ");
			} else
			{
				System.out.print(" = ");
			}
			if(lprec1.ch_sign[k] != 0)
				System.out.println(-lprec1.orig_rh[k]);
			else
				System.out.println(lprec1.orig_rh[k]);
		}

		System.out.print("Type      ");
		for(int l = 1; l <= lprec1.columns; l++)
			if(lprec1.must_be_int[lprec1.rows + l] == 1)
				System.out.print("     Int ");
			else
				System.out.print("    double ");

		System.out.print("\nupbo      ");
		for(int i1 = 1; i1 <= lprec1.columns; i1++)
			if(lprec1.orig_upbo[lprec1.rows + i1] == lprec1.infinite)
				System.out.print("     Inf ");
			else
				System.out.print(lprec1.orig_upbo[lprec1.rows + i1] + " ");

		System.out.print("\nlowbo     ");
		for(int j1 = 1; j1 <= lprec1.columns; j1++)
			System.out.print(lprec1.orig_lowbo[lprec1.rows + j1] + " ");

		System.out.print("\n");
		for(int k1 = 0; k1 < lprec1.nr_lagrange; k1++)
		{
			System.out.print("lag[" + k1 + "]  ");
			for(int i3 = 1; i3 <= lprec1.columns; i3++)
				System.out.print(lprec1.lag_row[k1][i3] + " ");

			if(lprec1.orig_upbo[k1] == lprec1.infinite)
				if(lprec1.lag_con_type[k1] == 2)
					System.out.print(">= ");
				else
				if(lprec1.lag_con_type[k1] == 0)
					System.out.print("<= ");
				else
				if(lprec1.lag_con_type[k1] == 1)
					System.out.print(" = ");
			System.out.println(lprec1.lag_rhs[k1]);
		}

	}

	public void set_row_name(lprec lprec1, int i, String s)
	{
		if(lprec1.names_used == 0)
		{
			lprec1.row_name = new String[lprec1.rows_alloc + 1];
			lprec1.col_name = new String[lprec1.columns_alloc + 1];
			lprec1.names_used = 1;
			for(int j = 0; j <= lprec1.rows; j++)
				lprec1.row_name[j] = new String("r_" + j);

			for(int k = 1; k <= lprec1.columns; k++)
				lprec1.col_name[k] = new String("var_" + k);

		}
		lprec1.row_name[i] = s;
	}

	public void set_col_name(lprec lprec1, int i, String s)
	{
		if(lprec1.names_used == 0)
		{
			lprec1.row_name = new String[lprec1.rows_alloc + 1];
			lprec1.col_name = new String[lprec1.columns_alloc + 1];
			lprec1.names_used = 1;
			for(int j = 0; j <= lprec1.rows; j++)
				lprec1.row_name[j] = new String("r_" + j);

			for(int k = 1; k <= lprec1.columns; k++)
				lprec1.col_name[k] = new String("var_" + k);

		}
		lprec1.col_name[i] = s;
	}

	private double minmax_to_scale(double d, double d1)
	{
		if(d == 0.0D || d1 == 0.0D)
		{
			return 1.0D;
		} else
		{
			double d2 = 1.0D / Math.pow(2.7182818284590451D, (Math.log(d) + Math.log(d1)) / 2D);
			return d2;
		}
	}

	public void unscale_columns(lprec lprec1)
	{
		for(int l = 1; l <= lprec1.columns; l++)
		{
			for(int i = lprec1.col_end[l - 1]; i < lprec1.col_end[l]; i++)
				lprec1.mat[i].value /= lprec1.scale[lprec1.rows + l];

		}

		for(int j = lprec1.rows + 1; j < lprec1.sum; j++)
		{
			if(lprec1.orig_lowbo[j] != 0.0D)
				lprec1.orig_lowbo[j] *= lprec1.scale[j];
			if(lprec1.orig_upbo[j] != lprec1.infinite)
				lprec1.orig_upbo[j] *= lprec1.scale[j];
		}

		for(int k = lprec1.rows + 1; k <= lprec1.sum; k++)
			lprec1.scale[k] = 1.0D;

		lprec1.columns_scaled = 0;
		lprec1.eta_valid = 0;
	}

	public void unscale(lprec lprec1)
	{
		if(lprec1.scaling_used != 0)
		{
			for(int i1 = 1; i1 <= lprec1.columns; i1++)
			{
				for(int i = lprec1.col_end[i1 - 1]; i < lprec1.col_end[i1]; i++)
					lprec1.mat[i].value /= lprec1.scale[lprec1.rows + i1];

			}

			for(int j = lprec1.rows + 1; j < lprec1.sum; j++)
			{
				if(lprec1.orig_lowbo[j] != 0.0D)
					lprec1.orig_lowbo[j] *= lprec1.scale[j];
				if(lprec1.orig_upbo[j] != lprec1.infinite)
					lprec1.orig_upbo[j] *= lprec1.scale[j];
			}

			for(int j1 = 1; j1 <= lprec1.columns; j1++)
			{
				for(int k = lprec1.col_end[j1 - 1]; k < lprec1.col_end[j1]; k++)
					lprec1.mat[k].value /= lprec1.scale[lprec1.mat[k].row_nr];

			}

			for(int l = 0; l <= lprec1.rows; l++)
				lprec1.orig_rh[l] /= lprec1.scale[l];

			lprec1.scaling_used = 0;
			lprec1.eta_valid = 0;
		}
	}

	public void auto_scale(lprec lprec1)
	{
		if(lprec1.scaling_used == 0)
		{
			lprec1.scale = new double[lprec1.sum_alloc + 1];
			for(int i = 0; i <= lprec1.sum; i++)
				lprec1.scale[i] = 1.0D;

		}
		double ad[] = new double[lprec1.rows + 1];
		double ad1[] = new double[lprec1.rows + 1];
		double ad2[] = new double[lprec1.sum + 1];
		for(int j = 0; j <= lprec1.rows; j++)
		{
			ad[j] = 0.0D;
			ad1[j] = lprec1.infinite;
		}

		for(int k2 = 1; k2 <= lprec1.columns; k2++)
		{
			for(int k = lprec1.col_end[k2 - 1]; k < lprec1.col_end[k2]; k++)
			{
				int k3 = lprec1.mat[k].row_nr;
				double d = Math.abs(lprec1.mat[k].value);
				if(d != 0.0D)
				{
					ad[k3] = Math.max(ad[k3], d);
					ad1[k3] = Math.min(ad1[k3], d);
				}
			}

		}

		for(int l = 0; l <= lprec1.rows; l++)
		{
			ad2[l] = minmax_to_scale(ad1[l], ad[l]);
			lprec1.scale[l] *= ad2[l];
		}

		for(int l2 = 1; l2 <= lprec1.columns; l2++)
		{
			for(int i1 = lprec1.col_end[l2 - 1]; i1 < lprec1.col_end[l2]; i1++)
				lprec1.mat[i1].value *= ad2[lprec1.mat[i1].row_nr];

		}

		for(int j1 = 0; j1 <= lprec1.rows; j1++)
			lprec1.orig_rh[j1] *= ad2[j1];

		int word0 = 0;
		for(int k1 = lprec1.rows + 1; word0 == 0 && k1 <= lprec1.sum; k1++)
			word0 = lprec1.must_be_int[k1];

		if(word0 == 0)
		{
			for(int i3 = 1; i3 <= lprec1.columns; i3++)
			{
				double d1 = 0.0D;
				double d2 = lprec1.infinite;
				for(int l1 = lprec1.col_end[i3 - 1]; l1 < lprec1.col_end[i3]; l1++)
					if(lprec1.mat[l1].value != 0.0D)
					{
						d1 = Math.max(d1, Math.abs(lprec1.mat[l1].value));
						d2 = Math.min(d2, Math.abs(lprec1.mat[l1].value));
					}

				ad2[lprec1.rows + i3] = minmax_to_scale(d2, d1);
				lprec1.scale[lprec1.rows + i3] *= ad2[lprec1.rows + i3];
			}

			for(int j3 = 1; j3 <= lprec1.columns; j3++)
			{
				for(int i2 = lprec1.col_end[j3 - 1]; i2 < lprec1.col_end[j3]; i2++)
					lprec1.mat[i2].value *= ad2[lprec1.rows + j3];

			}

			for(int j2 = lprec1.rows + 1; j2 < lprec1.sum; j2++)
			{
				if(lprec1.orig_lowbo[j2] != 0.0D)
					lprec1.orig_lowbo[j2] /= ad2[j2];
				if(lprec1.orig_upbo[j2] != lprec1.infinite)
					lprec1.orig_upbo[j2] /= ad2[j2];
			}

			lprec1.columns_scaled = 1;
		}
		lprec1.scaling_used = 1;
		lprec1.eta_valid = 0;
	}

	public void reset_basis(lprec lprec1)
	{
		lprec1.basis_valid = 0;
	}

	public void print_solution(lprec lprec1)
	{
		System.out.println("Value of objective function: " + lprec1.best_solution[0]);
		for(int i = 1; i <= lprec1.columns; i++)
			if(lprec1.names_used != 0)
				System.out.println(lprec1.col_name[i] + " " + lprec1.best_solution[lprec1.rows + i]);
			else
				System.out.println("Var [" + i + "]  " + lprec1.best_solution[lprec1.rows + i]);

		if(lprec1.verbose != 0)
		{
			System.out.print("\nActual values of the constraints:\n");
			for(int j = 1; j <= lprec1.rows; j++)
				if(lprec1.names_used != 0)
					System.out.println(lprec1.row_name[j] + " " + lprec1.best_solution[j]);
				else
					System.out.println("Row [" + j + "]  " + " " + lprec1.best_solution[j]);

		}
		if(lprec1.verbose != 0 || lprec1.print_duals != 0)
		{
			if(lprec1.max_level != 1)
				System.out.print("These are the duals from the node that gave the optimal solution.\n");
			else
				System.out.print("\nDual values:\n");
			for(int k = 1; k <= lprec1.rows; k++)
				if(lprec1.names_used != 0)
					System.out.println(lprec1.row_name[k] + " " + lprec1.duals[k]);
				else
					System.out.println("Row [" + k + "]  " + lprec1.duals[k]);

		}
	}

	public void write_LP(lprec lprec1, PrintStream printstream)
	{
		double ad[] = new double[lprec1.columns + 1];
		if(lprec1.maximise != 0)
			printstream.print("max:");
		else
			printstream.print("min:");
		get_row(lprec1, 0, ad);
		for(int i = 1; i <= lprec1.columns; i++)
			if(ad[i] != 0.0D)
			{
				if(ad[i] == -1D)
					printstream.print(" -");
				else
				if(ad[i] == 1.0D)
					printstream.print(" +");
				else
					printstream.print(ad[i]);
				if(lprec1.names_used != 0)
					printstream.print(lprec1.col_name[i]);
				else
					printstream.print("x" + i);
			}

		printstream.print(";\n");
		for(int i1 = 1; i1 <= lprec1.rows; i1++)
		{
			if(lprec1.names_used != 0)
				printstream.print(lprec1.row_name[i1]);
			get_row(lprec1, i1, ad);
			for(int j = 1; j <= lprec1.columns; j++)
				if(ad[j] != 0.0D)
				{
					if(ad[j] == -1D)
						printstream.print(" -");
					else
					if(ad[j] == 1.0D)
						printstream.print(" +");
					else
						printstream.print(" " + ad[j] + " ");
					if(lprec1.names_used != 0)
						printstream.print(lprec1.col_name[j]);
					else
						printstream.print("x" + j);
				}

			if(lprec1.orig_upbo[i1] == 0.0D)
				printstream.print(" =");
			else
			if(lprec1.ch_sign[i1] != 0)
				printstream.print(" >");
			else
				printstream.print(" <");
			if(lprec1.ch_sign[i1] != 0)
				printstream.println(" " + -lprec1.orig_rh[i1]);
			else
				printstream.println(" " + lprec1.orig_rh[i1]);
		}

		for(int k = lprec1.rows + 1; k <= lprec1.sum; k++)
		{
			if(lprec1.orig_lowbo[k] != 0.0D)
				if(lprec1.names_used != 0)
					printstream.println(lprec1.col_name[k - lprec1.rows] + ">" + lprec1.orig_lowbo[k] + ";");
				else
					printstream.print("x" + (k - lprec1.rows) + " > " + lprec1.orig_lowbo[k] + ";");
			if(lprec1.orig_upbo[k] != lprec1.infinite)
				if(lprec1.names_used != 0)
					printstream.println(lprec1.col_name[k - lprec1.rows] + " < " + lprec1.orig_upbo[k] + ";");
				else
					printstream.println("x" + (k - lprec1.rows) + " < " + lprec1.orig_upbo[k] + ";");
		}

		int l;
		for(l = 1; lprec1.must_be_int[lprec1.rows + l] == 0 && l <= lprec1.columns; l++);
		if(l <= lprec1.columns)
		{
			if(lprec1.names_used != 0)
				printstream.print("\nint " + lprec1.col_name[l]);
			else
				printstream.print("\nint x" + l);
			for(l++; l <= lprec1.columns; l++)
				if(lprec1.must_be_int[lprec1.rows + l] != 0)
					if(lprec1.names_used != 0)
						printstream.print("," + lprec1.col_name[l]);
					else
						printstream.print(", x" + l);

			printstream.print(";\n");
		}
	}

	public void print_duals(lprec lprec1)
	{
		for(int i = 1; i <= lprec1.rows; i++)
			if(lprec1.names_used != 0)
				System.out.println(lprec1.row_name[i] + " [" + i + "] " + lprec1.duals[i]);
			else
				System.out.println("Dual       [" + i + "] " + lprec1.duals[i]);

	}

	public void print_scales(lprec lprec1)
	{
		if(lprec1.scaling_used != 0)
		{
			for(int i = 0; i <= lprec1.rows; i++)
				System.out.println("Row[" + i + "]    scaled at " + lprec1.scale[i]);

			for(int j = 1; j <= lprec1.columns; j++)
				System.out.println("Column[" + j + "] scaled at " + lprec1.scale[lprec1.rows + j]);

		}
	}

	private void print_indent()
	{
		System.out.print(Level);
		if(Level < 50)
		{
			for(int i = Level; i > 0; i--)
				System.out.print("--");

		} else
		{
			System.out.print(" *** too deep ***");
		}
		System.out.print("> ");
	}

	public void debug_print_solution()
	{
		if(Lp.debug != 0)
		{
			for(int i = Rows + 1; i <= Sum; i++)
			{
				print_indent();
				if(Lp.names_used != 0)
					System.out.println(Lp.col_name[i - Rows] + " " + Solution[i]);
				else
					System.out.println("Var[" + (i - Rows) + "]   " + Solution[i]);
			}

		}
	}

	public void debug_print_bounds(double ad[], double ad1[])
	{
		if(Lp.debug != 0)
		{
			for(int i = Rows + 1; i <= Sum; i++)
			{
				if(ad1[i] != 0.0D)
				{
					print_indent();
					if(Lp.names_used != 0)
						System.out.println(Lp.col_name[i - Rows] + " > " + ad1[i]);
					else
						System.out.print("Var[" + (i - Rows) + "]  > " + ad1[i]);
				}
				if(ad[i] != Infinite)
				{
					print_indent();
					if(Lp.names_used != 0)
						System.out.println(Lp.col_name[i - Rows] + " < " + ad[i]);
					else
						System.out.println("Var[" + (i - Rows) + "]  < " + ad[i]);
				}
			}

		}
	}

	public void debug_print(String s)
	{
		if(Lp.debug != 0)
		{
			print_indent();
			System.out.print(s);
		}
	}

	void set_globals(lprec lprec1)
	{
		if(Lp != null)
			Lp.active = 0;
		Lp = lprec1;
		Rows = lprec1.rows;
		Columns = lprec1.columns;
		Sum = Rows + Columns;
		Non_zeros = lprec1.non_zeros;
		Mat = lprec1.mat;
		Col_no = lprec1.col_no;
		Col_end = lprec1.col_end;
		Row_end = lprec1.row_end;
		Rh = lprec1.rh;
		Rhs = lprec1.rhs;
		Orig_rh = lprec1.orig_rh;
		Must_be_int = lprec1.must_be_int;
		Orig_upbo = lprec1.orig_upbo;
		Orig_lowbo = lprec1.orig_lowbo;
		Upbo = lprec1.upbo;
		Lowbo = lprec1.lowbo;
		Bas = lprec1.bas;
		Basis = lprec1.basis;
		Lower = lprec1.lower;
		Eta_alloc = lprec1.eta_alloc;
		Eta_size = lprec1.eta_size;
		Num_inv = lprec1.num_inv;
		Eta_value = lprec1.eta_value;
		Eta_row_nr = lprec1.eta_row_nr;
		Eta_col_end = lprec1.eta_col_end;
		Solution = lprec1.solution;
		Best_solution = lprec1.best_solution;
		Infinite = lprec1.infinite;
		Epsilon = lprec1.epsilon;
		Epsb = lprec1.epsb;
		Epsd = lprec1.epsd;
		Epsel = lprec1.epsel;
		TREJ = TREJ;
		TINV = TINV;
		Maximise = lprec1.maximise;
		Floor_first = lprec1.floor_first;
		lprec1.active = 1;
	}

	private void ftran(int i, int j, double ad[])
	{
		for(int k = i; k <= j; k++)
		{
			int j1 = Eta_col_end[k] - 1;
			int k1 = Eta_row_nr[j1];
			double d = ad[k1];
			if(d != 0.0D)
			{
				for(int i1 = Eta_col_end[k - 1]; i1 < j1; i1++)
					ad[Eta_row_nr[i1]] += d * Eta_value[i1];

			}
			ad[k1] *= Eta_value[j1];
		}

		for(int l = 0; l <= Rows; l++)
			Util.round(ad[l], Epsel);

	}

	private void btran(double ad[])
	{
		for(int i = Eta_size; i >= 1; i--)
		{
			double d = 0.0D;
			int k = Eta_col_end[i] - 1;
			for(int j = Eta_col_end[i - 1]; j <= k; j++)
				d += ad[Eta_row_nr[j]] * Eta_value[j];

			d = Util.round(d, Epsel);
			ad[Eta_row_nr[k]] = d;
		}

	}

	static int Isvalid(lprec lprec1)
	{
		if(lprec1.row_end_valid == 0)
		{
			int ai3[] = new int[lprec1.rows + 1];
			int ai[] = new int[lprec1.rows + 1];
			for(int i = 0; i <= lprec1.rows; i++)
			{
				ai3[i] = 0;
				ai[i] = 0;
			}

			for(int j = 0; j < lprec1.non_zeros; j++)
				ai[lprec1.mat[j].row_nr]++;

			lprec1.row_end[0] = 0;
			for(int k = 1; k <= lprec1.rows; k++)
				lprec1.row_end[k] = lprec1.row_end[k - 1] + ai[k];

			for(int l = 1; l <= lprec1.columns; l++)
			{
				for(int i2 = lprec1.col_end[l - 1]; i2 < lprec1.col_end[l]; i2++)
				{
					int k2 = lprec1.mat[i2].row_nr;
					if(k2 != 0)
					{
						ai3[k2]++;
						lprec1.col_no[lprec1.row_end[k2 - 1] + ai3[k2]] = l;
					}
				}

			}

			lprec1.row_end_valid = 1;
		}
		if(lprec1.valid != 0)
			return 1;
		int ai1[] = new int[lprec1.rows + 1];
		for(int i1 = 0; i1 <= lprec1.rows; i1++)
			ai1[i1] = 0;

		int ai2[] = new int[lprec1.columns + 1];
		for(int j1 = 0; j1 <= lprec1.columns; j1++)
			ai2[j1] = 0;

		for(int k1 = 1; k1 <= lprec1.columns; k1++)
		{
			for(int j2 = lprec1.col_end[k1 - 1]; j2 < lprec1.col_end[k1]; j2++)
			{
				ai2[k1]++;
				ai1[lprec1.mat[j2].row_nr]++;
			}

		}

		for(int l1 = 1; l1 <= lprec1.columns; l1++)
			if(ai2[l1] == 0)
				if(lprec1.names_used != 0)
					System.err.print("Warning: Variable " + lprec1.col_name[l1] + " not used in any constraints\n");
				else
					System.err.print("Warning: Variable " + l1 + " not used in any constaints\n");

		lprec1.valid = 1;
		return 1;
	}

	private void resize_eta()
	{
		Eta_alloc *= 2;
		double ad[] = Eta_value;
		Eta_value = new double[Eta_alloc];
		System.arraycopy(ad, 0, Eta_value, 0, ad.length);
		Lp.eta_value = Eta_value;
		int ai[] = Eta_row_nr;
		Eta_row_nr = new int[Eta_alloc];
		System.arraycopy(ai, 0, Eta_row_nr, 0, ai.length);
		Lp.eta_row_nr = Eta_row_nr;
	}

	private void condensecol(int i, double ad[])
	{
		int k = Eta_col_end[Eta_size];
		if(k + Rows + 2 > Eta_alloc)
			resize_eta();
		for(int j = 0; j <= Rows; j++)
			if(j != i && ad[j] != 0.0D)
			{
				Eta_row_nr[k] = j;
				Eta_value[k] = ad[j];
				k++;
			}

		Eta_row_nr[k] = i;
		Eta_value[k] = ad[i];
		k++;
		Eta_col_end[Eta_size + 1] = k;
	}

	private void addetacol()
	{
		int j = Eta_col_end[Eta_size];
		Eta_size++;
		int k = Eta_col_end[Eta_size];
		double d = 1.0D / Eta_value[k - 1];
		Eta_value[k - 1] = d;
		for(int i = j; i < k - 1; i++)
			Eta_value[i] *= -d;

		JustInverted = 0;
	}

	private void setpivcol(int word0, int i, double ad[])
	{
		double d;
		if(word0 != 0)
			d = 1.0D;
		else
			d = -1D;
		for(int j = 0; j <= Rows; j++)
			ad[j] = 0.0D;

		if(i > Rows)
		{
			int l = i - Rows;
			for(int k = Col_end[l - 1]; k < Col_end[l]; k++)
				ad[Mat[k].row_nr] = Mat[k].value * d;

			ad[0] -= Extrad * d;
		} else
		if(word0 != 0)
			ad[i] = 1.0D;
		else
			ad[i] = -1D;
		ftran(1, Eta_size, ad);
	}

	private void minoriteration(int i, int j)
	{
		double d = 0.0D;
		int l1 = i + Rows;
		int j2 = Eta_col_end[Eta_size];
		int k1 = j2;
		Eta_size++;
		if(Extrad != 0.0D)
		{
			Eta_row_nr[j2] = 0;
			Eta_value[j2] = -Extrad;
			j2++;
		}
		for(int i1 = Col_end[i - 1]; i1 < Col_end[i]; i1++)
		{
			int j1 = Mat[i1].row_nr;
			if(j1 == 0 && Extrad != 0.0D)
				Eta_value[Eta_col_end[Eta_size - 1]] += Mat[i1].value;
			else
			if(j1 != j)
			{
				Eta_row_nr[j2] = j1;
				Eta_value[j2] = Mat[i1].value;
				j2++;
			} else
			{
				d = Mat[i1].value;
			}
		}

		Eta_row_nr[j2] = j;
		Eta_value[j2] = 1.0D / d;
		j2++;
		double d1 = Rhs[j] / d;
		Rhs[j] = d1;
		for(int k = k1; k < j2 - 1; k++)
			Rhs[Eta_row_nr[k]] -= d1 * Eta_value[k];

		int i2 = Bas[j];
		Bas[j] = l1;
		Basis[i2] = 0;
		Basis[l1] = 1;
		for(int l = k1; l < j2 - 1; l++)
			Eta_value[l] /= -d;

		Eta_col_end[Eta_size] = j2;
	}

	private void rhsmincol(double d, int i, int j)
	{
		if(i > Rows + 1)
		{
			System.err.print("Error: rhsmincol called with row_nr: " + i + ", rows: " + Rows + "\n");
			System.err.print("This indicates numerical instability\n");
			System.exit(-1);
		}
		int l = Eta_col_end[Eta_size];
		int i1 = Eta_col_end[Eta_size + 1];
		for(int k = l; k < i1; k++)
		{
			double d1 = Rhs[Eta_row_nr[k]] - d * Eta_value[k];
			d1 = Util.round(d1, Epsb);
			Rhs[Eta_row_nr[k]] = d1;
		}

		Rhs[i] = d;
		int j1 = Bas[i];
		Bas[i] = j;
		Basis[j1] = 0;
		Basis[j] = 1;
	}

	void invert()
	{
		if(Lp.print_at_invert != 0)
			System.out.print("Start Invert iter " + Lp.iter + " eta_size " + Eta_size + " rhs[0] " + -Rhs[0] + " \n");
		int ai[] = new int[Rows + 1];
		for(int i = 0; i <= Rows; i++)
			ai[i] = 0;

		int ai1[] = new int[Rows + 1];
		for(int j = 0; j <= Rows; j++)
			ai1[j] = 0;

		int ai2[] = new int[Rows + 1];
		for(int k = 0; k <= Rows; k++)
			ai2[k] = 0;

		double ad[] = new double[Rows + 1];
		for(int l = 0; l <= Rows; l++)
			ad[l] = 0.0D;

		int aword0[] = new int[Rows + 1];
		for(int i1 = 0; i1 <= Rows; i1++)
			aword0[i1] = 1;

		int aword1[] = new int[Columns + 1];
		for(int j1 = 0; j1 < Columns; j1++)
			aword1[j1] = 0;

		int ai3[] = new int[Columns + 1];
		for(int k1 = 0; k1 <= Columns; k1++)
			ai3[k1] = 0;

		for(int l1 = 0; l1 <= Rows; l1++)
			if(Bas[l1] > Rows)
				aword1[Bas[l1] - Rows - 1] = 1;
			else
				aword0[Bas[l1]] = 0;

		for(int i2 = 1; i2 <= Rows; i2++)
			if(aword0[i2] != 0)
			{
				for(int j4 = Row_end[i2 - 1] + 1; j4 <= Row_end[i2]; j4++)
				{
					int l6 = Col_no[j4];
					if(aword1[l6 - 1] != 0)
					{
						ai3[l6]++;
						ai[i2 - 1]++;
					}
				}

			}

		for(int j2 = 1; j2 <= Rows; j2++)
			Bas[j2] = j2;

		for(int k2 = 1; k2 <= Rows; k2++)
			Basis[k2] = 1;

		for(int l2 = 1; l2 <= Columns; l2++)
			Basis[l2 + Rows] = 0;

		for(int i3 = 0; i3 <= Rows; i3++)
			Rhs[i3] = Rh[i3];

		for(int j3 = 1; j3 <= Columns; j3++)
		{
			int j7 = Rows + j3;
			if(Lower[j7] == 0)
			{
				double d = Upbo[j7];
				for(int k4 = Col_end[j3 - 1]; k4 < Col_end[j3]; k4++)
					Rhs[Mat[k4].row_nr] -= d * Mat[k4].value;

			}
		}

		for(int k3 = 1; k3 <= Rows; k3++)
			if(Lower[k3] == 0)
				Rhs[k3] -= Upbo[k3];

		Eta_size = 0;
		int k6 = 0;
		int k7 = 0;
		Num_inv = 0;
		int i7 = 0;
		while(k6 < Rows) 
		{
			if(++k7 > Rows)
				k7 = 1;
			k6++;
			if(ai[k7 - 1] == 1 && aword0[k7] != 0)
			{
				k6 = 0;
				int l4;
				for(l4 = Row_end[k7 - 1] + 1; aword1[Col_no[l4] - 1] == 0; l4++);
				int k8 = Col_no[l4];
				aword1[k8 - 1] = 0;
				ai3[k8] = 0;
				for(int i5 = Col_end[k8 - 1]; i5 < Col_end[k8]; i5++)
					if(aword0[Mat[i5].row_nr] != 0)
						ai[Mat[i5].row_nr - 1]--;

				aword0[k7] = 0;
				minoriteration(k8, k7);
			}
		}
		k6 = 0;
		int l8 = 0;
		while(k6 < Columns) 
		{
			if(++l8 > Columns)
				l8 = 1;
			k6++;
			if(ai3[l8] == 1 && aword1[l8 - 1] != 0)
			{
				k6 = 0;
				int j5;
				for(j5 = Col_end[l8 - 1] + 1; aword0[Mat[j5 - 1].row_nr] == 0; j5++);
				int l7 = Mat[j5 - 1].row_nr;
				aword0[l7] = 0;
				ai[l7 - 1] = 0;
				for(int k5 = Row_end[l7 - 1] + 1; k5 <= Row_end[l7]; k5++)
					if(aword1[Col_no[k5] - 1] != 0)
						ai3[Col_no[k5]]--;

				aword1[l8 - 1] = 0;
				i7++;
				ai1[i7 - 1] = l8;
				ai2[i7 - 1] = l7;
			}
		}
		for(int l5 = 1; l5 <= Columns; l5++)
			if(aword1[l5 - 1] != 0)
			{
				aword1[l5 - 1] = 0;
				setpivcol(Lower[Rows + l5], l5 + Rows, ad);
				int i8;
				for(i8 = 1; (aword0[i8] == 0 || ad[i8] == 0.0D) && i8 <= Rows; i8++);
				if(i8 == Rows + 1)
					System.err.print("Inverting failed");
				aword0[i8] = 0;
				condensecol(i8, ad);
				double d1 = Rhs[i8] / ad[i8];
				rhsmincol(d1, i8, Rows + l5);
				addetacol();
			}

		for(int l3 = i7 - 1; l3 >= 0; l3--)
		{
			int i9 = ai1[l3];
			int j8 = ai2[l3];
			int j9 = i9 + Rows;
			for(int i6 = 0; i6 <= Rows; i6++)
				ad[i6] = 0.0D;

			for(int j6 = Col_end[i9 - 1]; j6 < Col_end[i9]; j6++)
				ad[Mat[j6].row_nr] = Mat[j6].value;

			ad[0] -= Extrad;
			condensecol(j8, ad);
			double d2 = Rhs[j8] / ad[j8];
			rhsmincol(d2, j8, j9);
			addetacol();
		}

		for(int i4 = 1; i4 <= Rows; i4++)
			Rhs[i4] = Util.round(Rhs[i4], Epsb);

		if(Lp.print_at_invert != 0)
			System.out.print("End Invert                eta_size " + Eta_size + " rhs[0] " + -Rhs[0] + "\n");
		JustInverted = 1;
		DoInvert = 0;
	}

	private int colprim(Ref ref, int word0, double ad[])
	{
		double d2 = -Epsd;
		ref.value = 0.0D;
		if(word0 == 0)
		{
			for(int j = 1; j <= Sum; j++)
				ad[j] = 0.0D;

			ad[0] = 1.0D;
			btran(ad);
			for(int k = 1; k <= Columns; k++)
			{
				int i = Rows + k;
				if(Basis[i] == 0 && Upbo[i] > 0.0D)
				{
					double d = 0.0D;
					for(int j1 = Col_end[k - 1]; j1 < Col_end[k]; j1++)
						d += ad[Mat[j1].row_nr] * Mat[j1].value;

					ad[i] = d;
				}
			}

			for(int l = 1; l <= Sum; l++)
				ad[l] = Util.round(ad[l], Epsd);

		}
		for(int i1 = 1; i1 <= Sum; i1++)
			if(Basis[i1] == 0 && Upbo[i1] > 0.0D)
			{
				double d1;
				if(Lower[i1] != 0)
					d1 = ad[i1];
				else
					d1 = -ad[i1];
				if(d1 < d2)
				{
					d2 = d1;
					ref.value = i1;
				}
			}

		if(Lp.trace != 0)
			if(ref.value > 0.0D)
				System.err.print("col_prim:" + ref.value + ", reduced cost: " + d2 + "\n");
			else
				System.err.print("col_prim: no negative reduced costs found, optimality!\n");
		if(ref.value == 0.0D)
		{
			Doiter = 0;
			DoInvert = 0;
			Status = 0;
		}
		return ref.value > 0.0D ? 1 : 0;
	}

	private int rowprim(int i, Ref ref, Ref ref1, double ad[])
	{
		double d = 0.0D;
		ref.value = 0.0D;
		ref1.value = Infinite;
		for(int j = 1; j <= Rows; j++)
		{
			d = ad[j];
			if(Math.abs(d) < TREJ)
				d = 0.0D;
			if(d != 0.0D)
			{
				double d1 = 2D * Infinite;
				if(d > 0.0D)
					d1 = Rhs[j] / d;
				else
				if(Upbo[Bas[j]] < Infinite)
					d1 = (Rhs[j] - Upbo[Bas[j]]) / d;
				Util.round(d1, Epsel);
				if(d1 < ref1.value)
				{
					ref1.value = d1;
					ref.value = j;
				}
			}
		}

		if(ref.value == 0.0D)
		{
			for(int k = 1; k <= Rows; k++)
			{
				d = ad[k];
				if(d != 0.0D)
				{
					double d2 = 2D * Infinite;
					if(d > 0.0D)
						d2 = Rhs[k] / d;
					else
					if(Upbo[Bas[k]] < Infinite)
						d2 = (Rhs[k] - Upbo[Bas[k]]) / d;
					d2 = Util.round(d2, Epsel);
					if(d2 < ref1.value)
					{
						ref1.value = d2;
						ref.value = k;
					}
				}
			}

		}
		if(ref1.value < 0.0D)
		{
			System.err.println("Warning: Numerical instability, qout = " + ref1.value);
			System.err.println("pcol[" + ref.value + "] = " + d + ", rhs[" + ref.value + "] = " + Rhs[(int)ref.value] + " , upbo = " + Upbo[Bas[(int)ref.value]]);
		}
		if(ref.value == 0.0D)
			if(Upbo[i] == Infinite)
			{
				Doiter = 0;
				DoInvert = 0;
				Status = 3;
			} else
			{
				int l;
				for(l = 1; ad[l] >= 0.0D && l <= Rows; l++);
				if(l > Rows)
				{
					Lower[i] = 0;
					Rhs[0] += Upbo[i] * ad[0];
					Doiter = 0;
					DoInvert = 0;
				} else
				if(ad[l] < 0.0D)
					ref.value = l;
			}
		if(ref.value > 0.0D)
			Doiter = 1;
		if(Lp.trace != 0)
			System.out.println("row_prim:" + ref.value + ", pivot element:" + ad[(int)ref.value]);
		return ref.value > 0.0D ? 1 : 0;
	}

	private int rowdual(Ref ref)
	{
		ref.value = 0.0D;
		double d2 = -Epsb;
		int i = 0;
		for(boolean flag = false; i < Rows && !flag;)
		{
			i++;
			double d = Upbo[Bas[i]];
			if(d == 0.0D && Rhs[i] != 0.0D)
			{
				flag = true;
				ref.value = i;
			} else
			{
				double d1;
				if(Rhs[i] < d - Rhs[i])
					d1 = Rhs[i];
				else
					d1 = d - Rhs[i];
				if(d1 < d2)
				{
					d2 = d1;
					ref.value = i;
				}
			}
		}

		if(Lp.trace != 0)
			if(ref.value > 0.0D)
			{
				System.out.println("row_dual:" + ref.value + ", rhs of selected row:           " + Rhs[(int)ref.value]);
				if(Upbo[Bas[(int)ref.value]] < Infinite)
					System.out.println("               upper bound of basis variable:    " + Upbo[Bas[(int)ref.value]]);
			} else
			{
				System.out.print("row_dual: no infeasibilities found\n");
			}
		return ref.value > 0.0D ? 1 : 0;
	}

	private int coldual(int i, Ref ref, int word0, double ad[], double ad1[])
	{
		Doiter = 0;
		if(word0 == 0)
		{
			for(int j = 0; j <= Rows; j++)
			{
				ad[j] = 0.0D;
				ad1[j] = 0.0D;
			}

			ad1[0] = 1.0D;
			ad[i] = 1.0D;
			for(int k = Eta_size; k >= 1; k--)
			{
				double d3 = 0.0D;
				double d6 = 0.0D;
				int i2 = Eta_row_nr[Eta_col_end[k] - 1];
				for(int k1 = Eta_col_end[k - 1]; k1 < Eta_col_end[k]; k1++)
				{
					d6 += ad[Eta_row_nr[k1]] * Eta_value[k1];
					d3 += ad1[Eta_row_nr[k1]] * Eta_value[k1];
				}

				d6 = Util.round(d6, Epsel);
				ad[i2] = d6;
				d3 = Util.round(d3, Epsel);
				ad1[i2] = d3;
			}

			for(int l = 1; l <= Columns; l++)
			{
				int j2 = Rows + l;
				if(Basis[j2] == 0)
				{
					double d4 = -Extrad * ad1[0];
					double d7 = 0.0D;
					for(int l1 = Col_end[l - 1]; l1 < Col_end[l]; l1++)
					{
						d4 += ad1[Mat[l1].row_nr] * Mat[l1].value;
						d7 += ad[Mat[l1].row_nr] * Mat[l1].value;
					}

					ad1[j2] = d4;
					ad[j2] = d7;
				}
			}

			for(int i1 = 0; i1 <= Sum; i1++)
			{
				ad[i1] = Util.round(ad[i1], Epsel);
				ad1[i1] = Util.round(ad1[i1], Epsd);
			}

		}
		double d8;
		if(Rhs[i] > Upbo[Bas[i]])
			d8 = -1D;
		else
			d8 = 1.0D;
		double d2 = 0.0D;
		ref.value = 0.0D;
		double d = Infinite;
		for(int j1 = 1; j1 <= Sum; j1++)
		{
			double d5;
			if(Lower[j1] != 0)
				d5 = ad[j1] * d8;
			else
				d5 = -ad[j1] * d8;
			if(d5 < 0.0D && Basis[j1] == 0 && Upbo[j1] > 0.0D)
			{
				double d1;
				if(Lower[j1] == 0)
					d1 = -ad1[j1] / d5;
				else
					d1 = ad1[j1] / d5;
				if(d1 < d)
				{
					d = d1;
					d2 = d5;
					ref.value = j1;
				} else
				if(d1 == d && Math.abs(d5) > Math.abs(d2))
				{
					d2 = d5;
					ref.value = j1;
				}
			}
		}

		if(Lp.trace != 0)
			System.out.println("col_dual:" + ref.value + ", pivot element:  " + ad[(int)ref.value]);
		if(ref.value > 0.0D)
			Doiter = 1;
		return ref.value > 0.0D ? 1 : 0;
	}

	private void iteration(int i, int j, Ref ref, double d, Ref ref1, Ref ref2, 
			int word0, double ad[])
	{
		Lp.iter++;
		ref1.value = ref.value > d + Epsb ? 1.0D : 0.0D;
		if(ref1.value != 0.0D)
		{
			ref.value = d;
			ref2.value = ref2.value == 0.0D ? 1.0D : 0.0D;
		}
		int j1 = Eta_col_end[Eta_size + 1];
		double d3 = Eta_value[j1 - 1];
		for(int k = Eta_col_end[Eta_size]; k < j1; k++)
		{
			double d1 = Rhs[Eta_row_nr[k]] - ref.value * Eta_value[k];
			d1 = Util.round(d1, Epsb);
			Rhs[Eta_row_nr[k]] = d1;
		}

		if(ref1.value == 0.0D)
		{
			Rhs[i] = ref.value;
			int k1 = Bas[i];
			Bas[i] = j;
			Basis[k1] = 0;
			Basis[j] = 1;
			if(word0 != 0 && d3 < 0.0D)
				Lower[k1] = 0;
			if(ref2.value == 0.0D && d < Infinite)
			{
				ref2.value = 1.0D;
				Rhs[i] = d - Rhs[i];
				for(int l = Eta_col_end[Eta_size]; l < j1; l++)
					Eta_value[l] = -Eta_value[l];

			}
			addetacol();
			Num_inv++;
		}
		if(Lp.trace != 0)
		{
			System.out.print("Theta = " + ref.value + " ");
			if(ref1.value != 0.0D)
			{
				if(Lower[j] == 0)
					System.out.print("Iteration:" + Lp.iter + ", variable" + j + " changed from 0 to its upper bound of " + Upbo[j] + "\n");
				else
					System.out.print("Iteration:" + Lp.iter + ", variable" + j + " changed its upper bound of " + Upbo[j] + " to 0\n");
			} else
			{
				System.out.print("Iteration:" + Lp.iter + ", variable" + j + " entered basis at:" + Rhs[i] + "\n");
			}
			if(word0 == 0)
			{
				double d2 = 0.0D;
				for(int i1 = 1; i1 <= Rows; i1++)
					if(Rhs[i1] < 0.0D)
						d2 -= Rhs[i1];
					else
					if(Rhs[i1] > Upbo[Bas[i1]])
						d2 += Rhs[i1] - Upbo[Bas[i1]];

				System.out.println("feasibility gap of this basis:" + d2);
			} else
			{
				System.out.println("objective function value of this feasible basis: " + Rhs[0]);
			}
		}
	}

	private int solvelp()
	{
		double d = 0.0D;
		double d2 = 0.0D;
		int l1 = 0;
		int i2 = 0;
		Ref ref = new Ref(0.0D);
		Ref ref1 = new Ref(0.0D);
		Ref ref2 = new Ref(0.0D);
		double ad[] = new double[Sum + 1];
		double ad1[] = new double[Sum + 1];
		double ad2[] = new double[Rows + 1];
		for(int i = 0; i <= Sum; i++)
		{
			ad[i] = 0.0D;
			ad1[i] = 0.0D;
		}

		for(int j = 0; j <= Rows; j++)
			ad2[j] = 0.0D;

		Lp.iter = 0;
		int word1 = 0;
		Status = 5;
		DoInvert = 0;
		Doiter = 0;
		int k = 0;
		int word0;
		for(word0 = 1; k != Rows && word0 != 0; word0 = Rhs[k] >= 0.0D && Rhs[k] <= Upbo[Bas[k]] ? 1 : 0)
			k++;

		if(Lp.trace != 0)
			if(word0 != 0)
				System.out.print("Start at feasible basis\n");
			else
				System.out.print("Start at infeasible basis\n");
		if(word0 == 0)
		{
			ad[0] = 1.0D;
			for(int l = 1; l <= Rows; l++)
				ad[l] = 0.0D;

			Extrad = 0.0D;
			for(int i1 = 1; i1 <= Columns; i1++)
			{
				int k1 = Rows + i1;
				ad[k1] = 0.0D;
				for(int j1 = Col_end[i1 - 1]; j1 < Col_end[i1]; j1++)
					if(ad[Mat[j1].row_nr] != 0.0D)
						ad[k1] += ad[Mat[j1].row_nr] * Mat[j1].value;

				if(ad[k1] < Extrad)
					Extrad = ad[k1];
			}

		} else
		{
			Extrad = 0.0D;
		}
		if(Lp.trace != 0)
			System.out.println("Extrad = " + Extrad);
		word1 = 0;
		while(Status == 5) 
		{
			Doiter = 0;
			DoInvert = 0;
			construct_solution(Solution);
			debug_print_bounds(Upbo, Lowbo);
			debug_print_solution();
			if(word0 != 0)
			{
				ref.value = l1;
				int word2 = colprim(ref, word1, ad);
				l1 = (int)ref.value;
				if(word2 != 0)
				{
					setpivcol(Lower[l1], l1, ad2);
					ref.value = i2;
					ref1.value = d2;
					int word3 = rowprim(l1, ref, ref1, ad2);
					i2 = (int)ref.value;
					d2 = ref1.value;
					if(word3 != 0)
						condensecol(i2, ad2);
				}
			} else
			{
				if(word1 == 0)
				{
					ref.value = i2;
					int word4 = rowdual(ref);
					i2 = (int)ref.value;
				}
				if(i2 > 0)
				{
					ref.value = l1;
					int word5 = coldual(i2, ref, word1, ad1, ad);
					l1 = (int)ref.value;
					if(word5 != 0)
					{
						setpivcol(Lower[l1], l1, ad2);
						if(ad2[i2] == 0.0D)
						{
							System.err.println("An attempt was made to divide by zero (Pcol[" + i2 + "])");
							System.err.println("This indicates numerical instability");
							Doiter = 0;
							if(JustInverted == 0)
							{
								System.out.println("Reinverting Eta");
								DoInvert = 1;
							} else
							{
								System.out.println("Can't reinvert, failure");
								Status = 4;
							}
						} else
						{
							condensecol(i2, ad2);
							double d1 = Rhs[i2] - Upbo[Bas[i2]];
							if(d1 > 0.0D)
							{
								d2 = d1 / ad2[i2];
								if(d2 <= Upbo[l1])
									Lower[Bas[i2]] = Lower[Bas[i2]] == 0 ? 1 : 0;
							} else
							{
								d2 = Rhs[i2] / ad2[i2];
							}
						}
					} else
					{
						Status = 2;
					}
				} else
				{
					word0 = 1;
					Doiter = 0;
					Extrad = 0.0D;
					DoInvert = 1;
				}
			}
			if(Doiter != 0)
			{
				ref.value = d2;
				ref1.value = word1;
				ref2.value = Lower[l1];
				iteration(i2, l1, ref, Upbo[l1], ref1, ref2, word0, ad2);
				d2 = ref.value;
				word1 = (int)ref1.value;
				Lower[l1] = (int)ref2.value;
			}
			if(Num_inv >= Lp.max_num_inv)
				DoInvert = 1;
			if(DoInvert != 0)
			{
				if(Lp.print_at_invert != 0)
					System.out.println("Inverting: Primal = " + word0);
				invert();
			}
		}
		Lp.total_iter += Lp.iter;
		return Status;
	}

	private int is_int(double d)
	{
		double d1 = d - Math.floor(d);
		if(d1 < Epsilon)
			return 1;
		else
			return d1 > 1.0D - Epsilon ? 1 : 0;
	}

	private void construct_solution(double ad[])
	{
		for(int i = 0; i <= Rows; i++)
			ad[i] = 0.0D;

		if(Lp.scaling_used != 0)
		{
			for(int j = Rows + 1; j <= Sum; j++)
				ad[j] = Lowbo[j] * Lp.scale[j];

			for(int k = 1; k <= Rows; k++)
			{
				int j3 = Bas[k];
				if(j3 > Rows)
					ad[j3] += Rhs[k] * Lp.scale[j3];
			}

			for(int l = Rows + 1; l <= Sum; l++)
				if(Basis[l] == 0 && Lower[l] == 0)
					ad[l] += Upbo[l] * Lp.scale[l];

			for(int l2 = 1; l2 <= Columns; l2++)
			{
				double d = ad[Rows + l2];
				if(d != 0.0D)
				{
					for(int i1 = Col_end[l2 - 1]; i1 < Col_end[l2]; i1++)
						ad[Mat[i1].row_nr] += (d / Lp.scale[Rows + l2]) * (Mat[i1].value / Lp.scale[Mat[i1].row_nr]);

				}
			}

			for(int j1 = 0; j1 <= Rows; j1++)
				if(Math.abs(ad[j1]) < Epsb)
					ad[j1] = 0.0D;
				else
				if(Lp.ch_sign[j1] != 0)
					ad[j1] = -ad[j1];

		} else
		{
			for(int k1 = Rows + 1; k1 <= Sum; k1++)
				ad[k1] = Lowbo[k1];

			for(int l1 = 1; l1 <= Rows; l1++)
			{
				int k3 = Bas[l1];
				if(k3 > Rows)
					ad[k3] += Rhs[l1];
			}

			for(int i2 = Rows + 1; i2 <= Sum; i2++)
				if(Basis[i2] == 0 && Lower[i2] == 0)
					ad[i2] += Upbo[i2];

			for(int i3 = 1; i3 <= Columns; i3++)
			{
				double d1 = ad[Rows + i3];
				if(d1 != 0.0D)
				{
					for(int j2 = Col_end[i3 - 1]; j2 < Col_end[i3]; j2++)
						ad[Mat[j2].row_nr] += d1 * Mat[j2].value;

				}
			}

			for(int k2 = 0; k2 <= Rows; k2++)
				if(Math.abs(ad[k2]) < Epsb)
					ad[k2] = 0.0D;
				else
				if(Lp.ch_sign[k2] != 0)
					ad[k2] = -ad[k2];

		}
	}

	private void calculate_duals()
	{
		for(int i = 1; i <= Rows; i++)
			Lp.duals[i] = 0.0D;

		Lp.duals[0] = 1.0D;
		btran(Lp.duals);
		if(Lp.scaling_used != 0)
		{
			for(int j = 1; j <= Rows; j++)
				Lp.duals[j] *= Lp.scale[j] / Lp.scale[0];

		}
		for(int k = 1; k <= Rows; k++)
			if(Lp.basis[k] != 0)
				Lp.duals[k] = 0.0D;
			else
			if(Lp.ch_sign[0] == Lp.ch_sign[k])
				Lp.duals[k] = -Lp.duals[k];

	}

	private int milpsolve(double ad[], double ad1[], int aword0[], int aword1[], int ai[])
	{
		Random random = new Random();
		int j2 = 0;
		if(Break_bb != 0)
			return 8;
		Level++;
		Lp.total_nodes++;
		if(Level > Lp.max_level)
			Lp.max_level = Level;
		debug_print("starting solve\n");
		System.arraycopy(ad, 0, Upbo, 0, Sum + 1);
		System.arraycopy(ad1, 0, Lowbo, 0, Sum + 1);
		System.arraycopy(aword0, 0, Basis, 0, Sum + 1);
		System.arraycopy(aword1, 0, Lower, 0, Sum + 1);
		System.arraycopy(ai, 0, Bas, 0, Rows + 1);
		System.arraycopy(Orig_rh, 0, Rh, 0, Rows + 1);
		if(Lp.anti_degen != 0)
		{
			for(int i = 1; i <= Columns; i++)
			{
				double d2 = random.nextDouble() * 0.001D;
				if(d2 > Epsb)
					Lowbo[i + Rows] -= d2;
				d2 = random.nextDouble() * 0.001D;
				if(d2 > Epsb)
					Upbo[i + Rows] += d2;
			}

			Lp.eta_valid = 0;
		}
		if(Lp.eta_valid == 0)
		{
			for(int j = 1; j <= Columns; j++)
				if(Lowbo[Rows + j] != 0.0D)
				{
					double d = Lowbo[Rows + j];
					if(Upbo[Rows + j] < Infinite)
						Upbo[Rows + j] -= d;
					for(int k1 = Col_end[j - 1]; k1 < Col_end[j]; k1++)
						Rh[Mat[k1].row_nr] -= d * Mat[k1].value;

				}

			invert();
			Lp.eta_valid = 1;
		}
		int i2 = solvelp();
		if(Lp.anti_degen != 0)
		{
			System.arraycopy(ad, 0, Upbo, 0, Sum + 1);
			System.arraycopy(ad1, 0, Lowbo, 0, Sum + 1);
			System.arraycopy(Orig_rh, 0, Rh, 0, Rows + 1);
			for(int k = 1; k <= Columns; k++)
				if(Lowbo[Rows + k] != 0.0D)
				{
					double d1 = Lowbo[Rows + k];
					if(Upbo[Rows + k] < Infinite)
						Upbo[Rows + k] -= d1;
					for(int l1 = Col_end[k - 1]; l1 < Col_end[k]; l1++)
						Rh[Mat[l1].row_nr] -= d1 * Mat[l1].value;

				}

			invert();
			Lp.eta_valid = 1;
			i2 = solvelp();
		}
		if(i2 != 0)
			debug_print("this problem has no solution, it is " + (i2 == 3 ? "unbounded" : "infeasible"));
		if(i2 == 2 && Lp.verbose != 0)
			System.out.print("level" + Level + " INF\n");
		if(i2 == 0)
		{
			construct_solution(Solution);
			debug_print("a solution was found\n");
			debug_print_solution();
			boolean flag;
			if(Maximise != 0)
				flag = Solution[0] <= Best_solution[0];
			else
				flag = Solution[0] >= Best_solution[0];
			if(flag)
			{
				if(Lp.verbose != 0)
					System.out.println("level" + Level + " OPT NOB value " + Solution[0] + " bound " + Best_solution[0]);
				debug_print("but it was worse than the best sofar, discarded\n");
				Level--;
				return 1;
			}
			if(Lp.bb_rule == 0)
			{
				j2 = 0;
				for(int l = Rows + 1; l <= Sum && j2 == 0; l++)
					if(Must_be_int[l] != 0 && is_int(Solution[l]) == 0)
						if(ad1[l] == ad[l])
						{
							System.err.println("Warning: integer var " + (l - Rows) + " is already fixed at " + ad1[l] + ", but has non-integer value " + Solution[l]);
							System.err.println("Perhaps the -e option should be used");
						} else
						{
							j2 = l;
						}

			}
			if(Lp.bb_rule == 1)
			{
				int k2 = 0;
				for(int i1 = Rows + 1; i1 <= Sum; i1++)
					if(Must_be_int[i1] != 0 && is_int(Solution[i1]) == 0)
						k2++;

				if(k2 == 0)
				{
					j2 = 0;
				} else
				{
					int l2 = random.nextInt() % k2 + 1;
					int j1;
					for(j1 = Rows + 1; l2 > 0; j1++)
						if(Must_be_int[j1] != 0 && is_int(Solution[j1]) == 0)
							l2--;

					j2 = j1 - 1;
				}
			}
			if(Lp.verbose == 1)
				if(j2 != 0)
					System.out.println("level " + Level + " OPT     value " + Solution[0]);
				else
					System.out.println("level " + Level + " OPT INT value " + Solution[0]);
			if(j2 != 0)
			{
				double ad2[] = new double[Sum + 1];
				double ad3[] = new double[Sum + 1];
				int aword2[] = new int[Sum + 1];
				int aword3[] = new int[Sum + 1];
				int ai1[] = new int[Rows + 1];
				System.arraycopy(ad, 0, ad2, 0, Sum + 1);
				System.arraycopy(ad1, 0, ad3, 0, Sum + 1);
				System.arraycopy(Lower, 0, aword2, 0, Sum + 1);
				System.arraycopy(Basis, 0, aword3, 0, Sum + 1);
				System.arraycopy(Bas, 0, ai1, 0, Rows + 1);
				if(Lp.names_used != 0)
					debug_print("not enough ints. Selecting var " + Lp.col_name[j2 - Rows] + ", val: " + Solution[j2]);
				else
					debug_print("not enough ints. Selecting Var [" + j2 + "], val: " + Solution[j2]);
				debug_print("current bounds:\n");
				debug_print_bounds(ad, ad1);
				int i3;
				int j3;
				if(Floor_first != 0)
				{
					double d3 = Math.ceil(Solution[j2]) - 1.0D;
					if(d3 < ad1[j2])
					{
						debug_print("New upper bound value " + d3 + " conflicts with old lower bound " + ad1[j2] + "\n");
						i3 = 1;
					} else
					{
						ad2[j2] = d3;
						debug_print("starting first subproblem with bounds:");
						debug_print_bounds(ad2, ad1);
						Lp.eta_valid = 0;
						i3 = milpsolve(ad2, ad1, aword3, aword2, ai1);
						Lp.eta_valid = 0;
					}
					d3++;
					if(d3 > ad[j2])
					{
						debug_print("New lower bound value " + d3 + " conflicts with old upper bound " + ad[j2] + "\n");
						j3 = 1;
					} else
					{
						ad3[j2] = d3;
						debug_print("starting second subproblem with bounds:");
						debug_print_bounds(ad, ad3);
						Lp.eta_valid = 0;
						j3 = milpsolve(ad, ad3, aword3, aword2, ai1);
						Lp.eta_valid = 0;
					}
				} else
				{
					double d4 = Math.ceil(Solution[j2]);
					if(d4 > ad[j2])
					{
						debug_print("New lower bound value " + d4 + " conflicts with old upper bound " + ad[j2] + "\n");
						i3 = 1;
					} else
					{
						ad3[j2] = d4;
						debug_print("starting first subproblem with bounds:");
						debug_print_bounds(ad, ad3);
						Lp.eta_valid = 0;
						i3 = milpsolve(ad, ad3, aword3, aword2, ai1);
						Lp.eta_valid = 0;
					}
					d4--;
					if(d4 < ad1[j2])
					{
						debug_print("New upper bound value " + d4 + " conflicts with old lower bound " + ad1[j2] + "\n");
						j3 = 1;
					} else
					{
						ad2[j2] = d4;
						debug_print("starting second subproblem with bounds:");
						debug_print_bounds(ad2, ad1);
						Lp.eta_valid = 0;
						j3 = milpsolve(ad2, ad1, aword3, aword2, ai1);
						Lp.eta_valid = 0;
					}
				}
				if(i3 != 0 && j3 != 0)
					i2 = 2;
				else
					i2 = 0;
			} else
			{
				debug_print("--> valid solution found\n");
				boolean flag1;
				if(Maximise != 0)
					flag1 = Solution[0] < Best_solution[0];
				else
					flag1 = Solution[0] > Best_solution[0];
				if(!flag1)
				{
					if(Lp.debug != 0 || Lp.verbose != 0 && Lp.print_sol == 0)
						System.out.print("*** new best solution: old: " + Best_solution[0] + ", new: " + Solution[0] + " ***\n");
					System.arraycopy(Solution, 0, Best_solution, 0, Sum + 1);
					calculate_duals();
					if(Lp.print_sol != 0)
						print_solution(Lp);
					if(Lp.break_at_int != 0)
					{
						if(Maximise != 0 && Best_solution[0] > Lp.break_value)
							Break_bb = 1;
						if(Maximise == 0 && Best_solution[0] < Lp.break_value)
							Break_bb = 1;
					}
				}
			}
		}
		Level--;
		return i2;
	}

	public int solve(lprec lprec1)
	{
		if(lprec1.active == 0)
			set_globals(lprec1);
		lprec1.total_iter = 0;
		lprec1.max_level = 1;
		lprec1.total_nodes = 0;
		if(Isvalid(lprec1) != 0)
		{
			if(Maximise != 0 && lprec1.obj_bound == Infinite)
				Best_solution[0] = -Infinite;
			else
			if(Maximise == 0 && lprec1.obj_bound == -Infinite)
				Best_solution[0] = Infinite;
			else
				Best_solution[0] = lprec1.obj_bound;
			Level = 0;
			if(lprec1.basis_valid == 0)
			{
				for(int j = 0; j <= lprec1.rows; j++)
				{
					lprec1.basis[j] = 1;
					lprec1.bas[j] = j;
				}

				for(int k = lprec1.rows + 1; k <= lprec1.sum; k++)
					lprec1.basis[k] = 0;

				for(int l = 0; l <= lprec1.sum; l++)
					lprec1.lower[l] = 1;

				lprec1.basis_valid = 1;
			}
			lprec1.eta_valid = 0;
			Break_bb = 0;
			int i = milpsolve(Orig_upbo, Orig_lowbo, Basis, Lower, Bas);
			lprec1.eta_size = Eta_size;
			lprec1.eta_alloc = Eta_alloc;
			lprec1.num_inv = Num_inv;
			return i;
		} else
		{
			return 4;
		}
	}

	public int lag_solve(lprec lprec1, double d, int i, int word0)
	{
		double ad[] = new double[lprec1.columns + 1];
		double ad1[] = new double[lprec1.columns + 1];
		for(int j = 0; j <= lprec1.columns; j++)
			ad1[j] = 0.0D;

		double ad2[] = new double[lprec1.nr_lagrange];
		for(int k = 0; k < lprec1.nr_lagrange; k++)
			ad2[k] = 0.0D;

		double ad3[] = new double[lprec1.sum + 1];
		for(int l = 0; l <= lprec1.sum; l++)
			ad3[l] = 0.0D;

		int ai[] = new int[lprec1.rows + 1];
		System.arraycopy(lprec1.bas, 0, ai, 0, lprec1.rows + 1);
		int aword0[] = new int[lprec1.sum + 1];
		System.arraycopy(lprec1.lower, 0, aword0, 0, lprec1.sum + 1);
		get_row(lprec1, 0, ad);
		double d4 = 2D;
		double d1;
		double d2;
		if(lprec1.maximise != 0)
		{
			d1 = 9.9999999999999998E+23D;
			d2 = d;
		} else
		{
			d2 = -9.9999999999999998E+23D;
			d1 = d;
		}
		byte byte0 = 5;
		double d6 = 1.0D;
		int i6 = 0;
		boolean flag = false;
		int l5 = 0;
		for(int i1 = 0; i1 < lprec1.nr_lagrange; i1++)
			lprec1.lambda[i1] = 0.0D;

		while(byte0 == 5) 
		{
			l5++;
			for(int j1 = 1; j1 <= lprec1.columns; j1++)
			{
				ad1[j1] = ad[j1];
				for(int i5 = 0; i5 < lprec1.nr_lagrange; i5++)
					if(lprec1.maximise != 0)
						ad1[j1] -= lprec1.lambda[i5] * lprec1.lag_row[i5][j1];
					else
						ad1[j1] += lprec1.lambda[i5] * lprec1.lag_row[i5][j1];

			}

			for(int k1 = 1; k1 <= lprec1.columns; k1++)
				set_mat(lprec1, 0, k1, ad1[k1]);

			double d5 = 0.0D;
			for(int l1 = 0; l1 < lprec1.nr_lagrange; l1++)
				if(lprec1.maximise != 0)
					d5 += lprec1.lambda[l1] * lprec1.lag_rhs[l1];
				else
					d5 -= lprec1.lambda[l1] * lprec1.lag_rhs[l1];

			if(word0 != 0)
			{
				System.out.println("Zub: " + d1 + " Zlb: " + d2 + " Step: " + d6 + " pie: " + d4 + " Feas " + i6);
				for(int i2 = 0; i2 < lprec1.nr_lagrange; i2++)
					System.out.println(i2 + " SubGrad " + ad2[i2] + " lambda " + lprec1.lambda[i2]);

			}
			if(word0 != 0 && lprec1.sum < 20)
				print_lp(lprec1);
			int k5 = solve(lprec1);
			if(word0 != 0 && lprec1.sum < 20)
				print_solution(lprec1);
			int j6 = 1;
			for(int j2 = 1; j6 != 0 && j2 < lprec1.rows; j2++)
				j6 = ai[j2] == lprec1.bas[j2] ? 1 : 0;

			for(int k2 = 1; j6 != 0 && k2 < lprec1.sum; k2++)
				j6 = aword0[k2] == lprec1.lower[k2] ? 1 : 0;

			if(j6 == 0)
			{
				System.arraycopy(lprec1.lower, 0, aword0, 0, lprec1.sum + 1);
				System.arraycopy(lprec1.bas, 0, ai, 0, lprec1.rows + 1);
				d4 *= 0.94999999999999996D;
			}
			if(word0 != 0)
				System.out.println("result: " + k5 + "  same basis: " + j6);
			if(k5 == 3)
			{
				for(int l2 = 1; l2 <= lprec1.columns; l2++)
					System.out.print(ad1[l2] + " ");

				System.exit(-1);
			}
			if(k5 == 4)
				byte0 = 4;
			if(k5 == 2)
				byte0 = 2;
			double d7 = 0.0D;
			for(int i3 = 0; i3 < lprec1.nr_lagrange; i3++)
			{
				ad2[i3] = -lprec1.lag_rhs[i3];
				for(int j5 = 1; j5 <= lprec1.columns; j5++)
					ad2[i3] += lprec1.best_solution[lprec1.rows + j5] * lprec1.lag_row[i3][j5];

				d7 += ad2[i3] * ad2[i3];
			}

			i6 = 1;
			for(int j3 = 0; j3 < lprec1.nr_lagrange; j3++)
				if(lprec1.lag_con_type[j3] != 0)
				{
					if(Math.abs(ad2[j3]) > lprec1.epsb)
						i6 = 0;
				} else
				if(ad2[j3] > lprec1.epsb)
					i6 = 0;

			if(i6 != 0)
			{
				flag = true;
				double d3 = 0.0D;
				for(int k3 = 1; k3 <= lprec1.columns; k3++)
					d3 += lprec1.best_solution[lprec1.rows + k3] * ad[k3];

				if(lprec1.maximise != 0 && d3 > d2)
				{
					d2 = d3;
					for(int l3 = 1; l3 <= lprec1.sum; l3++)
						ad3[l3] = lprec1.best_solution[l3];

					ad3[0] = d2;
					if(word0 != 0)
						System.out.println("Best feasible solution: " + d2);
				} else
				if(d3 < d1)
				{
					d1 = d3;
					for(int i4 = 1; i4 <= lprec1.sum; i4++)
						ad3[i4] = lprec1.best_solution[i4];

					ad3[0] = d1;
					if(word0 != 0)
						System.out.println("Best feasible solution: " + d1);
				}
			}
			if(lprec1.maximise != 0)
				d1 = Math.min(d1, d5 + lprec1.best_solution[0]);
			else
				d2 = Math.max(d2, d5 + lprec1.best_solution[0]);
			if(Math.abs(d1 - d2) < 0.001D)
				byte0 = 0;
			d6 = (d4 * (1.05D * d1 - d2)) / d7;
			for(int j4 = 0; j4 < lprec1.nr_lagrange; j4++)
			{
				lprec1.lambda[j4] += d6 * ad2[j4];
				if(lprec1.lag_con_type[j4] == 0 && lprec1.lambda[j4] < 0.0D)
					lprec1.lambda[j4] = 0.0D;
			}

			if(l5 == i && byte0 == 5)
				if(flag)
					byte0 = 6;
				else
					byte0 = 7;
		}
		for(int k4 = 0; k4 <= lprec1.sum; k4++)
			lprec1.best_solution[k4] = ad3[k4];

		for(int l4 = 1; l4 <= lprec1.columns; l4++)
			set_mat(lprec1, 0, l4, ad[l4]);

		if(lprec1.maximise != 0)
			lprec1.lag_bound = d1;
		else
			lprec1.lag_bound = d2;
		return byte0;
	}

	public solve()
	{
	}
}
