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 }