samer@0: package samer.mds; samer@0: samer@0: import samer.core.*; samer@0: import samer.core.types.*; samer@0: import samer.maths.*; samer@0: import samer.tools.*; samer@0: samer@0: /** samer@0: This is a version that does not use a separete metric and samer@0: stress function: the stress function is defined directly in terms samer@0: of the displacement vectors between objects. The distances samer@0: are now generalised link targets. samer@0: */ samer@0: public class NewMDS extends MDSBase samer@0: { samer@0: Stress stress; // stress function samer@0: samer@0: public interface Stress { samer@0: /** accumulate stress due to a link given end points, return gradient samer@0: in g, return true if gradient is usable, false of gradient is bad (eg singularity) */ samer@0: boolean add( double target, double [] x, double [] y, double [] g); samer@0: samer@0: /** return normalised stress and reset for next time */ samer@0: double done(); samer@0: samer@0: /** return last value returned by done() */ samer@0: double get(); samer@0: } samer@0: samer@0: public static class Laplacian implements Stress { samer@0: double S=0, a=0; samer@0: int n=0, E; samer@0: samer@0: public Laplacian(int E) { this.E=E; } samer@0: samer@0: /** add stress due to link from x to y. Force in link is returned in g. samer@0: Target is assumed to be a length measured according to a 1-norm. samer@0: */ samer@0: public boolean add( double target, double [] x, double [] y, double [] g) { samer@0: double b=0; samer@0: for (int i=0; i0) return +1; else return 0; samer@0: } samer@0: } samer@0: samer@0: public NewMDS(Matrix p) { samer@0: super(p); samer@0: Shell.push(node); samer@0: stress=new Laplacian(E); samer@0: Shell.pop(); samer@0: } samer@0: samer@0: public void run() samer@0: { samer@0: double [][] _P=P.getArray(); samer@0: double d, dS; samer@0: int i, j, k; samer@0: samer@0: // accumulate all forces on a per object basis samer@0: samer@0: for (k=0; k