예제 #1
0
        public static int Solve(List <DoubleRefObject> originalData, ConstraintContainer cons, double isFine)
        {
            var xLength = originalData.Count;

            //Save the original parameters for later.
            var origSolution1 = new List <DoubleRefObject>();

            foreach (var element in originalData)
            {
                var auxVal = new DoubleRefObject(element.Value);
                origSolution1.Add(auxVal);
            }

            var convergence = isFine > 0 ? XconvergenceFine : XconvergenceRough;
            //integer to keep track of how many times calc is called
            var ftimes = 0;
            //Calculate Function at the starting point:
            var f0 = cons.Calc();

            if (f0 < SmallF)
            {
                return(0);
            }

            ftimes++;
            //Calculate the gradient at the starting point:

            //Calculate the gradient
            //gradF=x;
            var    grad = BuildSizedList <double>(xLength); //The gradient vector (1xn)
            double first, second, temper;                   //The norm of the gradient vector
            double f1;
            double norm = 0;
            var    pert = f0 * PertMag;

            for (var j = 0; j < xLength; j++)
            {
                temper = originalData[j].Value;
                originalData[j].Value = temper - pert;
                first = cons.Calc();
                originalData[j].Value = temper + pert;
                second  = cons.Calc();
                grad[j] = .5 * (second - first) / pert;
                ftimes++;

                originalData[j].Value = temper;
                norm = norm + (grad[j] * grad[j]);
            }
            norm = Math.Sqrt(norm);
            //Estimate the norm of N

            //Initialize N and calculate s
            var s = BuildSizedList <double>(xLength); //The current search direction
            var n = BuildSizedList <List <double> >(xLength);

            for (var i = 0; i < xLength; i++)
            {
                n[i] = BuildSizedList <double>(xLength);
            }
            for (var i = 0; i < xLength; i++)
            {
                for (var j = 0; j < xLength; j++)
                {
                    if (i == j)
                    {
                        //N[i][j]=norm; //Calculate a scaled identity matrix as a Hessian inverse estimate
                        //N[i][j]=grad[i]/(norm+.001);
                        n[i][j] = 1;
                        s[i]    = -grad[i]; //Calculate the initial search vector
                    }
                    else
                    {
                        n[i][j] = 0;
                    }
                }
            }
            var    fnew  = f0 + 1;
            double alpha = 1;                        //Initial search vector multiplier

            var xold = new List <DoubleRefObject>(); //Storage for the previous design variables

            foreach (var element in originalData)
            {
                var auxValue = new DoubleRefObject(element.Value);
                xold.Add(auxValue);
            }

            ///////////////////////////////////////////////////////
            //  Start of line search
            ///////////////////////////////////////////////////////

            //Make the initial position alpha1
            double alpha1 = 0;

            f1 = f0;

            //Take a step of alpha=1 as alpha2
            double alpha2 = 1;

            for (int i = 0; i < xLength; i++)
            {
                originalData[i].Value = xold[i].Value + alpha2 * s[i];//calculate the new x
            }
            var f2 = cons.Calc();

            ftimes++;

            //Take a step of alpha 3 that is 2*alpha2
            var alpha3 = alpha * 2;

            for (var i = 0; i < xLength; i++)
            {
                originalData[i].Value = xold[i].Value + alpha3 * s[i];//calculate the new x
            }
            var f3 = cons.Calc();

            ftimes++;

            //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;
                    for (var i = 0; i < xLength; i++)
                    {
                        originalData[i].Value = xold[i].Value + alpha2 * s[i];//calculate the new x
                    }
                    f2 = cons.Calc();
                    ftimes++;
                }

                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;
                    for (var i = 0; i < xLength; i++)
                    {
                        originalData[i].Value = xold[i].Value + alpha3 * s[i];//calculate the new x
                    }
                    f3 = cons.Calc();
                    ftimes++;
                }
            }
            // get the alpha for the minimum f of the quadratic approximation
            var alphaStar = alpha2 + ((alpha2 - alpha1) * (f1 - f3)) / (3 * (f1 - 2 * f2 + f3));

            //Guarantee that the new alphaStar is within the bracket
            if (alphaStar > alpha3 || alphaStar < alpha1)
            {
                alphaStar = alpha2;
            }

            // Set the values to alphaStar
            for (var i = 0; i < xLength; i++)
            {
                originalData[i].Value = xold[i].Value + alphaStar * s[i];//calculate the new x
            }
            fnew = cons.Calc();
            ftimes++;
            var fold = fnew;

            /////////////////////////////////////
            // end of line search
            /////////////////////////////////////



            var deltaX              = BuildSizedList <double>(xLength);
            var gradnew             = BuildSizedList <double>(xLength);
            var gamma               = BuildSizedList <double>(xLength);
            var gammatDotN          = BuildSizedList <double>(xLength);
            var firstSecond         = BuildSizedList <List <double> >(xLength);
            var deltaXDotGammatDotN = BuildSizedList <List <double> >(xLength);;
            var gammatDotDeltaXt    = BuildSizedList <List <double> >(xLength);
            var nDotGammaDotDeltaXt = BuildSizedList <List <double> >(xLength);

            for (var i = 0; i < xLength; i++)
            {
                firstSecond[i]         = BuildSizedList <double>(xLength);
                deltaXDotGammatDotN[i] = BuildSizedList <double>(xLength);
                gammatDotDeltaXt[i]    = BuildSizedList <double>(xLength);
                nDotGammaDotDeltaXt[i] = BuildSizedList <double>(xLength);
            }
            double deltaXnorm = 1;

            var iterations = 1;

            //Calculate deltaX
            for (var i = 0; i < xLength; i++)
            {
                deltaX[i] = originalData[i].Value - xold[i].Value;//Calculate the difference in x for the Hessian update
            }
            double maxIterNumber = MaxIterations * xLength;

            while (deltaXnorm > convergence && fnew > SmallF && iterations < maxIterNumber)
            {
                /////////////////////////////////////////////////////////////////////
                //Start of main loop!!!!
                /////////////////////////////////////////////////////////////////////
                double bottom          = 0;
                double deltaXtDotGamma = 0;
                pert = fnew * PertMag;
                if (pert < PertMin)
                {
                    pert = PertMin;
                }
                for (var i = 0; i < xLength; i++)
                {
                    //Calculate the new gradient vector
                    temper = originalData[i].Value;
                    originalData[i].Value = temper - pert;
                    first = cons.Calc();
                    originalData[i].Value = temper + pert;
                    second     = cons.Calc();
                    gradnew[i] = .5 * (second - first) / pert;
                    ftimes++;
                    originalData[i].Value = temper;
                    //Calculate the change in the gradient
                    gamma[i] = gradnew[i] - grad[i];
                    bottom  += deltaX[i] * gamma[i];

                    deltaXtDotGamma += deltaX[i] * gamma[i];
                }

                //make sure that bottom is never 0
                if (bottom == 0)
                {
                    bottom = 1e-9;
                }

                //calculate all (1xn).(nxn)

                for (var i = 0; i < xLength; i++)
                {
                    gammatDotN[i] = 0;
                    for (var j = 0; j < xLength; j++)
                    {
                        gammatDotN[i] += gamma[j] * n[i][j]; //This is gammatDotN transpose
                    }
                }
                //calculate all (1xn).(nx1)

                double gammatDotNDotGamma = 0;
                for (var i = 0; i < xLength; i++)
                {
                    gammatDotNDotGamma += gammatDotN[i] * gamma[i];
                }

                //Calculate the first term

                var firstTerm = 1 + gammatDotNDotGamma / bottom;

                //Calculate all (nx1).(1xn) matrices
                for (var i = 0; i < xLength; i++)
                {
                    for (var j = 0; j < xLength; j++)
                    {
                        firstSecond[i][j]         = ((deltaX[j] * deltaX[i]) / bottom) * firstTerm;
                        deltaXDotGammatDotN[i][j] = deltaX[i] * gammatDotN[j];
                        gammatDotDeltaXt[i][j]    = gamma[i] * deltaX[j];
                    }
                }

                //Calculate all (nxn).(nxn) matrices

                for (var i = 0; i < xLength; i++)
                {
                    for (var j = 0; j < xLength; j++)
                    {
                        nDotGammaDotDeltaXt[i][j] = 0;
                        for (var k = 0; k < xLength; k++)
                        {
                            nDotGammaDotDeltaXt[i][j] += n[i][k] * gammatDotDeltaXt[k][j];
                        }
                    }
                }
                //Now calculate the BFGS update on N
                //cout<<"N:"<<endl;
                for (var i = 0; i < xLength; i++)
                {
                    for (var j = 0; j < xLength; j++)
                    {
                        n[i][j] = n[i][j] + firstSecond[i][j] -
                                  (deltaXDotGammatDotN[i][j] + nDotGammaDotDeltaXt[i][j]) / bottom;
                    }
                }

                //Calculate s
                for (var i = 0; i < xLength; i++)
                {
                    s[i] = 0;
                    for (var j = 0; j < xLength; j++)
                    {
                        s[i] += -n[i][j] * gradnew[j];
                    }
                }

                alpha = 1; //Initial search vector multiplier


                //copy newest values to the xold
                xold.Clear();
                foreach (var element in originalData)
                {
                    var auxValue = new DoubleRefObject(element.Value);
                    xold.Add(auxValue);//Copy last values to xold
                }

                ///////////////////////////////////////////////////////
                //  Start of line search
                ///////////////////////////////////////////////////////

                //Make the initial position alpha1
                alpha1 = 0;
                f1     = fnew;

                //Take a step of alpha=1 as alpha2
                alpha2 = 1;
                for (var i = 0; i < xLength; i++)
                {
                    originalData[i].Value = xold[i].Value + alpha2 * s[i];//calculate the new x
                }
                f2 = cons.Calc();
                ftimes++;

                //Take a step of alpha 3 that is 2*alpha2
                alpha3 = alpha2 * 2;
                for (int i = 0; i < xLength; i++)
                {
                    originalData[i].Value = xold[i].Value + alpha3 * s[i];//calculate the new x
                }
                f3 = cons.Calc();
                ftimes++;

                //Now reduce or lengthen alpha2 and alpha3 until the minimum is
                //Bracketed by the triplet f1>f2<f3
                var steps = 0;
                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;
                        for (int i = 0; i < xLength; i++)
                        {
                            originalData[i].Value = xold[i].Value + alpha2 * s[i];//calculate the new x
                        }
                        f2 = cons.Calc();
                        ftimes++;
                    }

                    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;
                        for (int i = 0; i < xLength; i++)
                        {
                            originalData[i].Value = xold[i].Value + alpha3 * s[i];//calculate the new x
                        }
                        f3 = cons.Calc();
                        ftimes++;
                    }
                    steps = steps + 1;
                }

                // get the alpha for the minimum f of the quadratic approximation
                alphaStar = alpha2 + ((alpha2 - alpha1) * (f1 - f3)) / (3 * (f1 - 2 * f2 + f3));


                //Guarantee that the new alphaStar is within the bracket
                if (alphaStar >= alpha3 || alphaStar <= alpha1)
                {
                    alphaStar = alpha2;
                }

                // Set the values to alphaStar
                for (var i = 0; i < xLength; i++)
                {
                    originalData[i].Value = xold[i].Value + alphaStar * s[i];//calculate the new x
                }
                fnew = cons.Calc();
                ftimes++;


                /////////////////////////////////////
                // end of line search
                ////////////////////////////////////

                deltaXnorm = 0;
                for (int i = 0; i < xLength; i++)
                {
                    deltaX[i]   = originalData[i].Value - xold[i].Value;//Calculate the difference in x for the hessian update
                    deltaXnorm += deltaX[i] * deltaX[i];
                    grad[i]     = gradnew[i];
                }
                deltaXnorm = Math.Sqrt(deltaXnorm);
                iterations++;
                /////////////////////////////////////////////////////////////
                // End of Main loop
                /////////////////////////////////////////////////////////////
            }

            // End of function
            double validSolution;

            if (isFine == 1)
            {
                validSolution = ValidSolutionFine;
            }
            else
            {
                validSolution = ValidSoltuionRough;
            }
            if (fnew < validSolution)
            {
                return(0);
            }
            //Replace the bad numbers with the last result
            for (var i = 0; i < xLength; i++)
            {
                originalData[i] = origSolution1[i];
            }
            return(1);
        }
        public static void derivatives(List <DoubleRefObject> original, List <int> x, List <double> gradF, int xLength, ConstraintContainer cons, int consLength)
        {
            int position;

            for (int i = 0; i < consLength; i++)
            {
                var constraint = cons[i];
                //////////////////////////////////////
                //Point on Point Constraint derivative
                //////////////////////////////////////
                if (constraint is PointOnPoint)
                {
                    // Derivative with respect to p1x
                    position = (int)(constraint.P1.X.Value - x[0]);
                    if (position >= 0 & position < xLength)
                    {
                        gradF[position] += 2 * (constraint.P1.X.Value - constraint.P2.X.Value);
                    }

                    // Derivative with respect to p1y
                    position = (int)(constraint.P1.Y.Value - x[0]);
                    if (position >= 0 & position < xLength)
                    {
                        gradF[position] += 2 * (constraint.P1.Y.Value - constraint.P2.Y.Value);
                    }

                    // Derivative with respect to p2x
                    position = (int)(constraint.P2.X.Value - x[0]);
                    if (position >= 0 & position < xLength)
                    {
                        gradF[position] += -2 * (constraint.P1.X.Value - constraint.P2.X.Value);
                    }

                    // Derivative with respect to p2y
                    position = (int)(constraint.P2.Y.Value - x[0]);
                    if (position >= 0 & position < xLength)
                    {
                        gradF[position] += -2 * (constraint.P1.Y.Value - constraint.P2.Y.Value);
                    }
                }
                //.........................................
                // End Point On Point Constraint derivative
                //.........................................

                //////////////////////////////////////
                //Point to Point Distance Constraint derivative
                //////////////////////////////////////
                if (constraint is P2PDistance)
                {
                    // Derivative with respect to p1x
                    position = (int)(constraint.P1.X.Value - x[0]);
                    if (position >= 0 & position < xLength)
                    {
                        gradF[position] += 2 * (constraint.P1.X.Value - constraint.P2.X.Value);
                    }

                    // Derivative with respect to p1y
                    position = (int)(constraint.P1.Y.Value - x[0]);
                    if (position >= 0 & position < xLength)
                    {
                        gradF[position] += 2 * (constraint.P1.Y.Value - constraint.P2.Y.Value);
                    }

                    // Derivative with respect to p2x
                    position = (int)(constraint.P2.X.Value - x[0]);
                    if (position >= 0 & position < xLength)
                    {
                        gradF[position] += -2 * (constraint.P1.X.Value - constraint.P2.X.Value);
                    }

                    // Derivative with respect to p2y
                    position = (int)(constraint.P2.Y.Value - x[0]);
                    if (position >= 0 & position < xLength)
                    {
                        gradF[position] += -2 * (constraint.P1.Y.Value - constraint.P2.Y.Value);
                    }

                    // Derivative with respect to distance
                    position = (int)(constraint.Distance - x[0]);
                    if (position >= 0 & position < xLength)
                    {
                        gradF[position] += -2 * constraint.Distance;
                    }
                }
                //..................................................
                // End Point to Point distance Constraint derivative
                //..................................................

                //////////////////////////////////////
                //Point to Point Distance Vert Constraint derivative
                //////////////////////////////////////
                if (constraint is P2PDistanceVert)
                {
                    // Derivative with respect to p1y
                    position = (int)(constraint.P1.Y.Value - x[0]);
                    if (position >= 0 & position < xLength)
                    {
                        gradF[position] += 2 * (constraint.P1.Y.Value - constraint.P2.Y.Value);
                    }

                    // Derivative with respect to p2y
                    position = (int)(constraint.P2.Y.Value - x[0]);
                    if (position >= 0 & position < xLength)
                    {
                        gradF[position] += -2 * (constraint.P1.Y.Value - constraint.P2.Y.Value);
                    }

                    // Derivative with respect to distance
                    position = (int)(constraint.Distance - x[0]);
                    if (position >= 0 & position < xLength)
                    {
                        gradF[position] += -2 * constraint.Distance;
                    }
                }
                //........................................................
                // End Point to Point Vert distance Constraint derivative
                //........................................................

                //////////////////////////////////////
                //Point to Point Horz Distance Constraint derivative
                //////////////////////////////////////
                if (constraint is P2PDistanceHorz)
                {
                    // Derivative with respect to p1x
                    position = (int)(constraint.P1.X.Value - x[0]);
                    if (position >= 0 & position < xLength)
                    {
                        gradF[position] += 2 * (constraint.P1.X.Value - constraint.P2.X.Value);
                    }

                    // Derivative with respect to p2x
                    position = (int)(constraint.P2.X.Value - x[0]);
                    if (position >= 0 & position < xLength)
                    {
                        gradF[position] += -2 * (constraint.P1.X.Value - constraint.P2.X.Value);
                    }

                    // Derivative with respect to distance
                    position = (int)(constraint.Distance - x[0]);
                    if (position >= 0 & position < xLength)
                    {
                        gradF[position] += -2 * constraint.Distance;
                    }
                }
                //.......................................................
                // End Point to Point Horz distance Constraint derivative
                //.......................................................

                //////////////////////////////////////
                //Point on line Constraint derivatives
                //////////////////////////////////////
                if (constraint is PointOnLine)
                {
                    // Derivative with respect to p1x
                    position = (int)(constraint.P1.X.Value - x[0]);
                    if (position >= 0 & position < xLength)
                    {
                        gradF[position] += 2 * (constraint.P1.X.Value - constraint.P2.X.Value);
                    }

                    // Derivative with respect to p2x
                    position = (int)(constraint.P2.X.Value - x[0]);
                    if (position >= 0 & position < xLength)
                    {
                        gradF[position] += -2 * (constraint.P1.X.Value - constraint.P2.X.Value);
                    }

                    // Derivative with respect to distance
                    position = (int)(constraint.Distance - x[0]);
                    if (position >= 0 & position < xLength)
                    {
                        gradF[position] += -2 * constraint.Distance;
                    }
                }
                //.......................................................
                // End Point to Point Horz distance Constraint derivative
                //.......................................................
            }
        }
예제 #3
0
        public void Run()
        {
            P = parameters;

            Point origin;


            constants[0] = 6;
            constants[1] = 6;
            constants[2] = 2;
            constants[3] = Math.PI / 3;
            constants[4] = 3;

            points.Add(new Point(parameters[0], parameters[1]));
            points.Add(new Point(parameters[2], parameters[3]));
            points.Add(new Point(parameters[4], parameters[5]));
            points.Add(new Point(parameters[6], parameters[7]));
            points.Add(new Point(new DoubleRefObject(constants[0]), new DoubleRefObject(constants[1])));

            lines[0].P1 = points[0];
            lines[0].P2 = points[1];
            lines[1].P1 = points[1];
            lines[1].P2 = points[2];

            var constraitns = new ConstraintContainer();

            constraitns.AddConstraint(new Horizontal()
            {
                L1 = lines[0]
            });
            constraitns.AddConstraint(new Vertical()
            {
                L1 = lines[1]
            });
            constraitns.AddConstraint(new PointOnPoint()
            {
                P1 = points[2],
                P2 = points[4]
            });

            constraitns.AddConstraint(new PointOnPoint()
            {
                P1 = points[3],
                P2 = points[4]
            });


            for (int i = 0; i < 1; i++)
            {
                parameters[0].Value = 0; //1x
                parameters[1].Value = 0; //y
                parameters[2].Value = 5; //x
                parameters[3].Value = 0; //y
                parameters[4].Value = 6; //xstart
                parameters[5].Value = 5; //y

                parameters[6].Value = 6; //xend
                parameters[7].Value = 5; //y


                var pparameters = new List <int>();

                for (var index = 0; index < 100; index++)
                {
                    pparameters.Add(index);
                }

                var sol = SketchSolve.Solve(parameters, constraitns, Rough);
                switch (sol)
                {
                case 0:
                    Console.WriteLine("A good Solution was found");
                    break;

                case 1:
                    Console.WriteLine("No valid Solutions were found from this start point");
                    break;
                }
                DisplayPoints();
                var hey = parameters[0].Value * parameters[2].Value + parameters[1].Value * parameters[3].Value;
                Console.WriteLine("dot product: " + hey);

                var        gradF  = new List <double>();
                List <int> ggradF = new List <int>();

                for (int index = 0; index < 20; index++)
                {
                    gradF.Add(0);
                    ggradF.Add(index);
                }

                SketchDerivative.derivatives(parameters, pparameters, gradF, 4, constraitns, 3);

                for (var index = 0; index < 4; index++)
                {
                    Console.WriteLine("GradF[" + index + "]: " + gradF[ggradF[index]]);
                }
            }
        }