public void FindMinimum_BettsTestFunction_AnalyticResult()
        {
            /* f(x) = 0.01 * x_0^2 + x_1^2 w.r.t 10*x_0 - x_1 >= 10, 2 <= x_0 <= 50, -50 <= x_1 <= 50 */
            var optimizer = new LevenbergMarquardtOptimizer();

            var box           = MultiDimRegion.Interval.Create(2, new[] { 2.0, -50.0 }, new[] { 50.0, 50.0 });
            var linConstraint = new MultiDimRegion.LinearInequality(new DenseMatrix(2, 1, new[] { 10.0, -1.0 }), new[] { 10.0 });

            var algorithm = optimizer.Create(optimizer.Constraint.Create(box), optimizer.Constraint.Create(linConstraint));

            algorithm.Function = optimizer.Function.Create(2, 2,
                                                           (x, J, y) =>
            {
                if (J != null)
                {
                    J[0] = 0.01;
                    J[1] = 0.0;
                    J[2] = 0.0;
                    J[3] = 1.0;
                }
                y[0] = 0.1 * x[0];
                y[1] = x[1];
            });

            var actualArgMin = new[] { 4.0, 5.0 }; // use feasible initial points
            var state        = algorithm.FindMinimum(actualArgMin, out double actualMinimum);

            var expectedArgMin  = new[] { 2.0, 0.0 };
            var expectedMinimum = 0.04;

            Assert.That(actualMinimum, Is.EqualTo(expectedMinimum).Within(1E-5), String.Format("State: {0}; actual Minimum: {1}; expected Minimum: {2}; actual argMin: [{3}; {4}]; expected argMin: [{5}; {6}].", state, actualMinimum, expectedMinimum, actualArgMin[0], actualArgMin[1], expectedArgMin[0], expectedArgMin[1]));
            Assert.That(actualArgMin, Is.EqualTo(expectedArgMin).AsCollection.Within(1E-5), String.Format("State: {0}; actual Minimum: {1}; expected Minimum: {2}; actual argMin: [{3}; {4}]; expected argMin: [{5}; {6}].", state, actualMinimum, expectedMinimum, actualArgMin[0], actualArgMin[1], expectedArgMin[0], expectedArgMin[1]));
        }
Beispiel #2
0
 /// <summary>Creates a new <see cref="MultiDimOptimizer.IConstraint"/> object.
 /// </summary>
 /// <param name="linearInequalityConstraint">The specific constraints in its <see cref="MultiDimRegion.LinearInequality"/> representation.</param>
 /// <returns>A specific <see cref="MultiDimOptimizer.IConstraint"/> object with respect to the specified optimization algorithm.</returns>
 /// <exception cref="InvalidOperationException">Thrown, if the optimization algorithm does not support this kind of constraints.</exception>
 public MultiDimOptimizer.IConstraint Create(MultiDimRegion.LinearInequality linearInequalityConstraint)
 {
     if (SupportedConstraints.HasFlag(ConstraintType.LinearInEquation) == true)
     {
         return(new MultiDimOptimizerConstraint(this, linearInequalityConstraint));
     }
     throw new InvalidOperationException();
 }
        /// <summary>Creates a new <see cref="NLoptConstraint"/> object.
        /// </summary>
        /// <param name="linearInequalityConstraint">The specific constraints in its <see cref="MultiDimRegion.LinearInequality"/> representation.</param>
        /// <returns>A specific <see cref="NLoptConstraint"/> object with respect to the specified optimization algorithm.</returns>
        /// <exception cref="InvalidOperationException">Thrown, if the optimization algorithm does not support this kind of constraints.</exception>
        public NLoptConstraint Create(MultiDimRegion.LinearInequality linearInequalityConstraint)
        {
            if (linearInequalityConstraint == null)
            {
                throw new ArgumentNullException(nameof(linearInequalityConstraint));
            }
            if (nloptMultiDimOptimizer.Configuration.NonlinearConstraintRequirement.HasFlag(NLoptNonlinearConstraintRequirement.SupportsInequalityConstraints) == false)
            {
                throw new InvalidOperationException("The NLopt algorithm does not support linear inequality constraints");
            }

            var entriesOfA = new List <double>();
            var entriesOfb = new List <double>();
            int r          = linearInequalityConstraint.GetRegionConstraints(entriesOfA, entriesOfb); // condition A^t * x >= b should be written as c(x) = b - A^t * x

            var A = entriesOfA.ToArray();                                                             // matrix A is of type d[dimension] x r, provided column-by-column
            var b = entriesOfb.ToArray();

            NLoptVectorInequalityConstraintFunction c = (m, result, n, x, grad, data) =>  // todo: bug in nlopt(?) - argument x has wrong dimension
            {
                BLAS.Level2.dgemv(n, m, -1.0, A, x, 0.0, result, BLAS.MatrixTransposeState.Transpose);
                VectorUnit.Basics.Add(r, result, b);

                if (grad != null)
                {
                    /* it holds \partial c_i / \partial x_j = A[j,i] which should be stored in grad[i * n + j], i = 0,...,m-1, j = 0,...,n-1 */
                    for (int i = 0; i < m; i++)
                    {
                        for (int j = 0; j < n; j++)
                        {
                            grad[i * n + j] = A[j + i * n]; // can be improved
                        }
                    }
                }
            };

            var tolerance = Enumerable.Repeat(MachineConsts.Epsilon, r).ToArray();

            return(new NLoptConstraint(this,
                                       linearInequalityConstraint.Dimension,
                                       "Linear Inequality constraint",
                                       nloptPtr =>
            {
                var code = nloptPtr.AddInequalityConstraint(c, r, tolerance);
                if (code != NLoptResultCode.Success)
                {
                    throw new InvalidOperationException(String.Format("Constraint can not be set to NLopt algorithm {0}; error code: {1}.", nloptPtr.ToString(), code));
                }
            },
                                       infoOutputPackage => { }
                                       ));
        }
 /// <summary>Creates a new <see cref="MultiDimOptimizer.IConstraint"/> object.
 /// </summary>
 /// <param name="linearInequalityConstraint">The specific constraints in its <see cref="MultiDimRegion.LinearInequality"/> representation.</param>
 /// <returns>A specific <see cref="MultiDimOptimizer.IConstraint"/> object with respect to the specified optimization algorithm.</returns>
 /// <exception cref="InvalidOperationException">Thrown, if the optimization algorithm does not support this kind of constraints.</exception>
 MultiDimOptimizer.IConstraint MultiDimOptimizer.IConstraintFactory.Create(MultiDimRegion.LinearInequality linearInequalityConstraint)
 {
     return(this.Create(linearInequalityConstraint));
 }