annotate src/samer/mds/MDS.java @ 8:5e3cbbf173aa tip

Reorganise some more
author samer
date Fri, 05 Apr 2019 22:41:58 +0100
parents bf79fb79ee13
children
rev   line source
samer@0 1 package samer.mds;
samer@0 2
samer@0 3 import samer.core.*;
samer@0 4 import samer.core.types.*;
samer@0 5 import samer.maths.*;
samer@0 6 import samer.tools.*;
samer@0 7
samer@0 8 /**
samer@0 9 This is an alternative version of MDS that uses less memory.
samer@0 10 Rather than keep a record of the force in each link, it accumulates
samer@0 11 the link forces on a per-object basis.
samer@0 12 */
samer@0 13 public class MDS extends MDSBase
samer@0 14 {
samer@0 15 Metric metric; // metric function
samer@0 16 Stress stress; // stress function
samer@0 17
samer@0 18 public interface Metric {
samer@0 19 /** return distance between x and y, put y-x in r */
samer@0 20 double d(double [] x, double [] y, double [] r);
samer@0 21 }
samer@0 22
samer@0 23 public interface Stress {
samer@0 24 /** accumulate stress due to a link and return dStress/dcurrent */
samer@0 25 double add( double target, double current);
samer@0 26
samer@0 27 /** return normalised stress and reset for next time */
samer@0 28 double done();
samer@0 29
samer@0 30 /** return last value returned by done() */
samer@0 31 double get();
samer@0 32 }
samer@0 33
samer@0 34 public static class SamerStress implements Stress {
samer@0 35 double S=0, a=0;
samer@0 36 int n=0;
samer@0 37
samer@0 38 public double add( double target, double current) {
samer@0 39 a += sqr(current/target-1); n++;
samer@0 40 return (current-target)/(target*target);
samer@0 41 }
samer@0 42 public double done() { S=a/n; a=0; n=0; return S; }
samer@0 43 public double get() { return S; }
samer@0 44 private final static double sqr(double t) {return t*t;}
samer@0 45 }
samer@0 46
samer@0 47 public MDS(Matrix p)
samer@0 48 {
samer@0 49 super(p);
samer@0 50
samer@0 51 Shell.push(node);
samer@0 52 metric=new Euclidean();
samer@0 53 stress=new SamerStress();
samer@0 54 Shell.pop();
samer@0 55 }
samer@0 56
samer@0 57 public void setMetric(Metric m) { metric=m; }
samer@0 58
samer@0 59 public void run()
samer@0 60 {
samer@0 61 double [][] _P=P.getArray();
samer@0 62 double d, dS;
samer@0 63 int i, j, k;
samer@0 64
samer@0 65 // accumulate all forces on a per object basis
samer@0 66
samer@0 67 for (k=0; k<N; k++) Mathx.zero(F[k]); // zero out object forces
samer@0 68 for (k=0; k<M; k++) { // for each link
samer@0 69 i=l1[k]; j=l2[k]; // object indices
samer@0 70 d=metric.d(_P[i],_P[j],f); // current distance, vector from i to j in f
samer@0 71 dS=stress.add(D[k],d);
samer@0 72
samer@0 73 if (d>0) { // ignore if current distance is zero
samer@0 74 // replace f with dS/dd * grad d
samer@0 75 Mathx.mul(f,dS/d);
samer@0 76
samer@0 77 // f contains 'force' on j from i
samer@0 78 // accumulate this force for both objects (only E dimensions used)
samer@0 79 Mathx.add(E,F[i],f);
samer@0 80 Mathx.sub(E,F[j],f);
samer@0 81 }
samer@0 82 }
samer@0 83 S.set(stress.done());
samer@0 84
samer@0 85 // now move objects at the ends of each link,
samer@0 86 // but only the first E dimensions
samer@0 87 for (k=0; k<N; k++) Mathx.muladd(E,_P[k],F[k],rate.value);
samer@0 88 P.changed();
samer@0 89 }
samer@0 90 }