Mercurial > hg > jslab
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 } |