Mercurial > hg > jslab
view src/samer/mds/MDS.java @ 0:bf79fb79ee13
Initial Mercurial check in.
author | samer |
---|---|
date | Tue, 17 Jan 2012 17:50:20 +0000 |
parents | |
children |
line wrap: on
line source
package samer.mds; import samer.core.*; import samer.core.types.*; import samer.maths.*; import samer.tools.*; /** This is an alternative version of MDS that uses less memory. Rather than keep a record of the force in each link, it accumulates the link forces on a per-object basis. */ public class MDS extends MDSBase { Metric metric; // metric function Stress stress; // stress function public interface Metric { /** return distance between x and y, put y-x in r */ double d(double [] x, double [] y, double [] r); } public interface Stress { /** accumulate stress due to a link and return dStress/dcurrent */ double add( double target, double current); /** return normalised stress and reset for next time */ double done(); /** return last value returned by done() */ double get(); } public static class SamerStress implements Stress { double S=0, a=0; int n=0; public double add( double target, double current) { a += sqr(current/target-1); n++; return (current-target)/(target*target); } public double done() { S=a/n; a=0; n=0; return S; } public double get() { return S; } private final static double sqr(double t) {return t*t;} } public MDS(Matrix p) { super(p); Shell.push(node); metric=new Euclidean(); stress=new SamerStress(); Shell.pop(); } public void setMetric(Metric m) { metric=m; } public void run() { double [][] _P=P.getArray(); double d, dS; int i, j, k; // accumulate all forces on a per object basis for (k=0; k<N; k++) Mathx.zero(F[k]); // zero out object forces for (k=0; k<M; k++) { // for each link i=l1[k]; j=l2[k]; // object indices d=metric.d(_P[i],_P[j],f); // current distance, vector from i to j in f dS=stress.add(D[k],d); if (d>0) { // ignore if current distance is zero // replace f with dS/dd * grad d Mathx.mul(f,dS/d); // f contains 'force' on j from i // accumulate this force for both objects (only E dimensions used) Mathx.add(E,F[i],f); Mathx.sub(E,F[j],f); } } S.set(stress.done()); // now move objects at the ends of each link, // but only the first E dimensions for (k=0; k<N; k++) Mathx.muladd(E,_P[k],F[k],rate.value); P.changed(); } }