#include "precomp.hpp" #include #include #include #define ALEX_DEBUG namespace cv{namespace optim{ using std::vector; using namespace std; #ifdef ALEX_DEBUG #define dprintf(x) printf x static void print_matrix(const Mat& x){ print(x); printf("\n"); } static void print_simplex_state(const Mat& c,const Mat& b,double v,const std::vector N,const std::vector B){ printf("\tprint simplex state\n"); printf("v=%g\n",v); printf("here c goes\n"); print_matrix(c); printf("non-basic: "); print(Mat(N)); printf("\n"); printf("here b goes\n"); print_matrix(b); printf("basic: "); print(Mat(B)); printf("\n"); } #else #define dprintf(x) #define print_matrix(x) #define print_simplex_state(c,b,v,N,B) #endif /**Due to technical considerations, the format of input b and c is somewhat special: *both b and c should be one column bigger than corresponding b and c of linear problem and the leftmost column will be used internally by this procedure - it should not be cleaned before the call to procedure and may contain mess after it also initializes N and B and does not make any assumptions about their init values * @return SOLVELP_UNFEASIBLE if problem is unfeasible, 0 if feasible. */ static int initialize_simplex(Mat_& c, Mat_& b,double& v,vector& N,vector& B); static inline void pivot(Mat_& c,Mat_& b,double& v,vector& N,vector& B, int leaving_index,int entering_index); /**@return SOLVELP_UNBOUNDED means the problem is unbdd, SOLVELP_MULTI means multiple solutions, SOLVELP_SINGLE means one solution. */ static int inner_simplex(Mat_& c, Mat_& b,double& v,vector& N,vector& B); static void swap_columns(Mat_& A,int col1,int col2); //return codes:-2 (no_sol - unbdd),-1(no_sol - unfsbl), 0(single_sol), 1(multiple_sol=>least_l2_norm) int solveLP(const Mat& Func, const Mat& Constr, Mat& z){ dprintf(("call to solveLP\n")); //sanity check (size, type, no. of channels) CV_Assert(Func.type()==CV_64FC1 || Func.type()==CV_32FC1); CV_Assert(Constr.type()==CV_64FC1 || Constr.type()==CV_32FC1); CV_Assert((Func.rows==1 && (Constr.cols-Func.cols==1))|| (Func.cols==1 && (Constr.cols-Func.rows==1))); //copy arguments for we will shall modify them Mat_ bigC=Mat_(1,(Func.rows==1?Func.cols:Func.rows)+1), bigB=Mat_(Constr.rows,Constr.cols+1); if(Func.rows==1){ Func.convertTo(bigC.colRange(1,bigC.cols),CV_64FC1); }else{ Mat FuncT=Func.t(); FuncT.convertTo(bigC.colRange(1,bigC.cols),CV_64FC1); } Constr.convertTo(bigB.colRange(1,bigB.cols),CV_64FC1); double v=0; vector N,B; if(initialize_simplex(bigC,bigB,v,N,B)==SOLVELP_UNFEASIBLE){ return SOLVELP_UNFEASIBLE; } Mat_ c=bigC.colRange(1,bigC.cols), b=bigB.colRange(1,bigB.cols); int res=0; if((res=inner_simplex(c,b,v,N,B))==SOLVELP_UNBOUNDED){ return SOLVELP_UNBOUNDED; } //return the optimal solution z.create(c.cols,1,CV_64FC1); MatIterator_ it=z.begin(); for(int i=1;i<=c.cols;i++,it++){ std::vector::iterator pos=B.begin(); if((pos=std::find(B.begin(),B.end(),i))==B.end()){ *it=0; }else{ *it=b.at(pos-B.begin(),b.cols-1); } } return res; } static int initialize_simplex(Mat_& c, Mat_& b,double& v,vector& N,vector& B){ N.resize(c.cols); N[0]=0; for (std::vector::iterator it = N.begin()+1 ; it != N.end(); ++it){ *it=it[-1]+1; } B.resize(b.rows); B[0]=N.size(); for (std::vector::iterator it = B.begin()+1 ; it != B.end(); ++it){ *it=it[-1]+1; } v=0; int k=0; { double min=DBL_MAX; for(int i=0;i=0){ N.erase(N.begin()); return 0; } Mat_ old_c=c.clone(); c=0; c(0,0)=-1; for(int i=0;i::iterator iterator=std::find(B.begin(),B.end(),0); if(iterator!=B.end()){ int iterator_offset=iterator-B.begin(); if(b(iterator_offset,b.cols-1)>0){ return SOLVELP_UNFEASIBLE; } pivot(c,b,v,N,B,iterator_offset,0); } { iterator=std::find(N.begin(),N.end(),0); int iterator_offset=iterator-N.begin(); std::iter_swap(iterator,N.begin()); swap_columns(c,iterator_offset,0); swap_columns(b,iterator_offset,0); } dprintf(("after swaps\n")); print_simplex_state(c,b,v,N,B); //start from 1, because we ignore x_0 c=0; v=0; for(int I=1;I& c, Mat_& b,double& v,vector& N,vector& B){ int count=0; while(1){ dprintf(("iteration #%d\n",count)); count++; static MatIterator_ pos_ptr; int e=-1,pos_ctr=0,min_var=INT_MAX; bool all_nonzero=true; for(pos_ptr=c.begin();pos_ptr!=c.end();pos_ptr++,pos_ctr++){ if(*pos_ptr==0){ all_nonzero=false; } if(*pos_ptr>0){ if(N[pos_ctr] min_row_ptr=b.begin(); for(MatIterator_ it=b.begin();it!=b.end();it+=b.cols,row_it++){ double myite=0; //check constraints, select the tightest one, reinforcing Bland's rule if((myite=it[e])>0){ double val=it[b.cols-1]/myite; if(val& c,Mat_& b,double& v,vector& N,vector& B, int leaving_index,int entering_index){ double Coef=b(leaving_index,entering_index); for(int i=0;i& A,int col1,int col2){ for(int i=0;i