Mercurial > hg > jslab
comparison src/samer/mds/NewMDS.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 a version that does not use a separete metric and | |
10 stress function: the stress function is defined directly in terms | |
11 of the displacement vectors between objects. The distances | |
12 are now generalised link targets. | |
13 */ | |
14 public class NewMDS extends MDSBase | |
15 { | |
16 Stress stress; // stress function | |
17 | |
18 public interface Stress { | |
19 /** accumulate stress due to a link given end points, return gradient | |
20 in g, return true if gradient is usable, false of gradient is bad (eg singularity) */ | |
21 boolean add( double target, double [] x, double [] y, double [] g); | |
22 | |
23 /** return normalised stress and reset for next time */ | |
24 double done(); | |
25 | |
26 /** return last value returned by done() */ | |
27 double get(); | |
28 } | |
29 | |
30 public static class Laplacian implements Stress { | |
31 double S=0, a=0; | |
32 int n=0, E; | |
33 | |
34 public Laplacian(int E) { this.E=E; } | |
35 | |
36 /** add stress due to link from x to y. Force in link is returned in g. | |
37 Target is assumed to be a length measured according to a 1-norm. | |
38 */ | |
39 public boolean add( double target, double [] x, double [] y, double [] g) { | |
40 double b=0; | |
41 for (int i=0; i<E; i++) { | |
42 b+=Math.abs(x[i]-y[i]); | |
43 g[i]=sgn(x[i]-y[i]); | |
44 } | |
45 b += sqr(b/target-1); n++; | |
46 Mathx.mul(g,(b-target)/(target*target)); | |
47 return true; | |
48 } | |
49 | |
50 /** finish accumulating stress terms: reset accumulators for next | |
51 iteration and return normalised stress (ie per link) | |
52 */ | |
53 public double done() { S=a/n; a=0; n=0; return S; } | |
54 | |
55 /** return last stress value */ | |
56 public double get() { return S; } | |
57 private final static double sqr(double t) {return t*t;} | |
58 private final static double sgn(double t) { | |
59 if (t<0) return -1; else if (t>0) return +1; else return 0; | |
60 } | |
61 } | |
62 | |
63 public NewMDS(Matrix p) { | |
64 super(p); | |
65 Shell.push(node); | |
66 stress=new Laplacian(E); | |
67 Shell.pop(); | |
68 } | |
69 | |
70 public void run() | |
71 { | |
72 double [][] _P=P.getArray(); | |
73 double d, dS; | |
74 int i, j, k; | |
75 | |
76 // accumulate all forces on a per object basis | |
77 | |
78 for (k=0; k<N; k++) Mathx.zero(F[k]); // zero out object forces | |
79 for (k=0; k<M; k++) { // for each link | |
80 i=l1[k]; j=l2[k]; // object indices | |
81 if (stress.add(D[k],_P[j],_P[i],f)) { | |
82 Mathx.add(E,F[i],f); | |
83 Mathx.sub(E,F[j],f); | |
84 } | |
85 } | |
86 S.set(stress.done()); | |
87 | |
88 // now move objects at the ends of each link, | |
89 // but only the first E dimensions | |
90 for (k=0; k<N; k++) Mathx.muladd(E,_P[k],F[k],rate.value); | |
91 P.changed(); | |
92 } | |
93 } |