public void ParallelToYAxisTest() { var parametersList = new List <double> { 1, 0, 1, 4, 5, 0, 5, 13 }; var parameters = new Vector(parametersList); var constraints = new ConstraintRefContainer(); var line1 = new RefLine(0, 1, 2, 3); var line2 = new RefLine(4, 5, 6, 7); constraints.Add(new ParallelRef { L1 = line1, L2 = line2 }); var solver = new BFGSSolver(); var error = solver.SolveRef(ref parameters, 0, constraints, 0); Assert.IsTrue(error == 0, "Invalid parallel solution"); var m1 = LineSlope(line1, parameters); var m2 = LineSlope(line2, parameters); Assert.IsTrue(double.IsPositiveInfinity(m1)); Assert.AreEqual(m1, m2); }
public void ParallelTest() { var parametersList = new List <double> { 0, 0, 3, 0, 0, 10, -5, 5 }; var parameters = new Vector(parametersList); var constraints = new ConstraintRefContainer(); constraints.Add(new ParallelRef { L1 = new RefLine(6, 7, 0, 1), L2 = new RefLine(2, 3, 4, 5) }); var solver = new BFGSSolver(); var error = solver.SolveRef(ref parameters, 0, constraints, 0); Assert.IsTrue(error == 1, "Invalid solution"); solver = new BFGSSolver(); error = solver.SolveRef(ref parameters, 1, constraints, 0); Assert.IsTrue(error == 0, "Invalid solution"); //parameters[0] = -3.49999 Assert.IsTrue(Math.Abs(parameters[0] + 3.4999) < 0.001); }
public void RectangleTest() { var parametersList = new List <double> { 1, 4, 6, 1, 6, 5, 1, 1 }; var parameters = new Vector(parametersList); var constraints = new ConstraintRefContainer(); constraints.Add(new ParallelRef { L1 = new RefLine(4, 5, 0, 1), L2 = new RefLine(6, 7, 2, 3) }); constraints.Add(new ParallelRef { L1 = new RefLine(2, 3, 4, 5), L2 = new RefLine(0, 1, 6, 7) }); constraints.Add(new PerpendicularRef { L1 = new RefLine(4, 5, 0, 1), L2 = new RefLine(0, 1, 6, 7) }); var solver = new BFGSSolver(); var error = solver.SolveRef(ref parameters, 0, constraints, 0); Assert.IsTrue(error == 1, "Invalid solution"); solver = new BFGSSolver(); error = solver.SolveRef(ref parameters, 2, constraints, 0); Assert.IsTrue(error == 0, "Invalid solution"); Assert.IsTrue(Math.Abs(parameters[0] - 1) < 0.001); Assert.IsTrue(Math.Abs(parameters[1] - 5) < 0.001); }
private static double LineSearch(ConstraintRefContainer cons, Vector xold, Vector s, double f1, double alpha2, double alpha1) { // //Take a step of alpha=1 as alpha2 var originalData = xold + alpha2 * s; var f2 = cons.Calc(originalData); // //Take a step of alpha 3 that is 2*alpha2 var alpha3 = alpha2 * 2; originalData = xold + alpha3 * s; var f3 = cons.Calc(originalData); //Now reduce or lengthen alpha2 and alpha3 until the minimum is //Bracketed by the triplet f1>f2<f3 while (f2 > f1 || f2 > f3) { if (f2 > f1) { //If f2 is greater than f1 then we shorten alpha2 and alpha3 closer to f1 //Effectively both are shortened by a factor of two. alpha3 = alpha2; f3 = f2; alpha2 = alpha2 / 2; originalData = xold + alpha2 * s; f2 = cons.Calc(originalData); } else if (f2 > f3) { //If f2 is greater than f3 then we length alpah2 and alpha3 closer to f1 //Effectively both are lengthened by a factor of two. alpha2 = alpha3; f2 = f3; alpha3 = alpha3 * 2; originalData = xold + alpha3 * s; f3 = cons.Calc(originalData); } } // get the alpha for the minimum f of the quadratic approximation var denominator = f1 - 2 * f2 + f3; denominator = denominator < 1e-13 ? 1e-13 : denominator; var alphaStar = alpha2 + ((alpha2 - alpha1) * (f1 - f3)) / (3 * denominator); //Guarantee that the new alphaStar is within the bracket if (alphaStar > alpha3 || alphaStar < alpha1) { alphaStar = alpha2; } return(alphaStar); }
// public List<int> softConstraints = new List<int>(); public NaroSketchSolveBuilder(Document document, Node sketchNode) { _document = document; ShapeSolverObjectMapping = new Dictionary <string, ISolverObjectMapping>(); ConstraintList = new ConstraintRefContainer(); MapShapes(); ConstraintMappingList = new ConstraintMappingList(); DefaultConstraintsMapping.SetupFunctions(ConstraintMappingList); }
private void LoadConstraints() { var constraintsList = new List <ConstraintRefBase>(); var allConstraints = new List <int>(); allConstraints.AddRange(_constraints); //ConstraintList = new ConstraintRefContainer(); foreach (var shape in allConstraints) { var builder = new NodeBuilder(_document.Root[shape]); ISolverConstraintMapping objectMapper; if (ConstraintMappingList.ShapeConstraintObjectMapping.TryGetValue(builder.FunctionName, out objectMapper)) { var constr = objectMapper.MapRef(_document, builder, ShapeToParamIndex); //only do this for the new constraints if (constr != null) { constraintsList.AddRange(constr); } } } SetConstraintsList = new ConstraintRefContainer(); SetConstraintsList.AddRange(constraintsList); ConstraintList.AddRange(constraintsList); // GetSoftConstraints(); allConstraints.Clear(); allConstraints.AddRange(softConstraints); constraintsList.Clear(); SoftConstraintsList = new ConstraintRefContainer(); foreach (var shape in allConstraints) { var builder = new NodeBuilder(_document.Root[shape]); ISolverConstraintMapping objectMapper; if (ConstraintMappingList.ShapeConstraintObjectMapping.TryGetValue(builder.FunctionName, out objectMapper)) { var constr = objectMapper.MapRef(_document, builder, ShapeToParamIndex); //only do this for the new constraints if (constr != null) { constraintsList.AddRange(constr); } } } SoftConstraintsList.AddRange(constraintsList); ConstraintList.AddRange(constraintsList); }
public void VerticalTest() { var parametersList = new List <double> { 3, 1, 4, 2 }; var parameters = new Vector(parametersList); var constraints = new ConstraintRefContainer(); constraints.Add(new VerticalRef { L1 = new RefLine(0, 1, 2, 3) }); var solver = new BFGSSolver(); var error = solver.SolveRef(ref parameters, 1, constraints, 0); Assert.IsTrue(error == 0, "Invalid horizontal solution"); Assert.IsTrue(Math.Abs(parameters[0] - 4) < 0.01, "invalid x axis values"); }
public void HorizontalDistanceToCenterTest() { var parametersList = new List <double> { 2, 2 }; var parameters = new Vector(parametersList); var constraints = new ConstraintRefContainer(); constraints.Add(new HorizontalDistanceToCenterRef { P1 = new RefPoint(0, 1), Distance = 10 }); var solver = new BFGSSolver(); var error = solver.SolveRef(ref parameters, 2, constraints, 0); Assert.IsTrue(error == 0, "Invalid horizontal solution"); Assert.IsTrue(Math.Abs(parameters[0] - 10) < 0.01, "invalid x axis values"); }
public void PointOnLineTest() { var parametersList = new List <double> { 3, 1, 4, 2, 5, 2 }; var parameters = new Vector(parametersList); var constraints = new ConstraintRefContainer(); constraints.Add(new PointOnLineRef { P1 = new RefPoint(0, 1), L1 = new RefLine(2, 3, 4, 5) }); var solver = new BFGSSolver(); var error = solver.SolveRef(ref parameters, 2, constraints, 0); Assert.IsTrue(error == 0, "Invalid point on point solution"); Assert.IsTrue(Math.Abs(parameters[0] - 3) < 0.01, "invalid x axis value"); Assert.IsTrue(Math.Abs(parameters[1] - 2) < 0.01, "invalid y axis value"); }
public void PerpendicularTest() { var parametersList = new List <double> { 5, 3, 1, 1, 4, 1 }; var parameters = new Vector(parametersList); var constraints = new ConstraintRefContainer(); constraints.Add(new PerpendicularRef { L1 = new RefLine(2, 3, 4, 5), L2 = new RefLine(0, 1, 4, 5) }); var solver = new BFGSSolver(); var error = solver.SolveRef(ref parameters, 1, constraints, 0); Assert.IsTrue(error == 0, "Invalid perpendicular solution"); Assert.IsTrue(Math.Abs(parameters[0] - 4) < 0.0001); Assert.IsTrue(Math.Abs(parameters[1] - 3) < 0.0001); }
public void PerpendicularWithFixedPointTest() { var parametersList = new List <double> { 6, 8, 6, 3, 2, 6 }; var parameters = new Vector(parametersList); var constraints = new ConstraintRefContainer(); constraints.Add(new PerpendicularRef { L1 = new RefLine(0, 1, 2, 3), L2 = new RefLine(0, 1, 4, 5) }); constraints.Add(new HorizontalDistanceToCenterRef { P1 = new RefPoint(0, 1), Distance = 2 }); constraints.Add(new VerticalDistanceToCenterRef { P1 = new RefPoint(0, 1), Distance = 2 }); var solver = new BFGSSolver(); var error = solver.SolveRef(ref parameters, 6, constraints, 0); Assert.IsTrue(error == 0, "Invalid perpendicular solution"); var m1 = LineSlope(new RefLine(0, 1, 2, 3), parameters); var m2 = LineSlope(new RefLine(0, 1, 4, 5), parameters); Assert.IsTrue((m1 * m2 + 1) < 0.01, "invalid perpendicular values"); Assert.IsTrue(Math.Abs(parameters[0] - 2) < 0.0001, "invalid point values for Horizontal distance constraint"); Assert.IsTrue(Math.Abs(parameters[1] - 2) < 0.0001, "invalid point values for Vertical distance constraint"); }
protected override Matrix CalculateUpdate(int freeValuesCount, int xLength, Vector originalData, ConstraintRefContainer cons, Matrix n, Vector grad, Vector deltaX) { var gammatDotN = new Vector(xLength); var firstSecond = new Matrix(xLength, xLength); var deltaXDotGammatDotN = new Matrix(xLength, xLength); var gammatDotDeltaXt = new Matrix(xLength, xLength); var gradnew = new Vector(xLength); for (var i = 0; i < freeValuesCount; i++) { gradnew[i] = cons.Grad(originalData, i); } Vector gamma = gradnew - grad; double bottom = deltaX * gamma; //make sure that bottom is never 0 if (bottom < 1e-9) { bottom = 1e-9; } for (var i = 0; i < xLength; i++) { gammatDotN[i] = 0; for (var j = 0; j < freeValuesCount; j++) { gammatDotN[i] += gamma[j] * n[i, j]; } } double gammatDotNDotGamma = gammatDotN * gamma; var firstTerm = 1 + gammatDotNDotGamma / bottom; for (var i = 0; i < freeValuesCount; i++) { for (var j = 0; j < freeValuesCount; j++) { firstSecond[i, j] = ((deltaX[j] * deltaX[i]) / bottom) * firstTerm; deltaXDotGammatDotN[i, j] = deltaX[i] * gammatDotN[j]; gammatDotDeltaXt[i, j] = gamma[i] * deltaX[j]; } } Matrix nDotGammaDotDeltaXt = n * gammatDotDeltaXt; //Now calculate the BFGS update on N n = n + firstSecond - (deltaXDotGammatDotN + nDotGammaDotDeltaXt) * (1 / bottom); return(n); }
public void ThreeRectanglesTest() { var parametersList = new List <double> { 2, 1, 5, 4, 8, 1, 11, 1, /*fixed points:*/ 7, -1, 2, 4, 8, 4, 11, 4 }; var parameters = new Vector(parametersList); var constraints = new ConstraintRefContainer(); /* first rectangle*/ constraints.Add(new ParallelRef { L1 = new RefLine(0, 1, 8, 9), L2 = new RefLine(10, 11, 2, 3) }); constraints.Add(new ParallelRef { L1 = new RefLine(10, 11, 0, 1), L2 = new RefLine(2, 3, 8, 9) }); constraints.Add(new PerpendicularRef { L1 = new RefLine(10, 11, 0, 1), L2 = new RefLine(0, 1, 8, 9) }); /*second rectangle*/ constraints.Add(new ParallelRef { L1 = new RefLine(2, 3, 12, 13), L2 = new RefLine(8, 9, 4, 5) }); constraints.Add(new ParallelRef { L1 = new RefLine(2, 3, 8, 9), L2 = new RefLine(12, 13, 4, 5) }); constraints.Add(new PerpendicularRef { L1 = new RefLine(2, 3, 8, 9), L2 = new RefLine(8, 9, 4, 5) }); /*third rectangle*/ constraints.Add(new ParallelRef { L1 = new RefLine(12, 13, 14, 15), L2 = new RefLine(4, 5, 6, 7) }); constraints.Add(new ParallelRef { L1 = new RefLine(12, 13, 4, 5), L2 = new RefLine(14, 15, 6, 7) }); constraints.Add(new PerpendicularRef { L1 = new RefLine(12, 13, 4, 5), L2 = new RefLine(4, 5, 6, 7) }); var solver = new BFGSSolver(); var error = solver.SolveRef(ref parameters, parameters.Count - 8, constraints, 0); Assert.IsTrue(error == 0, "Invalid parallel solution"); Assert.IsTrue(Math.Abs(parameters[1] + 1) < 0.001, "P0.y is not -1!"); Assert.IsTrue(Math.Abs(parameters[5] + 1) < 0.001, "P3.y is not -1!"); Assert.IsTrue(Math.Abs(parameters[7] + 1) < 0.001, "P4.y is not -1!"); Assert.IsTrue(Math.Abs(parameters[9] + 1) < 0.001, "P5.y is not -1!"); Assert.IsTrue(Math.Abs(parameters[0] - 2) < 0.001, "P0.x is not 7!"); Assert.IsTrue(Math.Abs(parameters[4] - 8) < 0.001, "P3.x is not 2!"); Assert.IsTrue(Math.Abs(parameters[6] - 11) < 0.001, "P4.x is not 8!"); Assert.IsTrue(Math.Abs(parameters[8] - 7) < 0.001, "P5.x is not 11!"); Assert.IsTrue(Math.Abs(parameters[2] - 7) < 0.001, "P2.x is not 7!"); Assert.IsTrue(Math.Abs(parameters[3] - 4) < 0.001, "P2.Y is not 4!"); }
protected override Matrix CalculateUpdate(int freeValuesCount, int xLength, Vector originalData, ConstraintRefContainer cons, Matrix n, Vector grad, Vector deltaX) { var firstTerm = new Matrix(xLength, xLength); var gradnew = new Vector(xLength); for (var i = 0; i < freeValuesCount; i++) { gradnew[i] = cons.Grad(originalData, i); } Vector gamma = gradnew - grad; double bottom = deltaX * gamma; //make sure that bottom is never 0 if (bottom < 1e-9) { bottom = 1e-9; } double gammatDotNDotGamma = 0.0; for (var i = 0; i < xLength; i++) { for (var j = 0; j < freeValuesCount; j++) { gammatDotNDotGamma += gamma[j] * n[i, j] * gamma[i]; } } if (gammatDotNDotGamma < 1e-9) { gammatDotNDotGamma = 1e-9; } var secondTerm = new Matrix(xLength, xLength); for (var i = 0; i < freeValuesCount; i++) { for (var j = 0; j < freeValuesCount; j++) { firstTerm[i, j] = (deltaX[i] * deltaX[j]) / bottom; secondTerm[i, j] = n[i, j] * gamma[i] * gamma[j] * n[i, j] * (1 / gammatDotNDotGamma); } } //Now calculate the DFP update on N n = n + firstTerm - secondTerm; return(n); }
public int SolveRef(ref Vector originalData, int freeValuesCount, ConstraintRefContainer cons, double isFine) { var xLength = originalData.Count; //Save the original parameters for later. var origSolution1 = new Vector(originalData); var convergence = isFine > 0.1 ? XconvergenceFine : XconvergenceRough; //Calculate Function at the starting point: var f0 = cons.Calc(originalData); if (f0 < SmallF) { return(0); } //Calculate the gradient at the starting point: var grad = new Vector(xLength); //The gradient vector (1xn) for (var j = 0; j < freeValuesCount; j++) { grad[j] = cons.Grad(originalData, j); } //Initialize N and calculate s var n = Matrix.Identity(xLength, xLength); var s = -grad; var fnew = f0 + 1; var xold = new Vector(originalData); //Storage for the previous design variables ///////////////////////////////////////////////////////// //// Calculate first step ///////////////////////////////////////////////////////// //Make the initial position alpha1 double alpha1 = 0; ////Take a step of alpha=1 as alpha2 double alpha2 = 1; double f1 = fnew; var alphaStar = LineSearch(cons, xold, s, f1, alpha2, alpha1); originalData = xold + alphaStar * s; fnew = cons.Calc(originalData); ///////////////////////////////////// // end of first step ///////////////////////////////////// var deltaX = new Vector(xLength); var gradnew = new Vector(xLength); double deltaXnorm = 1; var iterations = 1; deltaX = originalData - xold; while (deltaXnorm > convergence && fnew > SmallF && iterations < MaxIterations * xold.Count) { n = CalculateUpdate(freeValuesCount, xLength, originalData, cons, n, grad, deltaX); ////// line search + next steps ///// for (var i = 0; i < freeValuesCount; i++) { gradnew[i] = cons.Grad(originalData, i); } s = n * (-gradnew); //copy newest values to the xold xold = originalData; f1 = fnew; alphaStar = LineSearch(cons, xold, s, f1, alpha2, alpha1); originalData = xold + alphaStar * s; fnew = cons.Calc(originalData); deltaX = originalData - xold; grad = new Vector(gradnew); deltaXnorm = deltaX.Norm(); iterations++; } // End of function double validSolution = isFine < 0.1 ? ValidSolutionFine : ValidSoltuionRough; if (fnew < validSolution) { return(0); } originalData = origSolution1; return(1); }
protected virtual Matrix CalculateUpdate(int freeValuesCount, int xLength, Vector originalData, ConstraintRefContainer cons, Matrix n, Vector grad, Vector deltaX) { return(n); }