Let's say I want to minimize a function that uses a Table named a with the Conjugate Gradient Method of FindMinimum.

Instinctively I do the following :

FindMinimum[(Sum[a[[i]]*Cos[1.3], {i, 1, 2}])^2, {a, {0, 0}}, Method -> "ConjugateGradient"]

But I obviously get the following messages and results :

During evaluation of In[135]:= Part::partd: Part specification a[[1]] is longer than depth of object. >>
During evaluation of In[135]:= Part::partd: Part specification a[[2]] is longer than depth of object. >>

{0., {a -> {0., 0.}}}

So, to overcome this little difficulty, I tried the following :

a = {a1, a2};
FindMinimum[(Sum[a[[i]]*Cos[1.3], {i, 1, 2}])^2, {a, {0, 0}}, Method -> "ConjugateGradient"]

During evaluation of In[136]:= Part::partd: Part specification a[[1]] is longer than depth of object. >>
During evaluation of In[136]:= Part::partd: Part specification a[[2]] is longer than depth of object. >>

{0., {{a1, a2} -> {0., 0.}}}

and again I obtain the same error messages. So I came down to the dirty manner:

FindMinimum[(a1*Cos[1.3] + a2*Cos[1.3])^2, {{a1, 2}, {a2, 0}}, 
  Method -> "ConjugateGradient"]

which this time provided me with actual results :

{2.86222*10^-17, {a1 -> 1., a2 -> -1.}}

Now, while this last alternative works for this simple example and for a Table containing only two values, It will become impossible if I had to do for example:

FindMinimum[(Sum[a[[i]]*Cos[1.3], {i, 1, 1000}])^2, {a, {0, 0}}, 
  Method -> "ConjugateGradient"]

How can I sort this out? I'm aware that there might something wrong with my approach, but I can't find another manner to set this up.

  • $\begingroup$ Note that you did get correct results in all three attempts. (The constant Cos[1.3] can be factored out of your example, showing that any set of numbers summing to zero is a valid solution.) $\endgroup$ – whuber Mar 26 '13 at 22:29
  • $\begingroup$ @whuber oops... you're right! In fact even with the warnings and stuff, it works! Just tested it with some other toy models and it gives the right solutions... Only problem is that it takes unexpectedly long time to converge... $\endgroup$ – Meclassic Mar 26 '13 at 23:31

A solution (maybe to specific) to your example is to consider Sum[a[[i]]*Cos[1.3], {i, 1, 2}]
as the dot product a . {Cos[1.3],Cos[1.3]}.

Then the problem becomes :

FindMinimum[(a . {Cos[1.3], Cos[1.3]}) ^2, {a, {2, 0}},Method -> "ConjugateGradient"]

which is a syntax Mathematica accepts. It gives :


Of course, it can be extended to more variables

| improve this answer | |
  • $\begingroup$ (+1) that's the cleanest solution (I think Mathematica used to be unable to do this, but it got cleverer...) $\endgroup$ – Jens Mar 26 '13 at 22:43

This kind of question gets asked very often. You can do this:

up = 5;
varlst = {a@#, 0.1} & /@ Range[up];
FindMinimum[(Total@Table[a[i]*Cos[1.3], {i, 1, up}])^2, varlst, 
 Method -> "ConjugateGradient"]

Mathematica graphics

does the job.

The reason your attempt does not work is that, if a is not defined, a[[4]] attempts to take the 4th part of the symbol a; but a has length 1, and its only part is a[[0]] which is Symbol, its head... So I replaced a[[i]] by a[i], which creates an expression with head a and i on the branch (the important point is that a[4] is a perfectly normal variable, for purposes of this discussion).

I also replaced Sum by Total@Table[] because Mathematica tries to do clever things with Sum, while Total@Table[] just constructs the list and adds the terms.

The varlst = {a@#, 0.1} & /@ Range[up]; could also have been written varlst=Table[{a[i], 0.1}, {i, 1, up}]; it just constructs the last argument of FindRoot before the options.

| improve this answer | |
  • $\begingroup$ Actually a[[0]] is not a, it's Symbol, which is really the Head of a $\endgroup$ – RunnyKine Jul 18 '14 at 3:24
  • $\begingroup$ @RunnyKine right, fixed $\endgroup$ – acl Jul 18 '14 at 8:41

Another way to get your code to work is this:

a = Array["a", 2];

Clear[a, c];
a = Array[c, 2];
FindMinimum[(Sum[Evaluate@a[[i]]*Cos[1.3], {i, 1, 2}])^2, 
 Thread@{a, {2, 0}}, Method -> "ConjugateGradient"]

{2.86222*10^-17, {c[1] -> 1., c[2] -> -1.}}

Here, I maintained the array a the way you wanted it in the sum, but had to add an Evaluate because Sum has attribute HoldAll so that it doesn't look up the values of its arguments (including a[[i]]) initially.

In FindMinimum, you then have to make sure that the variables represented by a have the correct number. If a isn't assigned any values beforehand, that doesn't work. So I precede the minimization by the assignment a = Array[c, 2] where now c[1] and c[2] are inserted as the entries of array a. The starting values are then formulated in terms of a, but they really are initial conditions for the c[i]. To set those, I use Thread to make the assignments pairwise for each member of the array a and of the value list {2, 0}.

| improve this answer | |

Mathematica 10 introduces Indexed allowing this without error messages:

FindMinimum[(Sum[Indexed[a, i]*Cos[1.3], {i, 1, 2}])^2, {a, {2, 0}}]
{3.97214*10^-18, {a -> {1., -1.}}}
| improve this answer | |

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.