parallel constraint

This commit is contained in:
Val Erastov 2014-09-20 21:00:35 -07:00
parent 789d9f0aee
commit 3dadb83248
7 changed files with 268 additions and 110 deletions

View file

@ -7,6 +7,7 @@ import cad.gcs.GradientDescent3;
import cad.gcs.Param;
import cad.gcs.Solver;
import cad.gcs.constr.Constraint2;
import cad.gcs.constr.Parallel;
import cad.gcs.constr.Perpendicular;
import cad.gcs.constr.Perpendicular2;
import cad.gcs.constr.X;
@ -57,9 +58,9 @@ public class App2DCtrl implements Initializable {
Line l1 = new Line(100, 100, 300, 600);
Line l2 = new Line(400, 600, 600, 100);
content.getChildren().addAll(l1, l2);
Line l3 = new Line(650, 100, 800, 600);
content.getChildren().addAll(l1, l2, l3);
solve.setOnAction(event -> {
@ -74,13 +75,16 @@ public class App2DCtrl implements Initializable {
Param l1p1y = new Param(l1.getStartY());
Param l1p2x = new Param(l1.getEndX());
Param l1p2y = new Param(l1.getEndY());
Param l2p1x = new Param(l2.getStartX());
Param l2p1y = new Param(l2.getStartY());
Param l2p2x = new Param(l2.getEndX());
Param l2p2y = new Param(l2.getEndY());
Perpendicular2 perpendicular2 = new Perpendicular2(as, ae, bs, be);
Param l3p1x = new Param(l3.getStartX());
Param l3p1y = new Param(l3.getStartY());
Param l3p2x = new Param(l3.getEndX());
Param l3p2y = new Param(l3.getEndY());
Perpendicular perpendicular = new Perpendicular(
@ -94,6 +98,17 @@ public class App2DCtrl implements Initializable {
l2p2y
);
Parallel parallel = new Parallel(
l3p1x,
l3p1y,
l3p2x,
l3p2y,
l2p1x,
l2p1y,
l2p2x,
l2p2y
);
XY xy = new XY(as, new Vector(100, 100));
@ -120,9 +135,9 @@ public class App2DCtrl implements Initializable {
// solveGC(subSystem);
java.lang.System.out.println(perpendicular.angle());
java.lang.System.out.println("ANGLE |- :" + perpendicular.angle());
java.lang.System.out.println("ANGLE || :" + parallel.angle());
Constraint2 constr = perpendicular2;
// Constraint2 constr = xy;
// Constraint constr = perpendicular;
@ -146,17 +161,39 @@ public class App2DCtrl implements Initializable {
l1.setStartY(l1p1y.get());
l1.setEndX(l1p2x.get());
l1.setEndY(l1p2y.get());
l2.setStartX(l2p1x.get());
l2.setStartY(l2p1y.get());
l2.setEndX(l2p2x.get());
l2.setEndY(l2p2y.get());
});
l3.setStartX(l3p1x.get());
l3.setStartY(l3p1y.get());
l3.setEndX(l3p2x.get());
l3.setEndY(l3p2y.get());
// scale(l1);
// scale(l2);
// scale(l3);
});
}
double xxx = 100;
private void scale(Line l) {
Vector v = new Vector(l.getEndX() - l.getStartX(), l.getEndY() - l.getStartY());
v = v.normalize().multi(200);
l.setStartX(xxx += 100.);
l.setStartY(500.);
l.setEndX(l.getStartX() + v.x);
l.setEndY(l.getStartY() + v.y);
}
private void solveGC(final Solver.SubSystem subSystem) {
GaussNewtonOptimizer optimizer = new GaussNewtonOptimizer((iteration, previous, current) -> {
return subSystem.value() < 0.00000001;
return subSystem.value() < 0.00001;
}) {
@Override

View file

@ -4,8 +4,6 @@ public interface Constraint extends System {
double error();
void step(double alpha);
void set(double[] input);
}

View file

@ -15,6 +15,9 @@ import org.apache.commons.math3.linear.QRDecomposition;
import org.apache.commons.math3.linear.RealMatrix;
import org.apache.commons.math3.linear.SingularMatrixException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
public class Solver {
@ -401,7 +404,7 @@ public class Solver {
try {
h = new LUDecomposition(A).getSolver().solve(g);
} catch (Exception ssse) {
java.lang.System.out.println( "");
ssse.printStackTrace();
return SolveStatus.Success;
}
@ -675,20 +678,38 @@ public class Solver {
return new Array2DRowRealMatrix(rsize, csize);
}
static class ParamInfo {
final int id;
final List<Constraint> constraints = new ArrayList<>();
ParamInfo(int id) {
this.id = id;
}
}
public static class SubSystem {
private final List<Constraint> constraints;
private final LinkedHashMap<Param, ParamInfo> params = new LinkedHashMap<>();
public SubSystem(List<Constraint> constraints) {
this.constraints = constraints;
for (Constraint c : constraints) {
for (Param p : c.getParams()) {
ParamInfo paramInfo = params.get(p);
if (paramInfo == null) {
paramInfo = new ParamInfo(params.size());
params.put(p, paramInfo);
}
paramInfo.constraints.add(c);
}
}
}
public int pSize() {
int s = 0;
for (Constraint c : constraints) {
s += c.params().length;
}
return s;
return params.size();
}
public int cSize() {
@ -697,40 +718,23 @@ public class Solver {
public void fillParams(RealMatrix x) {
int i = 0;
TDoubleList params = new TDoubleArrayList();
for (Constraint c : constraints) {
params.add(c.params());
}
x.setColumn(0, params.toArray());
x.setColumn(0, getParams().toArray());
}
public TDoubleList getParams() {
int i = 0;
TDoubleList params = new TDoubleArrayList();
for (Constraint c : constraints) {
params.add(c.params());
TDoubleList params_ = new TDoubleArrayList();
for (Param p : params.keySet()) {
params_.add(p.get());
}
return params;
return params_;
}
public TDoubleList getValues2() {
TDoubleList params = new TDoubleArrayList();
for (Constraint c : constraints) {
double err = c.error();
params.add(err);
}
return params;
}
public TDoubleList getValues() {
TDoubleList params = new TDoubleArrayList();
TDoubleList values = new TDoubleArrayList();
for (Constraint c : constraints) {
params.add(c.error());
values.add(c.error());
}
return params;
return values;
}
public double calcResidual(RealMatrix r) {
@ -778,51 +782,34 @@ public class Solver {
}
for (int i=0; i < constraints.size(); i++) {
Constraint c = constraints.get(i);
double[] grad = new double[c.params().length];
Param[] cParams = c.getParams();
double[] grad = new double[cParams.length];
c.gradient(grad);
for (int j=0; j < grad.length; j++) {
jacobi.setEntry(i,j, grad[j]);
for (int p = 0; p < cParams.length; p++) {
Param param = cParams[p];
int j = params.get(param).id;
jacobi.setEntry(i,j, grad[p]);
}
}
}
public RealMatrix makeJacobi() {
RealMatrix jacobi = new Array2DRowRealMatrix(cSize(), pSize());
for (int j=0; j < pSize(); j++) {
for (int i=0; i < constraints.size(); i++) {
jacobi.setEntry(i, j, 0);
}
}
for (int i=0; i < constraints.size(); i++) {
Constraint c = constraints.get(i);
double[] grad = new double[c.params().length];
c.gradient(grad);
for (int j=0; j < grad.length; j++) {
jacobi.setEntry(i,j, grad[j]);
}
}
calcJacobi(jacobi);
return jacobi;
}
public void setParams(RealMatrix params) {
int off = 0;
double[] arr = params.getColumn(0);
for (Constraint c : constraints) {
int l = c.params().length;
double[] cp = new double[l];
java.lang.System.arraycopy(arr, off, cp, 0, l);
c.set(cp);
}
setParams(params.getData()[0]);
}
public void setParams(double[] arr) {
int off = 0;
for (Constraint c : constraints) {
int l = c.params().length;
double[] cp = new double[l];
java.lang.System.arraycopy(arr, off, cp, 0, l);
c.set(cp);
Iterator<Param> pit = params.keySet().iterator();
for (double v : arr) {
pit.next().set(v);
}
}
@ -831,15 +818,7 @@ public class Solver {
}
public void calcGrad(RealMatrix out) {
int cc = 0;
for (Constraint c : constraints) {
double[] grad = new double[c.params().length];
c.gradient(grad);
for (double aGrad : grad) {
out.setEntry(cc++, 0, aGrad);
}
}
throw new UnsupportedOperationException("men at work");
}
}

View file

@ -1,7 +1,9 @@
package cad.gcs;
public interface System {
Param[] getParams();
double[] params();
void gradient(double[] out);

View file

@ -0,0 +1,156 @@
package cad.gcs.constr;
import cad.gcs.Constraint;
import cad.gcs.Param;
import cad.math.Vector;
public class Parallel implements Constraint {
public static final int l1p1x = 0;
public static final int l1p1y = 1;
public static final int l1p2x = 2;
public static final int l1p2y = 3;
public static final int l2p1x = 4;
public static final int l2p1y = 5;
public static final int l2p2x = 6;
public static final int l2p2y = 7;
private final Param[] params = new Param[8];
public Parallel(
Param _l1p1x,
Param _l1p1y,
Param _l1p2x,
Param _l1p2y,
Param _l2p1x,
Param _l2p1y,
Param _l2p2x,
Param _l2p2y
) {
params[l1p1x] = _l1p1x;
params[l1p1y] = _l1p1y;
params[l1p2x] = _l1p2x;
params[l1p2y] = _l1p2y;
params[l2p1x] = _l2p1x;
params[l2p1y] = _l2p1y;
params[l2p2x] = _l2p2x;
params[l2p2y] = _l2p2y;
}
public void out(Vector p1, Vector p2, Vector p3, Vector p4) {
p1.x = params[l1p1x].get();
p1.y = params[l1p1y].get();
p2.x = params[l1p2x].get();
p2.y = params[l1p2y].get();
p3.x = params[l2p1x].get();
p3.y = params[l2p1y].get();
p4.x = params[l2p2x].get();
p4.y = params[l2p2y].get();
}
@Override
public Param[] getParams() {
return params;
}
@Override
public double[] params() {
double[] _params = new double[8];
_params[l1p1x] = params[l1p1x].get();
_params[l1p1y] = params[l1p1y].get();
_params[l1p2x] = params[l1p2x].get();
_params[l1p2y] = params[l1p2y].get();
_params[l2p1x] = params[l2p1x].get();
_params[l2p1y] = params[l2p1y].get();
_params[l2p2x] = params[l2p2x].get();
_params[l2p2y] = params[l2p2y].get();
return _params;
}
@Override
public double error() {
double dx1 = (params[l1p2x].get() - params[l1p1x].get());
double dy1 = (params[l1p2y].get() - params[l1p1y].get());
double dx2 = -(params[l2p2y].get() - params[l2p1y].get());
double dy2 = (params[l2p2x].get() - params[l2p1x].get());
//dot product shows how the lines off to be perpendicular
double off = dx1 * dx2 + dy1 * dy2;
return off * off;
}
//derivative of ((x-a1)*a2 + a3)^2
public double partDerivative1(double a1, double a2, double a3, double x) {
return 2*a2*(-a1*a2 + a2*x+a3);
}
//derivative of ((a1-x)*a2 + a3)^2
public double partDerivative2(double a1, double a2, double a3, double x) {
return -2*a2*(a1*a2 - a2*x+a3);
}
@Override
public void gradient(double[] out) {
double x1 = params[l1p1x].get();
double x2 = params[l1p1y].get();
double x3 = params[l1p2x].get();
double x4 = params[l1p2y].get();
double x6 = params[l2p1x].get();
double x5 = - params[l2p1y].get();
double x8 = params[l2p2x].get();
double x7 = - params[l2p2y].get();
double c1 = x3 - x1;
double c2 = x7 - x5;
double c3 = x4 - x2;
double c4 = x8 - x6;
//
//f(x) = ( (x3 - x1) * ( x7 - x5) + (x4 - x2) * (x8 - x6) ) ^ 2 =>
//f(x) = ( (x3 - x1) * (-x8 + x6) + (x4 - x2) * (x7 - x5) ) ^ 2
out[l1p1x] = partDerivative2(x3, c2, c3 * c4, x1);
out[l1p1y] = partDerivative2(x4, c4, c1 * c2, x2);
out[l1p2x] = partDerivative1(x1, c2, c3 * c4, x3);
out[l1p2y] = partDerivative1(x2, c4, c1 * c2, x4);
out[l2p1x] = partDerivative2(x7, c1, c3 * c4, x5);
out[l2p1y] = partDerivative2(x8, c3, c1 * c2, x6);
out[l2p2x] = partDerivative1(x5, c1, c3 * c4, x7);
out[l2p2y] = partDerivative1(x6, c3, c1 * c2, x8);
}
public double angle() {
double dx1 = (params[l1p2x].get() - params[l1p1x].get());
double dy1 = (params[l1p2y].get() - params[l1p1y].get());
double dx2 = (params[l2p2x].get() - params[l2p1x].get());
double dy2 = (params[l2p2y].get() - params[l2p1y].get());
Vector d1 = new Vector(dx1, dy1);
Vector d2 = new Vector(dx2, dy2);
return Math.acos(d1.normalize().dot(d2.normalize())) / Math.PI * 180;
}
@Override
public int pSize() {
return 8;
}
@Override
public void set(double[] input) {
params[l1p1x].set(input[l1p1x]);
params[l1p1y].set(input[l1p1y]);
params[l1p2x].set(input[l1p2x]);
params[l1p2y].set(input[l1p2y]);
params[l2p1x].set(input[l2p1x]);
params[l2p1y].set(input[l2p1y]);
params[l2p2x].set(input[l2p2x]);
params[l2p2y].set(input[l2p2y]);
}
}

View file

@ -48,6 +48,11 @@ public class Perpendicular implements Constraint {
p4.y = params[l2p2y].get();
}
@Override
public Param[] getParams() {
return params;
}
@Override
public double[] params() {
double[] _params = new double[8];
@ -64,10 +69,10 @@ public class Perpendicular implements Constraint {
@Override
public double error() {
double dx1 = (params[l1p1x].get() - params[l1p2x].get());
double dy1 = (params[l1p1y].get() - params[l1p2y].get());
double dx2 = (params[l2p1x].get() - params[l2p2x].get());
double dy2 = (params[l2p1y].get() - params[l2p2y].get());
double dx1 = (params[l1p2x].get() - params[l1p1x].get());
double dy1 = (params[l1p2y].get() - params[l1p1y].get());
double dx2 = (params[l2p2x].get() - params[l2p1x].get());
double dy2 = (params[l2p2y].get() - params[l2p1y].get());
//dot product shows how the lines off to be perpendicular
double off = dx1 * dx2 + dy1 * dy2;
return off * off;
@ -148,18 +153,6 @@ public class Perpendicular implements Constraint {
}
@Override
public void step(double alpha) {
System.out.println(angle());
step(l1p1x, l1p1y, params[l2p1x].get() - params[l2p2x].get(), params[l2p1y].get() - params[l2p2y].get(), alpha);
step(l1p2x, l1p2y, -(params[l2p1x].get() - params[l2p2x].get()), -(params[l2p1y].get() - params[l2p2y].get()), alpha);
step(l2p1x, l2p1y, (params[l1p1x].get() - params[l1p2x].get()), (params[l1p1y].get() - params[l1p2y].get()), alpha);
step(l2p2x, l2p2y, -(params[l1p1x].get() - params[l1p2x].get()), -(params[l1p1y].get() - params[l1p2y].get()), alpha);
}
public double angle() {
double dx1 = (params[l1p2x].get() - params[l1p1x].get());
double dy1 = (params[l1p2y].get() - params[l1p1y].get());

View file

@ -55,7 +55,12 @@ public class X implements Constraint {
public double valueY() {
return (params[l2p2y].get() - params[l2p1y].get()) * .5 - (params[l1p2y].get() - params[l1p1y].get()) * .5;
}
@Override
public Param[] getParams() {
return params;
}
@Override
public double[] params() {
double[] _params = new double[8];
@ -111,18 +116,6 @@ public class X implements Constraint {
}
@Override
public void step(double alpha) {
System.out.println(angle());
step(l1p1x, l1p1y, params[l2p1x].get() - params[l2p2x].get(), params[l2p1y].get() - params[l2p2y].get(), alpha);
step(l1p2x, l1p2y, -(params[l2p1x].get() - params[l2p2x].get()), -(params[l2p1y].get() - params[l2p2y].get()), alpha);
step(l2p1x, l2p1y, (params[l1p1x].get() - params[l1p2x].get()), (params[l1p1y].get() - params[l1p2y].get()), alpha);
step(l2p2x, l2p2y, -(params[l1p1x].get() - params[l1p2x].get()), -(params[l1p1y].get() - params[l1p2y].get()), alpha);
}
public double angle() {
double dx1 = (params[l1p1x].get() - params[l1p2x].get());
double dy1 = (params[l1p1y].get() - params[l1p2y].get());