function [z,err] = lemke(M,q,z0) % syntax: [z,err] = lemke(M,q,z0) % LEMKE Solves linear complementarity problems (LCPs). % An LCP solves % Mz+q >=0, z>=0, z'(Mz+q)=0. % The input z0 defines a starting basis; it can be either % an initial guess of the solution or a vector of zeros and ones % with ones representing those z(i) thought to be non-zero in the % solution. For example, passing z=[1.5;0;2.2] has the same % effect as passing z=[1;0;1]. % If z0 is omitted the origin is used as a starting basis. % ERR returns an error condition: % 0: Solution found % 1: Maximum iterations exceeded % 2: Unbounded ray termination % If NARGOUT==1, a warning message is displayed instead. % % ALGORITHM % Uses a modified Lemke's algorithm (complementary pivoting) % with a covering ray of ones. The algorithm is modified to % allow a user defined initial basis. n = length(q); zer_tol = 1e-5; piv_tol = 1e-8; maxiter = min([1000 25*n]); err=0; % Trivial solution exists if all(q >= 0.) z=zeros(n,1); return; end z = zeros(2*n,1); j = zeros(n,1); % Determine initial basis if nargin<3 bas=(n+1:2*n)'; B = -speye(n); else bas=[find(z0>0);n+find(z0<=0)]; B = [sparse(M) -speye(n)]; B = B(:,bas); end % Determine initial values x=-(B\q); % Check if initial basis provides solution if all(x>=0) z(bas)=x; z=z(1:n); return end t = 2*n+1; % Artificial variable entering=t; % is the first entering variable % Determine initial leaving variable [tval,lvindex]=max(-x); leaving=bas(lvindex); bas(lvindex)=t; % pivot in the artificial variable x=x+tval; x(lvindex)=tval; B(:,lvindex)=-B*ones(n,1); % Main iterations begin here for iter=1:maxiter % Check if done; if not, get new entering variable if (leaving == t) break elseif (leaving <= n) entering = n+leaving; Be = sparse(leaving,1,-1.0,n,1); else entering = leaving-n; Be = M(:,entering); end d = B\Be; % Find new leaving variable j=find(d>piv_tol); % indices of d>0 if isempty(j) % no new pivots - ray termination err=2; break end theta=min((x(j)+zer_tol)./d(j)); % minimal ratios, d>0 j=j(find((x(j)./d(j))<=theta)); % indices of minimal ratios, d>0 lvindex=find(bas(j)==t); % check if artificial among these if ~isempty(lvindex) % Always use artifical if possible lvindex=j(lvindex); else % otherwise pick among set of max d theta=max(d(j)); lvindex=find(d(j)==theta); lvindex=j(ceil(length(lvindex)*rand)); % if multiple choose randomly end leaving=bas(lvindex); % Perform pivot ratio=x(lvindex)./d(lvindex); x = x - ratio*d; x(lvindex) = ratio; B(:,lvindex) = Be; bas(lvindex) = entering; end % end of iterations if iter>=maxiter & leaving~=t err=1; end z(bas) = x; z = z(1:n); % Display warning messages if no error code is returned if nargout<2 & err(1)~=0 s='Warning: solution not found - '; if err(1)==2 disp([s 'Unbounded ray']); elseif err(1)==1 disp([f 'Iterations exceeded limit']); end end