#include #include #include #include // Copyright (C) 2000 Ben Sapp. All rights reserved. // // This is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the // Free Software Foundation; either version 2, or (at your option) any // later version. // // This is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. #define TRUE 1 #define FALSE 0 static inline Matrix identity_matrix(int m,int n) { int min = (m > n) ? n : m; Matrix me(m,n,0.0); for(int i=0;i The upper bound is the smallest #define CASE_B 1 // min{y_i0/y_ij} for all y_ij > 0 is the smallest #define CASE_C 2 // min{(y_i0-h_j)/y_ij) for all y_ij < 0 is the smallest // This takes a tableau and reduces it to the solution tableau. static Matrix minimize(Matrix T, Matrix &basis,ColumnVector upper_bounds,RowVector &which_bound) { int nr = T.rows(); int nc = T.cols(); int i,j,k,min_case; double min_val; int min_row = 0; int found_one; while(TRUE){ found_one = FALSE; for(i=0;i<(nc-1);i++){ if(T(nr-1,i) < -10.0*DBL_EPSILON){ found_one = TRUE; break; } } if(!found_one){ break; } // Now i is the column we will pivot on. min_row = -1; min_case = CASE_A; min_val = upper_bounds(i); for(j=0;j<(nr-1);j++){ if(T(j,i) > 0){ if(min_val > (T(j,nc-1)/T(j,i))){ min_row = j; min_val = T(j,nc-1)/T(j,i); min_case = CASE_B; } }else if(T(j,i) < 0){ if(min_val > ((T(j,nc-1)-upper_bounds(i))/T(j,i))){ min_row = j; min_val = (T(j,nc-1)-upper_bounds(i))/T(j,i); min_case = CASE_C; } } } int interesting_column=0; for(j=0;j<(nr-1);j++){ if(basis(j,0) == min_row){ interesting_column = int(basis(j,1)); /*basis(j,0) = min_row; basis(j,1) = i; */ break; } } // Now min_row is the row and i is the column to pivot on. Matrix Id; switch(min_case) { case CASE_A: for(k = 0; k < nr; k++) { T(k,i) = -T(k,i); T(k,nc-1) += T(k,i); } which_bound(i) = -which_bound(i); break; case CASE_B: T = pivot(T,min_row,i); for(j=0;j 0){ print_usage("lp"); return(retval); } // Now take care of upper and lower bounds idx_vector aRange; idx_vector bRange(Range(1,nr)); for(i =0;i -octave_Inf) { // Translate variable up; // Make the {x_min < x < x_max} constraint now equal to {0 < x_new < x_max - x_min} aRange = idx_vector(Range(i+1,i+1)); b = b-ColumnVector(Matrix(A.index(bRange,aRange))*double(vlb(i))); // If the upper bound is Infinity we do not change it. if(vub(i) < octave_Inf){ vub(i) = vub(i)-vlb(i); } } else if(vub(i) < octave_Inf) { // Now we have the following constraint ==> {-Inf < x < x_max} // After we are done it will be {0 < x_new < Inf}, where {x_new = -x+x_max} b = b-ColumnVector(Matrix(A.index(bRange,aRange))*double(vub(i))); T = identity_matrix(A.rows()); T(i,i) = -1.0; A = A*T; vub(i) = octave_Inf; } else { // both bounds are infinity so make this into two variables; // Now we have the following constraint -Inf < x < Inf // After we are done we have {0 < x1_new < Inf} and // {0 < x2_new < Inf} where {x = x1_new-x2_new} aRange = idx_vector(Range(i+1,i+1)); A = A.append(-Matrix(A.index(bRange,aRange))); c = RowVector(Matrix(c).append(Matrix(1,1,-c(i)))); if(freeVarNum > 0) { freeVars.stack(Matrix(1,2,0.0)); } freeVars(i,0) = i; freeVars(i,1) = A.cols()-1; freeVarNum++; vub = ColumnVector(Matrix(vub).stack(Matrix(1,1,octave_Inf))); } } // find a basis. Each row of basis holds where one element of the basis is. // For example if [1,2] is on row 1 of basis then row 1 , column 2 is an // element in the basis. Matrix basis(nr,2,-1.0); RowVector which_bound(nc+freeVarNum,1.0); int index = 0; int slacks = 0; if(ne <= nr) { A = A.append(identity_matrix(nr,(nr-ne))); for(i=0;i<(nr-ne);i++) { basis(i,1) = i+nc; basis(i,0) = i; index++; slacks++; } which_bound = which_bound.append(RowVector(nr-ne,1.0)); vub = vub.stack(ColumnVector(nr-ne,octave_Inf)); c = c.append(RowVector(nr-ne,0)); } else { octave_stdout << "It does not make sense to have more equalities than the rank of the system\n"; return(retval); } if(index < nr) { include_in_basis = FALSE; // Loop over all columns for(i = 0;i < nc;i++) { k=0; // Decide if this column can be included in a basis for(j = 0;j 1){break; /* If there are already too many non-zero entries ... move on! */ } } if(k == (nr-1)) { basis(index,1) = i; include_in_basis = TRUE; for(l = 0;l -octave_Inf) { // Make the {x_min < x < x_max} constraint now equal to {0 < x_new < x_max - x_min} x(i) = x(i)-vlb(i); } else if(orig_vub(i) < octave_Inf) { // Translate negative variable up; x(i) = -x(i)+orig_vub(i); } else { // both bounds are infinity so make this into two variables; if(x(freeVars(j,0)) != 0) { if(x(freeVars(j,1)) != 0) { // This should be a mathematical impossibility! octave_stdout << "You have found a bug in lp.\n"; octave_stdout << "Something that should be mathematically impossible occured\n"; octave_stdout << "The answer given may or may not be correct\n"; octave_stdout << "Please report the problem\n"; } T = Matrix(x); aRange = idx_vector(Range(1,freeVars(j,1)-1)); if(freeVars(j,1) < T.rows()) { cRange = idx_vector(Range(freeVars(j,1)+1,T.rows())); T = Matrix(T.index(aRange,bRange)).stack(Matrix(T.index(cRange,bRange))); } else { T = Matrix(T.index(aRange,bRange)); } x = ColumnVector(T); } else if(x(freeVars(j,1)) != 0) { // This means that a free variable is nagative x(freeVars(j,0)) = -x(freeVars(j,1)); T = Matrix(x); aRange = idx_vector(Range(1,freeVars(j,1))); if(freeVars(j,1) < (T.rows()-1)) { cRange = idx_vector(Range(freeVars(j,1)+1,T.rows())); T = Matrix(T.index(aRange,bRange)).stack(Matrix(T.index(cRange,bRange))); } else { T = Matrix(T.index(aRange,bRange)); } x = ColumnVector(T); } else { // This means that both variables are zero. // I simply remove the extra one and proceed as normal T = Matrix(x); aRange = idx_vector(Range(1,freeVars(j,1))); if(freeVars(j,1) < T.rows()) { cRange = idx_vector(Range(freeVars(j,1)+1,T.rows())); T = Matrix(T.index(aRange,bRange)).stack(Matrix(T.index(cRange,bRange))); } else { T = Matrix(T.index(aRange,bRange)); } x = ColumnVector(T); } } } // -------------------------------------------------------- return(x); #endif /* !HAVE_OCTAVE_20 */ }