0
$\begingroup$

I'd like to minimize some function (of 3-4 variables) over a big list of integers, but not consecutive. Like arr = {5, 10, 7, 101,...}
I did not understand this answer at all.
And this code:

NMinimize[{someFunc[c1, c2 , c3], MemberQ[arr, c1]&&MemberQ[arr, c2]&&MemberQ[arr, c3]}, {c1, c2 c3}]

not work.

$\endgroup$
1
  • $\begingroup$ I believe this is a hard problem (NP?) and there are instances of someFunc where only an explicit enumeration of all tuples will discover the optimum (like Bill suggests). The quality of the tricks shown here will depend very much on the detailed form of someFuncand whether or not it has some semblance of continuity that allows for classical optimization algorithms to work. For example, if you're trying to optimize a classical disordered spin glass, then you're sheer out of luck here. $\endgroup$
    – Roman
    Jul 13 at 11:03
1
$\begingroup$

Use integer constraints, restrict the integers to [1,length] of arr, and use IntegerQ to prevent symbolic evaluation of the objective. This will perform well up to a certain point beyond which you'll need to look at other techniques like integer programming, or other kinds of optimization like ResourceFunction["AntColonyOptimization"]

Remove["Global`*"]

SeedRandom[1];
arr = RandomInteger[10^4, 1000];

someFunc[c1_, c2_, c3_] := c1^2 - c2^3 + c3

objective[i1_?IntegerQ, i2_?IntegerQ, i3_?IntegerQ] := 
 someFunc[arr[[i1]], arr[[i2]], arr[[i3]]]

With[{len = Length[arr]},
 NMinimize[{objective[i1, i2, i3],
   1 <= i1 <= len,
   1 <= i2 <= len,
   1 <= i3 <= len}, {i1 ∈ Integers, i2 ∈ Integers, i3 ∈ Integers}]]

For AntColonyOptimization it's fairly simple:

possibValues = Table[RandomSample[arr], {i, Range[3]}];
result = ResourceFunction["AntColonyOptimization"][
  possibValues, someFunc @@ # &]
someFunc @@ result

(* {196, 9979, 6971} : -993713175352*)
$\endgroup$
1
  • $\begingroup$ Yes, this works great, thank you! $\endgroup$
    – lesobrod
    Jul 13 at 9:41
2
$\begingroup$

So you want c1,c2,c3 to be elements of arr. And they don't have to be distinct elements. That makes me think Tuples. And you want to find the smallest value of someFunc given those three elements. That makes me think SortBy. And you want to know what c1,c2,c3 are and the value of someFunc given those three values.

arr = {5, 10, 7, 101};
someFunc[c1_,c2_,c3_]:=c1^2-3*c2+1/c3; (*make up some function*)
First[SortBy[Map[{someFunc@@#,#}&,Tuples[arr,3]],First]]

and that returns

{-28077/101, {5, 101, 101}}

So c1==5 and c2==101 and c3==101 means someFunc returns -28077/101 and that is the minimum.

Now try that with your actual someFunc and your actual arr. You can leave off that First and look at the whole list that it returns and try to make certain it is correctly calculating all the tuples and it is correctly choosing the smallest value from someFunc.

Is this simple enough that you can figure out the thought process I used to do this? That is the most important part so that you can perhaps think similarly on your future problems and come up with your own solutions.

There are almost always other ways of doing almost anything in Mathematica. Try to pick the simplest way that you can understand and remember and be able to modify and use when you need to do something somewhat different in the future.

Check this very carefully to try to make certain I haven't made a mistake.

$\endgroup$
4
  • $\begingroup$ Thank you, for small lists it works well. But in real task length of list is about 10000, so it have to be numerical calculation ( $\endgroup$
    – lesobrod
    Jul 13 at 9:11
  • $\begingroup$ So use RandomSample[arr,3] to select some random subset of arr. Calculate the value of someFunc given that. Save the 3 parameters and the result as the best result found so far. Then repeat that a billion times and every time you find a smaller result save that as the new best result. BUT that RandomSample isn't going to give you repetitions of your parameters. So can you think of another way that will allow repetitions but won't require you generate all those tuples at once? That isn't hard to do. $\endgroup$
    – Bill
    Jul 13 at 9:15
  • $\begingroup$ MinimalBy[Tuples[arr, 3], Apply[someFunc]] is simpler & faster. $\endgroup$
    – Roman
    Jul 13 at 9:46
  • $\begingroup$ @Bill you could use RandomChoice instead of RandomSample to get the repetitions. $\endgroup$
    – flinty
    Jul 13 at 10:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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