comparison src/samer/mds/MDS.java @ 0:bf79fb79ee13

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