package de.gaalop.visualizer.zerofinding;
import de.gaalop.dfg.MultivectorComponent;
import de.gaalop.visualizer.Point3d;
import de.gaalop.visualizer.ia_math.RealInterval;
import java.util.HashMap;
import java.util.LinkedList;
/**
* Implements a zero finder thread, which uses rays
* @author christian
*/
public class RayMethodThread extends Thread {
private float fromOY_Incl;
private float toOY_Excl;
private float a;
private float dist;
private double epsilon;
private HashMap<MultivectorComponent, Double> globalValues;
private CodePiece codePiece;
public LinkedList<Point3d> points = new LinkedList<Point3d>();
private boolean renderIn2d;
public RayMethodThread(float fromOY_Incl, float toOY_Excl, float a, float dist, HashMap<MultivectorComponent, Double> globalValues, CodePiece codePiece, double epsilon, boolean renderIn2d) {
this.fromOY_Incl = fromOY_Incl;
this.toOY_Excl = toOY_Excl;
this.a = a;
this.dist = dist;
this.globalValues = globalValues;
this.codePiece = codePiece;
this.epsilon = epsilon;
this.renderIn2d = renderIn2d;
}
@Override
public void run() {
if (renderIn2d)
run2d();
else
run3d();
}
private void run2d() {
HashMap<MultivectorComponent, RealInterval> values = new HashMap<MultivectorComponent, RealInterval>();
for (MultivectorComponent mvC: globalValues.keySet())
values.put(mvC, new RealInterval(globalValues.get(mvC)));
values.put(new MultivectorComponent("_V_oz", 0), new RealInterval(0));
float ox = -a;
values.put(new MultivectorComponent("_V_ox", 0), new RealInterval(ox));
for (float oy = fromOY_Incl; oy <= toOY_Excl; oy += dist) {
values.put(new MultivectorComponent("_V_oy", 0), new RealInterval(oy));
isolation(new RealInterval(0, 2*a),values);
}
}
private void run3d() {
HashMap<MultivectorComponent, RealInterval> values = new HashMap<MultivectorComponent, RealInterval>();
for (MultivectorComponent mvC: globalValues.keySet())
values.put(mvC, new RealInterval(globalValues.get(mvC)));
float ox = -a;
values.put(new MultivectorComponent("_V_ox", 0), new RealInterval(ox));
for (float oy = fromOY_Incl; oy <= toOY_Excl; oy += dist) {
values.put(new MultivectorComponent("_V_oy", 0), new RealInterval(oy));
for (float oz = -a; oz <= a; oz += dist) {
values.put(new MultivectorComponent("_V_oz", 0), new RealInterval(oz));
isolation(new RealInterval(0, 2*a),values);
}
}
}
/**
* Splits an interval as long as more than one root exists in this interval
* @param t The interval to be splitted
* @param values The gloabal values
*/
private void isolation(RealInterval t, HashMap<MultivectorComponent, RealInterval> values) {
final String product = codePiece.nameOfMultivector;
values.put(new MultivectorComponent("_V_t", 0), t);
IntervalEvaluater evaluater = new IntervalEvaluater(values);
evaluater.evaluate(codePiece);
RealInterval f = values.get(new MultivectorComponent(product,0));
if (f.lo() <= 0 && 0 <= f.hi()) {
RealInterval df = values.get(new MultivectorComponent(product+"D",0));
if (df.lo() <= 0 && 0 <= df.hi()) {
if (t.hi()-t.lo() > 0.05) {
double center = (t.lo()+t.hi())/2.0d;
isolation(new RealInterval(t.lo(), center), values);
isolation(new RealInterval(center, t.hi()), values);
} else {
double tCenter = (t.lo()+t.hi())/2.0d;
values.put(new MultivectorComponent("_V_t", 0), new RealInterval(tCenter));
evaluater = new IntervalEvaluater(values);
evaluater.evaluate(codePiece);
f = values.get(new MultivectorComponent(product,0));
if (Math.abs((f.lo()+f.hi())/2) <= epsilon)
points.add(new Point3d(
values.get(new MultivectorComponent("_V_ox", 0)).lo()+tCenter,
values.get(new MultivectorComponent("_V_oy", 0)).lo(),
values.get(new MultivectorComponent("_V_oz", 0)).lo()
));
}
} else {
refinement(t, values);
}
}
}
/**
* Given an interval, where only one root exists, find the root.
* @param t The interval
* @param values The global values
*/
private void refinement(RealInterval t, HashMap<MultivectorComponent, RealInterval> values) {
final String product = codePiece.nameOfMultivector;
MultivectorComponent pr = new MultivectorComponent(product, 0);
boolean refine = true;
double ce = 1000;
while (refine) {
double center = (t.lo()+t.hi())/2.0d;
values.put(new MultivectorComponent("_V_t", 0), new RealInterval(t.lo()));
IntervalEvaluater evaluater = new IntervalEvaluater(values);
evaluater.evaluate(codePiece);
double lo = values.get(pr).lo();
values.put(new MultivectorComponent("_V_t", 0), new RealInterval(center));
evaluater = new IntervalEvaluater(values);
evaluater.evaluate(codePiece);
ce = values.get(pr).lo();
if (Math.abs(ce) <= epsilon) refine = false;
if (t.hi()-t.lo() < 0.001) return;
if (ce*lo < 0)
t = new RealInterval(t.lo(),center);
else
t = new RealInterval(center,t.hi());
}
if (Math.abs(ce) <= epsilon)
points.add(new Point3d(
values.get(new MultivectorComponent("_V_ox", 0)).lo()+(t.lo()+t.hi())/2.0d,
values.get(new MultivectorComponent("_V_oy", 0)).lo(),
values.get(new MultivectorComponent("_V_oz", 0)).lo()
));
}
}