Mercurial > hg > jslab
view src/samer/mds/NewMDS.java @ 8:5e3cbbf173aa tip
Reorganise some more
author | samer |
---|---|
date | Fri, 05 Apr 2019 22:41:58 +0100 |
parents | bf79fb79ee13 |
children |
line wrap: on
line source
package samer.mds; import samer.core.*; import samer.core.types.*; import samer.maths.*; import samer.tools.*; /** This is a version that does not use a separete metric and stress function: the stress function is defined directly in terms of the displacement vectors between objects. The distances are now generalised link targets. */ public class NewMDS extends MDSBase { Stress stress; // stress function public interface Stress { /** accumulate stress due to a link given end points, return gradient in g, return true if gradient is usable, false of gradient is bad (eg singularity) */ boolean add( double target, double [] x, double [] y, double [] g); /** return normalised stress and reset for next time */ double done(); /** return last value returned by done() */ double get(); } public static class Laplacian implements Stress { double S=0, a=0; int n=0, E; public Laplacian(int E) { this.E=E; } /** add stress due to link from x to y. Force in link is returned in g. Target is assumed to be a length measured according to a 1-norm. */ public boolean add( double target, double [] x, double [] y, double [] g) { double b=0; for (int i=0; i<E; i++) { b+=Math.abs(x[i]-y[i]); g[i]=sgn(x[i]-y[i]); } b += sqr(b/target-1); n++; Mathx.mul(g,(b-target)/(target*target)); return true; } /** finish accumulating stress terms: reset accumulators for next iteration and return normalised stress (ie per link) */ public double done() { S=a/n; a=0; n=0; return S; } /** return last stress value */ public double get() { return S; } private final static double sqr(double t) {return t*t;} private final static double sgn(double t) { if (t<0) return -1; else if (t>0) return +1; else return 0; } } public NewMDS(Matrix p) { super(p); Shell.push(node); stress=new Laplacian(E); Shell.pop(); } public void run() { double [][] _P=P.getArray(); double d, dS; int i, j, k; // accumulate all forces on a per object basis for (k=0; k<N; k++) Mathx.zero(F[k]); // zero out object forces for (k=0; k<M; k++) { // for each link i=l1[k]; j=l2[k]; // object indices if (stress.add(D[k],_P[j],_P[i],f)) { Mathx.add(E,F[i],f); Mathx.sub(E,F[j],f); } } S.set(stress.done()); // now move objects at the ends of each link, // but only the first E dimensions for (k=0; k<N; k++) Mathx.muladd(E,_P[k],F[k],rate.value); P.changed(); } }