vgivanov
(Vladimir Ivanov)
April 19, 2020, 7:18pm
1
Hello!
I want to make a procedure for minimization of function that takes a vector of arbitrary dimension as the input argument (it is the starting point) and provides a vector as the output one. My solution:
In[1] := myFindMinimum[func_, p0_List] := Module[{sol, s1, s2},
s1 = "{";
s2 = "{";
Do[
s1 = s1 <> "p" <> ToString[i] <> ",";
s2 = s2 <> "{p" <> ToString[i] <> "," <> ToString[p0[[i]]] <> "},",
{i, Length[p0]}
];
s1 = StringDrop[s1, -1] <> "}";
s2 = StringDrop[s2, -1] <> "}";
sol = ToExpression[
"FindMinimum[" <> ToString[func] <> "[" <> s1 <> "]," <> s2 <>
"]"];
{sol[[1]], ToExpression[s1] /. sol[[2]]}
]
It works:
In[2] := func[p_List] := Plus @@ (p^2)
myFindMinimum[func, {1, 1, 1, 1}]
Out[2] := {0., {0., 0., 0., 0.}}
However, it is rather ugly. Are there better solutions?
… Are there better solutions?
Hi Vladimir, in Mathematica there are virtually always better solutions! One approach might be:
myFindMinimum[func_, p0_List] := Module[{vars, sol},
vars = Table[Unique[], Length[p0]];
sol = FindMinimum[func[vars], Transpose[{vars, p0}]];
{sol[[1]], vars /. sol[[2]]}]
vgivanov
(Vladimir Ivanov)
April 20, 2020, 11:24am
3
Thank you, Henrik!
I guess you mean
vars = Table[Unique[], {Length[p0]}];
The idea is great. But I see a problem with memory leak here. Every time you use the function you create a new set of variables:
func[p_List] := Plus @@ (p^2)
m1 = MemoryInUse[]
Do[myFindMinimum[func, {1, 1, 1, 1}], {1000}]
m2 = MemoryInUse[]
m2 - m1
29771888
30893576
1121688
Let’s compare:
m1 = MemoryInUse[]
Do[FindMinimum[p1^2 + p2^2 + p3^2 + p4^2, {p1, 1}, {p2, 1}, {p3, 1}, {p4,1}], {1000}]
m2 = MemoryInUse[]
m2 - m1
30944336
30947488
3152
Can we avoid this effect?
Hi Vladimir,
I guess e.g. Table[..., 4] and Table[..., {4}] does not make a difference.
But I see a problem with memory leak here. Every time you use the function you create a new set of variables …
Well, yes, this effect is somewhat typical - you find it e.g. whenever you use Module (with or without local variables):
test0 := Module[{}, {}]
test1 := Module[{tmp}, tmp]
m0 = MemoryInUse[]
test0;
m1 = MemoryInUse[]
test1;
m2 = MemoryInUse[]
Differences[{m0, m1, m2}]
vgivanov
(Vladimir Ivanov)
April 20, 2020, 3:45pm
5
Table::itform: Argument 1 at position 2 does not have the correct form for an iterator. >>
At least Mathematica 9 requires an iterator there:
Table[1, 3]
Table::itform: Argument 1 at position 2 does not have the correct form for an iterator.
Table[1, {3}]
{1, 1, 1}
Well, yes, this effect is somewhat typical - you find it e.g. whenever you use Module (with or without local variables):
Module does not eat memory so agressively. So I like to use a `hybrid’ variant of the procedure:
myFindMinimum2[func_, p0_List] := Module[{svars, vars, sol},
svars = "{";
Do[svars = svars <> "p" <> ToString[i] <> ",", {i, Length[p0]}];
vars = ToExpression[StringDrop[svars, -1] <> "}"];
sol = FindMinimum[func[vars], Transpose[{vars, p0}]];
{sol[[1]], vars /. sol[[2]]}
]
MemoryInUse[]
Do[myFindMinimum2[func, {1, 1, 1, 1}], {1000}]
MemoryInUse[]
% - %%%
35267376
35269064
1688
But I still look for more elegant solutions.