function [phi, X, y] = maxcut( L); % function [phi, X, y] = maxcut( L); % solves: max trace(LX) s.t. X psd, diag(X) = b; b = ones(n,1)/4 % min b'y s.t. Diag(y) - L psd, y unconstrained, % input: L ... symmetric matrix % output: phi ... optimal value of primal, phi =trace(LX) % X ... optimal primal matrix % y ... optimal dual vector % call: [phi, X, y] = psd_ip( L); digits = 8; % 8 significant digits of phi [n, n1] = size( L); % problem size L(1:n+1:end)=zeros(n,1); b = ones( n,1 ) / 4; % any b>0 works just as well X = diag( b); % initial primal matrix is pos. def. y = sum( abs( L))' * 1.1; % initial y is chosen so that Z = diag( y) - L; % initial dual slack Z is pos. def. phi = b'*y; % initial dual psi = L(:)' * X( :); % and primal costs mu = Z( :)' * X( :)/( 2*n); % initial complementarity iter=0; % iteration count disp([' iter alphap alphad -log10(gap) lower upper']); while phi-psi > max([1,abs(phi)]) * 10^(-digits) iter = iter + 1; % start a new iteration Zi = inv( Z); % inv(Z) is needed explicitly Zi = (Zi + Zi')/2; dy = (Zi.*X) \ (mu * diag(Zi) - b); % solve for dy dX = - Zi * diag( dy) * X + mu * Zi - X; % back substitute for dX dX = ( dX + dX')/2; % symmetrize % line search on primal alphap = 2; % initial steplength changed to 2 % alphap = 1; % initial steplength [dummy,posdef] = chol( X + alphap * dX ); % test if pos.def while posdef > 0, alphap = alphap * .8; [dummy,posdef] = chol( X + alphap * dX ); end; alphap = alphap * .95; % stay away from boundary % line search on dual; dZ is handled implicitly: dZ = diag( dy); % alphad = 1; alphad = 2; % initial steplength changed to 2 [dummy,posdef] = chol( Z + alphad * diag(dy) ); while posdef > 0; alphad = alphad * .8; [dummy,posdef] = chol( Z + alphad * diag(dy) ); end; alphad = alphad * .95; % update X = X + alphap * dX; y = y + alphad * dy; Z = Z + alphad * diag(dy); mu = X( :)' * Z( :) / (2*n); if alphap + alphad > 1.8, mu = mu/2; end; % speed up for long steps phi = b' * y; psi = L( :)' * X( :); % display current iteration disp([ iter alphap alphad -log10(phi-psi) psi phi ]); end; % end of main loop disp(['maxcut ended: -log10((phi-psi)/(1+abs(psi))) is: ',... num2str( -log10( (phi-psi)/(1+abs(psi)) ) )]);