% matlab implementation of the cocktail algorithm for D-optimal designs (approximate theory) % % [w, tm]=cocktail(X, maxiter, small, alg) % % required input % X: design matrix (n by m) % (n: number of design points) % (m: dimension of parameter) % % optional input % maxiter: maximum number of iterations (default=1000) % small: convergence threshold (default=1e-6) % alg: choice of algorithm (default=4) % alg=0: multiplicative algorithm only % alg=1: vertex exchange method (VEM) % alg=2: both the vertex direction method (VDM) and the multiplicative algorithm % alg=3: cocktail algorithm (VDM + nearest neighbor exchange + multiplicative algorithm) % alg=4: same as alg=3, except the nearest neighbors are computed on the fly % % output % w: optimal weights (1 by n) % tm: cpu time function [w, tm]=cocktail(X, maxiter, small, alg) if(nargin<=3) alg=4; if(nargin<=2) small=1e-6; if(nargin==1) maxiter=1000; end end end if(alg==0) fprintf('Using the multiplicative algorithm only\n'); end if(alg==1) fprintf('Using the vertex exchange method (VEM)\n'); end if(alg==2) fprintf('Using both the vertex direction method (VDM) and the multiplicative algorithm\n'); end if(alg==3) fprintf('Using the cocktail algorithm:\n'); fprintf('VDM + nearest neighbor exchange + multiplicative algorithm\n'); fprintf('The neighborhood structure is pre-specified\n'); end if(alg==4) fprintf('Using the cocktail algorithm:\n'); fprintf('VDM + nearest neighbor exchange + multiplicative algorithm\n'); fprintf('The nearest neighbors are computed on the fly\n'); end tm=cputime(); [n, m]=size(X); w=ones(1,n); if(alg>=1) w=zeros(1, n); w(1, floor(unifrnd(0, 1, 1, 2*m)*n)+1)=1; end w(w>0)=1/sum(w>0); %% starting design index=1:n; ind=index(w>0); Y=zeros(n, m); for(j=1:length(ind)) Y(ind(j), 1:m)=X(ind(j), 1:m)*w(ind(j)); end M=(Y(ind, 1:m))'*X(ind, 1:m); lam=1:n; for(i=1:maxiter) P=inv(M); for(j=1:n) lam(j)=X(j,1:m)*P*(X(j,1:m))'/m; end tmp=max(lam); if(tmp<1+small) %% testing convergence break; end if(alg==1) %% VEM step j2=max(index(tmp==lam)); tmp=min(lam(w>0)); j1=min(index(w>0&tmp==lam)); d=X([j1, j2], 1:m)*P*(X([j1, j2], 1:m))'; tmp=0.5*(d(1,1)-d(2,2))/(d(1,1)*d(2,2)-d(1,2)*d(2,1)+1e-200); tmp=max(min(tmp, w(j2)), -w(j1)); w(j1)=w(j1)+tmp; w(j2)=w(j2)-tmp; M=M+tmp*((X(j1, 1:m))'*X(j1, 1:m)-(X(j2, 1:m))'*X(j2, 1:m)); end if(alg>=2) %% VDM step j2=max(index(tmp==lam)); tmp=(tmp-1)/(m*tmp-1); w=(1-tmp)*w; w(j2)=w(j2)+tmp; M=(1-tmp)*M+tmp*(X(j2, 1:m))'*X(j2, 1:m); end if(alg>=3) %% nearest neighbor exchanges ind=index(w>0); for(j=1:(length(ind)-1)) j1=ind(j); j2=ind(j+1); if(alg==4) %% nearest neighbor computed on the fly near=1e+200; for(k=(j+1):length(ind)) tmp=sum(abs(X(j1, 1:m)-X(ind(k), 1:m))); if(near>tmp) near=tmp; j2=ind(k); end end end d=X([j1, j2], 1:m)*inv(M)*(X([j1, j2], 1:m))'; tmp=0.5*(d(1,1)-d(2,2))/(d(1,1)*d(2,2)-d(1,2)*d(2,1)+1e-200); tmp=max(min(tmp, w(j2)), -w(j1)); w(j1)=w(j1)+tmp; w(j2)=w(j2)-tmp; M=M+tmp*((X(j1, 1:m))'*X(j1, 1:m)-(X(j2, 1:m))'*X(j2, 1:m)); end end if(alg~=1) %% multiplicative step if(alg==0) w(ind)=w(ind).*lam(ind); else ind=index(w>0); P=inv(M); for(j=1:length(ind)) w(ind(j))=w(ind(j))*X(ind(j),1:m)*P*(X(ind(j),1:m))'/m; end end w(ind)=w(ind)/sum(w(ind)); %% redundant (numerical safeguard) for(j=1:length(ind)) Y(ind(j), 1:m)=X(ind(j), 1:m)*w(ind(j)); end M=(Y(ind, 1:m))'*X(ind, 1:m); end end %% end for tm=cputime()-tm; if(i==maxiter) fprintf('No convergence in %7d iterations\ncpu time: %14g seconds\n', maxiter, tm); else fprintf('Convergence in %7d iterations\ncpu time: %14g seconds\n', i, tm); end end