function [x,y,ez,flag] = simplex(A,b,c,x0,B0) % function [x,y,z,flag] = simplex(A,b,c,x0,B0) % Fernando Guevara Vasquez - Oct. 2004 % Solves the LP % % min c'*x % s.t. Ax=b, x>=0. % % using the simplex method. Based on Chapter 13 in Nocedal and Wright. % % inputs: % A mxn matrix (m0 % outputs: % x n vector optimal solution to the LP (only if flag==0) % y m vector optimal Lagrange multipliers (only if flag==0) % z n vector optimal slacks (only if flag==0) % flag 0 if optimal solution was found % 1 if problem is unbounded % 2 if big-M method failed to find a bfp (which maybe due to M % not being big enough) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % parameters eps = 1e-10; M = 1e6; debug=1; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % sanity checks m=size(A,1); n=size(A,2); if (m>=n) error('must have m=4) if (n~=size(x0,1) | 1~=size(x0,2)) error('x0 must be an nx1 vector'); end; % find the basis set for x0 (if not given) if (nargin==5) B = B0; else B = find(x0>0); end; if (length(B)~=m) error('start bfp does not have exactly m non zero entries'); end; % some checks to see if (x0,B) is really a bfp % check feasability of x0 if (any(x0<0)) error('x0 not feasible: it has negative entries!!'); end; if (norm(A*x0-b,inf)>eps) error('x0 not feasible: Ax0 != b '); end; % check all components outside basis are zero if ( sum(x0(setdiff(1:n,B)))>eps ) error('not all components of x0 outside basis set are zero'); end; % check A(:,B) is invertible if (rank(A(:,B)) big-M method\n'); end; E = 1*(b>=0) -1*(b<0); % I don't use sign since sign(0)=0 E = diag(E); [xM,yM,zM,xMflag] = simplex([A E],b,[c; M*ones(m,1)],... [zeros(n,1); abs(b)],n+1:n+m); x = xM(1:n); y = yM; ez = zM(1:n); flag = 2*xMflag; return; end; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % main loop icount=0; while (1) icount=icount+1; if (debug) fprintf('-- iteration %d\n',icount); fprintf('B: '); fprintf('%d ',B); fprintf('\n'); end; I = setdiff(1:n,B); % 1) y = A(:,B)'\c(B); z = c(I) - A(:,I)'*y; % 2) check for solution if (all(z>=0)) % we have found a solution flag=0; if (debug) fprintf('\n** simplex found optimal solution\n'); end; % expand z ez = zeros(n,1); ez(I) = z; return; end; % 3) choose entering index q according to Bland's rule to avoid cycling % (ie choose the smallest) iq = find(z<0); iq = iq(1); q = I(iq); % 4) Compute descent direction d = - A(:,B)\A(:,q); % 5) check for unboundedness if (all(d>=0)) % the problem is unbounded flag=1; if (debug) fprintf('\n** the problem is unbounded\n'); end; % expand z ez = zeros(n,1); ez(I) = z; return; end; % 6) Choose the index that we are replacing q with idx = B(find(d<0)); tmp = -x(idx)./d(find(d<0)); t = min(tmp); % use Bland's rule: find the smallest one realizing the min l = idx(find(t==tmp)); l = l(1); % 7) update x and the basis B x(B) = x(B) + t*d; % we are doing the op. for x(l) too x(q) = t; B = [ setdiff(B,l) q]; x(setdiff(1:n,B)) = 0; % but here x(l) = 0 end;