function [x,y,z] = dMinLin( x,y,z, d, tol ) % dMinimize - minimizes square error of distances % [x,y,z] = dMinimize( x0,y0,z0, d, epsilon ) % x0, y0, z0 - 1D column vectors, initial estimates of the points coordinates. % d - matrix of distances between points, d(i,j)=distance between points i and j % epsilon - required precision % x,y,z - result points % A matrix with distances between n 3D points is given (d). % The problem is to find cartesian coordinates of the points. % For further explanations look at the end of the file n = size(d,1); % Newton method - works when close to solution % Algorithm: % 1. Calculate g, G where g=d(e^2)/dx, G=d^2(e^2)/(dxi dxj), e is error % 2. While G+ni*I is not positive definite, ni=ni*4 % 3. Solve (G + ni*I) * d = -g for d % 4. r = (f(x+d)-f(x))/(q(x+d)-q(x)), where f is squared error, q is quadratic approximation of f % 5. if r<0.25, ni=4*ni; elseif r>0.75, ni=0.5*ni; % 6. if r>0, x = x + d % 7. Goto 1 until errorepsilon ), while( det(Gx+nix*eye(n))<0 ), nix = 4*nix; end; while( det(Gy+niy*eye(n))<0 ), niy = 4*niy; end; while( det(Gz+niz*eye(n))<0 ), niz = 4*niz; end; dx = - 1/nix*gx; dy = - 1/niy*gy; dz = - 1/niz*gz; rx = ( dErrorF(x+dx,y,z,d,tt)-e )/( dx'*gx + 0.5*dx'*Gx*dx ); ry = ( dErrorF(x,y+dy,z,d,tt)-e )/( dy'*gy + 0.5*dy'*Gy*dy ); rz = ( dErrorF(x,y,z+dz,d,tt)-e )/( dz'*gz + 0.5*dz'*Gz*dz ); if (rx<0.25), nix=4*nix; elseif (rx>0.75), nix=0.5*nix; end; if (ry<0.25), niy=4*niy; elseif (ry>0.75), niy=0.5*niy; end; if (rz<0.25), niz=4*niz; elseif (rz>0.75), niz=0.5*niz; end; if (rx>0 & 0*rx<100), x = x + dx; else, nix = 4*nix; end; if (ry>0 & 0*ry<100), y = y + dy; else, niy = 4*niy; end; if (rz>0 & 0*rz<100), z = z + dz; else, niz = 4*niz; end; [e, gx,gy,gz, Gx,Gy,Gz, maxe] = dErrorF(x,y,z,d); counter = counter + 1; disp([e, rx, nix, counter] ); end; %while %Additional coments: % Problem definition: % A n*n matrix (d) with distances between the points is given so that % d(i,j) = distance between point i and point j % d2(i,j) = d(i,j)^2 = (x(i)-x(j))^2+(y(i)-y(j))^2+(z(i)-z(j))^2 + noise % matrix d2 should be idealy symetric, but due to the noise, it is not. % % The minimization function is squared error: % f = sum_i(sum_j( e(i,j)^2 )) % The first derivative % df(x)/dx(i) = g(i) = sum_j( 4*(x(i)-x(j))*e(i,j) ); % The second derivative % d^2 f(x)/ dx(i)dx(j) = G(i,j) = -4*[ e(i,j) + 2*(x(i)-x(j))^2 ] % Taylor series is: % f(x+h) = f(x) + h'*g(x) + 1/2*h'*G(x)*h + o(h'*h) % The quadratic approximation is: % q(x) = f(x) % q(x+h) = f(x) + h'*g(x) + 1/2*h'*G(x)*h % => Dq = h'*g(x) + 1/2*h'*G(x)*h % Convergence ratio: % r = Df / Dq = ( f(x+h)-f(x) ) / Dq % % Accuracy: (xi-xj) = x0+2*eps => % (x(i)-x(j))^2+(y(i)-y(j))^2+(z(i)-z(j))^2-d(i,j)^2= % = (x0+2*eps)^2+(y0+2*eps)^2+(z0+2*eps)^2 - d^2 = % = (x0^2+y0^2+z0^2 - d^2) + 4*eps*(x0+y0+z0) + 3*4*eps^2 =~ % =~ 4*eps*(x0+y0+z0) =~ 3*4*eps*mean(x) =~ 12*eps*mean(d/2)=6*eps*mean(d) => % => sum(sum( e^2 )) =~ (6*eps)^2 * sum(sum(d^2))