6
$\begingroup$

I have a set of complicated 100 constraints which can be computed numerically for the given iterative values of the design variables. Once evaluated the lhs of the constraints are available as a vector with all numbers. All the constraints are of the form (number <= 0).

How can I state that each of these elements of the vector should be <= 0 inside NMinimize ?

In the following trivial example I have used a simple constraint function for better communication; but my actual problem is more complicated and has 3 design variables.

f[x_] := -x^2 + 4 x;

const[x_?NumericQ] := Module[{n, xs, j, xval, ret},
n = 100;
xs = Table[j*(x/n), {j, 1, n}];
ret = {-1};
For[j = 1, j <= n, j++,
xval = xs[[j]];
ret = Join[ret, {f[xval]}];
];
Return[ret];
]

The optimization part

NMinimize[x^2 - 28 x, Thread[const[x] <= 0], {x}]

Returns the following error

NMinimize::bcons: The following constraints are not valid: 
{const[x]<=0}.     Constraints should be equalities, inequalities, 
or domain specifications involving the variables. >>
$\endgroup$

2 Answers 2

4
$\begingroup$

Most of the Methods used by NMinimize try to enforce constaints by creating a penalty function, which behaves such that when constraints are violated, the penalty function should grow and thus take us away from unconstrained minima. You can read a little about it here.

In order to do this, NMinimize actually needs to know the functional dependence of the constraints on the variables, so in your case that won't be feasible. But we can create our own penalty function!

In your case, this is not so hard given that all your constraints are of the form "something should be negative". My proposal:

penalty[x_?NumericQ] := 100*Total[UnitStep[const[x]]]

This function will add 100 to the function we want to minimize for every element of const[x] that is not negative. Depending on the values of the function being minimized, we can adjust 100 to something more appropriate.

Now we can do

NMinimize[f[x] + penalty[x], x]

and for f[x_] := x^2 - 28 x we get

{-196., {x -> 14.}}

(which in this case is equal to the unconstrained minimum) without any error messages. A very basic check that it actually enforces the constraints can be done for this function f by changing const to

const[x_?NumericQ] := {x - 13}

i.e. we don't allow x to grow larger than 13. Now

NMinimize[f[x] + penalty[x], x]

gives

{-195., {x -> 13.}}

as it should.

$\endgroup$
0
$\begingroup$

The form needed by NMinimize for constraints are equalities, inequalities or the variable being a member of a region.

For example when you apply your function const[x] using a variable and Thread it over LessEqual you get out the following list:

cons = 4 (# x/100) - (# x/100)^2 <= 0 & /@ Range[100]

which for brevity I will only show a sample of three the 100 elements

{x/25 - x^2/10000 <= 0, (2 x)/25 - x^2/2500 <= 0, ..., 4 x - x^2 <= 0}

In order to use constraints in NMinimize the required form is:

NMinimize[{f, cons}, x]

The tricky part is splicing the list of 100 constraints into the list containing f. In order to do that use Apply and Sequence.

NMinimize[{x^2 - 28 x, Sequence @@ cons}, x]

(* {-5.16344*10^-19, {x -> 1.84409*10^-20}} *)

Try this method on the actual constraints. It may be a chore to place them in a list but if you are able to do so you should be successful.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.