Winner Paulo Uribe (turbf1)

Finish 2002-05-23 00:00:00 UTC

cumbuild_n_09_02

by Stijn Helsen

Status: Failed
Results: []

Comments
Please login or create a profile.
Code
function xy = solver(kd,bx)

npts = size(kd,1);
dx=bx(2);
dy=bx(4);
D=dx+1i*dy;
lD=abs(D);
mxmx=max(kd(:));
kd(kd>lD)=lD;
xy = zeros(npts,1);
mx=max(kd-eye(npts));
ismart=find(mx>=0);
if ~isempty(ismart)&dx+dy>1e-3
	npts1=length(ismart);
	if npts1==2
		p=[0;D/lD*kd(ismart(1),ismart(2))];
		xy=zeros(npts,1);
		xy(ismart)=p;
		xy=[real(xy) imag(xy)];
		return
	end
	ipts=1:npts1;
	kd=kd(ismart,ismart);
	S=(kd-eye(npts1))>=0;
	p=zeros(npts1,1);
	if npts1>5
		p = solvecomplex(kd,S,dx,dy,p,0,npts1,inf);
		xy(ismart)=p;
	else
	pm=D/2;
	zerolen=lD/1e6;
	
	%k=kd;
	%k(k<0)=0;
	%mnd=mean(sum(k))/sqrt(npts1);
	%dx=min(mnd,dx);
	%dy=min(mnd,dy);
	
	if npts1==2
		xy(ismart(2))=D*kd(1,2)/lD;
	else
		k=kd-eye(npts1);
		S=k>=0;
		[mx,imx]=max(k);
	
		[mx1,jmx]=max(mx);
		i1=imx(jmx);
		j=ipts(jmx);
		i=ipts(i1);
		n=3;
		if mx1<=dx
			p(i)=pm+mx1/2;
			p(j)=pm-mx1/2;
		elseif mx1<=dy
			p(i)=pm+1i*mx1/2;
			p(j)=pm-1i*mx1/2;
		else
			p1=D*min(1,mx1/lD)/2;
			p(i)=pm+p1;
			p(j)=pm-p1;
		end
	
		if jmx==1
			if i1>2
				ipts(i1)=ipts(2);
				ipts(2)=i;
			end
		else
			if i1~=1
				ipts(i1)=ipts(1);
				ipts(1)=i;
			end
			if jmx~=2
				ipts(jmx)=ipts(2);
				ipts(2)=j;
			end
		end
		contloop=1;
		while contloop>0&n<=npts1
			sS=sum(S(ipts(1:n-1),ipts(n:end)),1);
			[n1,i1]=max(sS);
			i2=find(sS==n1);
			[mx1,jmx]=max(sum(kd(ipts(1:n-1),ipts(i2+n-1)),1));
			i1=i2(jmx);
			i=ipts(i1+n-1);
			if i>n
				ipts(i1+n-1)=ipts(n);
				ipts(n)=i;
			end
			if n1
				l=find(S(ipts(1:n-1),i));
				j=ipts(l);
				if n1==2
					dp=diff(p(j));
					d1=abs(dp);
					if d1<=zerolen
						n1=1;
						l=l(1);
						j=j(1);
					else
						d2=kd(j(1),i);
						d3=kd(j(2),i);
						if d2<=zerolen
							p(i)=p(j(1));
							n1=0;
						elseif d3<=zerolen
							p(i)=p(j(2));
							n1=0;
						elseif d1>=d2+d3
%							contloop=0;
							p(i)=p(j(1))+dp/d1*d2;	%verbeteren?
							n1=0;
						elseif d2>=d1+d3
%							contloop=0;
							p(i)=p(j(2))+dp/d1*d3;	%(?)
							n1=0;
						elseif d3>=d1+d2
%							contloop=0;
							n1=0;
							p(i)=p(j(1))-dp/d1*d2;	%?
						end
					end
				end
				switch n1
				case 0
					% do nothing (already processed)
				case 1
%					contloop=0;
%					break;
					% Now the direction is taken to have a point closest
					% to the center.  This is not always(/often?) best.
					if abs(p(j)-pm)<zerolen
						p(i)=pm+D/lD*k(j,i);
					else
						p1=pm-p(j);
						p(i)=p(1)+p1/abs(p1)*k(j,i);
					end
					p(i)=min(dx,max(0,real(p(i))))+1i*min(dy,max(0,imag(p(i))));
				case 2
					p(i)=calctriang(d1,d2,d3,p(j(1)),dp,pm);
				otherwise
					P=meshgrid(p(j));
					dP=abs(P-P.');
					[I,J]=find(triu(dP));
					IJ=(I-1)*n1+J;
					[d,id]=sort(-dP(IJ));
					I=I(id);
					J=J(id);
					n2=min(6,n1);
					pp=zeros(n2,2);
					ok=zeros(n2,1);
					for k=1:n2
						d1=-d(k);
						d2=kd(j(I(k)),i);
						d3=kd(j(J(k)),i);
						p1=p(j(I(k)));
						p2=p(j(J(k)));
						if abs((d1*d1+d2*d2-d3*d3)/2/d1/d2)<1
							ok(k)=1;
							[pp(k,1),pp(k,2)]=calctriang(d1,d2,d3,p1,p2-p1,pm);
						end
					end
					iok=find(ok);
					if isempty(iok)
						contloop=0;
					elseif length(iok)==1
						if abs(pp(iok,1)-pm)<=abs(pp(iok,2)-pm)
							p(i)=pp(iok);
						else
							p(i)=pp(iok);
						end
						contloop=-1;
					else
						pp=pp(iok,:);
						pp=pp(:);
						[P1,P2]=meshgrid(p(j),pp);
						dP=sum(abs(abs(P1-P2)-kd(i*ones(length(pp),1),j)),2);
						[P,n1]=min(dP);
						p(i)=pp(n1);
						if P>0.1
							contloop=-1;
						end
					end
				end
			else	% n1==0
%				fprintf('!!!!4\n');
%				p(i)=pm;	% terug zoeken naar twee elementen?
				contloop=0;
					% vermits er al getest is of er gescheiden blokken
					% zijn, en dat de "dummy's" er al uit zijn,
					% zou dit niet kunnen voorkomen.
			end
			if contloop
				p(ipts(1:n))=limitpoint(p(ipts(1:n)),dx,dy);
				n=n+1;
			end
		end	% place points
%		[n npts1]
		if n<=npts1|1	% (doing something else if all points a set ?)
			n=n-1;
			i=ipts(1:n);
			pi=p(i);
			mnx=min(real(pi));
			mxx=max(real(pi));
			mny=min(imag(pi));
			mxy=max(imag(pi));
			p(i)=pi+(pm-((mxx+mnx)+1i*(mxy+mny))/2);
			kd1=kd(ipts,ipts);
			S1=S(ipts,ipts);
			p=p(ipts);
			s1=findstrain(S1,p,kd1);
			s2=findstrain(S1,zeros(npts1,1),kd1);
			if s1>s2
				n=0;
				s1=s2;
			end
			p(ipts) = solvecomplex(kd1,S,dx,dy,p(ipts),n,npts1,s1);
		end
		xy(ismart) = p;
	end
	end
end
xy=[real(xy) imag(xy)];

function [p2,p22]=calctriang(d1,d2,d3,p0,dp,pm)
g=acos((d1*d1+d2*d2-d3*d3)/2/d2/d1);
p21=p0+exp( 1i*g)*dp/d1*d2;
p22=p0+exp(-1i*g)*dp/d1*d2;
if nargout>1
	p2=p21;
elseif abs(p21-pm)<abs(p22-pm)
	p2=p21;
else
	p2=p22;
end

function p=limitpoint(p0,dx,dy)
p=p0;
rp2=real(p(end));
ip2=imag(p(end));
if rp2<0|rp2>dx
	dtot=max(real(p))-min(real(p));
		% (ook konstant bij te houden)
	if dtot<dx
		if rp2<0
			p=p-max(rp2,dtot-dx);
			p(end)=max(0,real(p(end)))+1i*imag(p(end));
		else
			p=p-min(rp2-dx,dx-dtot);
			p(end)=min(dx,real(p(end)))+1i*imag(p(end));
		end
	elseif rp2<0
		p(end)=1i*imag(p(end));
	elseif rp2>dx
		p(end)=dx+1i*imag(p(end));
	end
end
if ip2<0|ip2>dy
	dtot=max(imag(p))-min(imag(p));
		% (ook konstant bij te houden)
	if dtot<dy
		if ip2<0
			p=p-1i*max(ip2,dtot-dy);
			p(end)=real(p(end))+1i*max(0,real(p(end)));
		else
			p=p-1i*min(ip2-dy,dy-dtot);
			p(end)=real(p(end))+1i*min(dy,imag(p(end)));
		end
	elseif ip2<0
		p(end)=real(p(end));
	elseif ip2>dy
		p(end)=real(p(end))+1i*dy;
	end
end

function xy = solvecomplex(kd,S,dx,dy,xy0,npt0,npts,olds)
D=dx+1i*dy;
pm=D/2;
xy = xy0(:).';
xy(npt0+1:end)=pm;

d=0.1*max(dx,dy);
x=0:d:dx;
y=0:d:dy;

[xx,yy] = ndgrid(x,1i*y);
[nx,ny]=size(xx);
XX=[0;xx(:)+yy(:)];

nX=length(XX);
xOnes=ones(nX,1);
xZeros=zeros(nX,1);
start=1;
iones=ones(1,npts);
sCut = 1;

[dum,p]=sort(-max(kd));
S=S(p,p);
kd=kd(p,p);
[v,w]=sort(p);
for iter=1:7
    for index = npt0+1:npts
        I = find(S(:,index)); 
        if ~isempty(I)
			XX(1)=xy(index);
            st = sum(abs(abs(XX(:,ones(size(I)))-xy(xOnes,I))-kd(xZeros+index,I)),2);
            [null,minloc] = min(st);
            xy(index) = XX(minloc);
        end
    end
    [s,M]=findstrain(S,xy,kd);
    if((abs(s-olds)/(s+1)) < 0.002) | s < sCut
        break;
    end
    olds = s;
	npt1=0;
end
xy=xy.';
xy=xy(w,:);
kd=kd(w,w);
S=S(w,w);

olds = 1.0e50;
oldxy = xy;
alpha = 1;

for iter=1:40
    [s,M]=findstrain(S,xy,kd);
    if( iter > 5 & abs(s-olds) / (s+1) < 0.0001 ) | s < sCut
        xy = oldxy;
        break;
    end
    
    if( s > olds )
        xy = oldxy;
        break;
    end
    oldxy = xy;
    olds = s;
    for indx = 1:npts
        I = find(S(:,indx)>0);
        dX=xy(I)-xy(indx);
        Dx=mean(dX.*(1-kd(I,indx)./(abs(dX)+eps)));
%            Dx=mean(dX./(abs(dX)+eps) .* M(I,indx));
        
        xy(indx) = xy(indx) + alpha*Dx;
        xy(indx) = min(dx,max(0,real(xy(indx))))+1i*min(dy,max(0,imag(xy(indx))));
    end
end

alpha = 0.1;
ngrad = 30;

obj = 1.0e20*ones(ngrad,1);
xybig = zeros(npts,ngrad);

[objnew,strainMatrix]=findstrain(S,xy,kd);
obj(1) = objnew;
xybig(:,1) = xy;
gradient = zeros(npts,1);

for ij=2:ngrad
   [s,sM,dM]=findstrain(S,xy,kd);
   gradient(:) = sum(dM./(abs(dM)+eps).*sign(sM));
   
   xy = xy - alpha  * gradient;
	xy = min(max(real(xy),0),dx) + 1j * min(max(imag(xy),0),dy);
   [objnew,strainMatrix]=findstrain(S,xy,kd);
   
   obj(ij) = objnew;
   xybig(:,ij) = xy;
   if( obj(ij) > obj(ij-1) )
       xy = xybig(:,ij-1);
       alpha = alpha / 10;
   else
       alpha = alpha * 2;
   end
   [bestobj,index] = min(obj);
   if( ij > 3 & index < 2 ) | bestobj < sCut
      break
  end
end
[bestobj,index] = min(obj);
xy = xybig(:,index);

function [s,strainMatrix,dX]=findstrain(S,xy,kd)
sI=find(S);
strainMatrix=S;
dX=S;
[X1,X2]=meshgrid(xy); 
dX(sI)=X1(sI)-X2(sI);
strainMatrix(sI) = abs(dX(sI))-kd(sI);
s = sum(abs(strainMatrix(sI)));