Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
        }
Пример #5
0
        // 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);
        }
Пример #6
0
        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);
        }
Пример #7
0
        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");
        }
Пример #8
0
        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");
        }
Пример #9
0
        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");
        }
Пример #10
0
        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);
        }
Пример #11
0
        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");
        }
Пример #12
0
        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);
        }
Пример #13
0
        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!");
        }
Пример #14
0
        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);
 }