Exemplo n.º 1
0
 /// <summary>Adds a specific inequality constraint.
 /// </summary>
 /// <param name="inequalityConstraintFunction">The inequality constraint function, i.e. a argument x will be accepted iff c(x) &lt; <paramref name="tolerance"/> component-wise.</param>
 /// <param name="constraintFunctionDimension"> The dimensionality of the constraint function.</param>
 /// <param name="tolerance">An array of at least <paramref name="constraintFunctionDimension"/> elements that represents the tolerance in each constraint dimension; or <c>null</c> for zero tolerances.</param>
 /// <returns>A value indicating whether the inequality constraint has been added.</returns>
 public NLoptResultCode AddInequalityConstraint(NLoptVectorInequalityConstraintFunction inequalityConstraintFunction, int constraintFunctionDimension, double[] tolerance)
 {
     if (m_NLopPtr == IntPtr.Zero)
     {
         throw new ObjectDisposedException("NLoptPtr");
     }
     return(nlopt_add_inequality_mconstraint(m_NLopPtr, constraintFunctionDimension, inequalityConstraintFunction, IntPtr.Zero, tolerance));
 }
        /// <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 => { }
                                       ));
        }
Exemplo n.º 3
0
 private static extern NLoptResultCode nlopt_add_inequality_mconstraint(IntPtr opt, int m, [MarshalAs(UnmanagedType.FunctionPtr)] NLoptVectorInequalityConstraintFunction constraintFunction, IntPtr data, double[] tolerance);
        /// <summary>Creates a new <see cref="NLoptConstraint"/> object.
        /// </summary>
        /// <param name="polynomialConstraint">The specific constraints in its <see cref="MultiDimRegion.Polynomial"/> 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.Polynomial polynomialConstraint)
        {
            if (polynomialConstraint == null)
            {
                throw new ArgumentNullException(nameof(polynomialConstraint));
            }
            if (nloptMultiDimOptimizer.Configuration.NonlinearConstraintRequirement.HasFlag(NLoptNonlinearConstraintRequirement.SupportsInequalityConstraints) == false)
            {
                throw new InvalidOperationException("The NLopt algorithm does not support linear inequality for polynomial constraints");
            }

            /* we split the constraint to at most two NLopt constraints c_1(x) <= \epsilon and c_2(x) <= \epsilon, where
             *    c_1(x) = P(x) - upper bound,
             *    c_2(x) = lower bound - P(x),
             *    where P(x) is the polynomial representation of the constraint.
             *
             * We use the NLopt vector constraint representation to combine both constraint, because the evaluation is almost identically.
             */

            if ((Double.IsNegativeInfinity(polynomialConstraint.LowerBound) == false) && (Double.IsPositiveInfinity(polynomialConstraint.UpperBound) == false))
            {
                NLoptVectorInequalityConstraintFunction c = (m, result, n, x, grad, data) =>
                {
                    double polynomialValue = 0.0;
                    foreach (var term in polynomialConstraint.Terms)
                    {
                        double temp = 0.0;
                        foreach (var monomial in term.Item2)
                        {
                            temp += DoMath.Pow(x[monomial.ArgumentIndex], monomial.Power);
                        }
                        polynomialValue += term.Item1 * temp;
                    }

                    if (grad != null)
                    {
                        for (int j = 0; j < n; j++)
                        {
                            grad[j] = 0.0;
                        }
                        foreach (var term in polynomialConstraint.Terms)
                        {
                            foreach (var monomial in term.Item2)
                            {
                                grad[monomial.ArgumentIndex] -= term.Item1 * monomial.Power * DoMath.Pow(x[monomial.ArgumentIndex], monomial.Power - 1);
                            }
                        }
                    }
                    result[0] = polynomialValue - polynomialConstraint.UpperBound;
                    result[1] = polynomialConstraint.LowerBound - polynomialValue;
                };

                var tolerance = new[] { MachineConsts.Epsilon, MachineConsts.Epsilon };

                return(new NLoptConstraint(this,
                                           polynomialConstraint.Dimension,
                                           "Polynomial constraint",
                                           nloptPtr =>
                {
                    var code = nloptPtr.AddInequalityConstraint(c, 2, 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));
                    }
                }
                                           ));
            }
            else if (Double.IsNegativeInfinity(polynomialConstraint.LowerBound) == false)
            {
                return(CreateSingle(polynomialConstraint, polynomialConstraint.LowerBound, sign: 1));
            }
            else
            {
                return(CreateSingle(polynomialConstraint, polynomialConstraint.UpperBound, sign: -1));
            }
        }