So, I'm fairly new to Mathematica (apologies in advance for the noobiness), and I'm having some problems regarding fitting the parameters of a user defined function to data. I'll give a representative toy example of what I'm trying to accomplish.

Imagine that I have data that is comprised of two lists:

TestData = {
  {1, 0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15},
  {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}

And I have a model/function that itself produces discrete data such as this. This function would be something like:

TestFunction[A_, B_] :=  
   Module[{results = {}, vec1 = {}, vec2 = {}},   
      For[i = 1, i < 18, i++, Do;  
         [vec1 = Append[vec1, (A - i)];  
          vec2 = Append[vec2, (B + i)]]];  
      results = Append[results, vec1];  
      results = Append[results, vec2];  

Now, I want to find the parameters A and B that give the best approximation to TestData (i.e., such as the distance between TestData and the results of the function would be minimized).

I tried looking into the FindFit and NonlinearModelFit functions, but these would seem to be more suited for continuous functions(?), so I'm not sure how to use it with a function that returns specific and discrete values. How would you go about solving this question?

Thank you very much in advance.

  • $\begingroup$ Your TestFunction is not working for me. $\endgroup$ Jan 30 '13 at 12:19
  • $\begingroup$ Should be working now, thanks $\endgroup$
    – Sousky
    Jan 30 '13 at 13:41
  • $\begingroup$ FindFit/NonlinearModelFit are usable for this. They don't intrinsically care if the function is continuous or discrete, as they only evaluate it at the abscissae you give in your data. $\endgroup$ Jan 30 '13 at 13:48
  • $\begingroup$ In Mathematica your test function can be written as testF[a_, b_] := {Table[a - i, {i, 17}], Table[b + i, {i, 17}]}, which both faster and simpler. $\endgroup$
    – m_goldberg
    Feb 1 '13 at 7:45

First of all, two general remarks.

  1. Try to avoid using procedural loops (For, While etc.) in Mathematica. Instead use functions like Map (/@), Array, Apply (@@) or Table.
  2. You should always use lower case letters for your own functions and variables.

The Do in your TestFunction is either missing a second argument, or (judging from the structure of your test data) shouldn't be there at all. I assume that you want the function to work like this:

testFunction[a_, b_] := Transpose@Table[{a - i, b + i}, {i, 17}]

Since the first list in testFunction's result depends only on a and the second only on b, respectively, you can find the values for a and b seperately. Nevertheless, here's a piece of code that minimizes the norm of the difference for a and b in one step:

Minimize[Plus @@ Norm /@ (testFunction[a, b] - testData), {a, b}]

{0, {a -> 2, b -> 3}}

The result is the minimum of the norm and a list of replacement rules for a and b.

For more complicated data or functions, it probably makes sense to use NMinimize instead.

  • $\begingroup$ Yeah, I have old habits from other programming languages. But that solution looks nice, thank you so much. How would you add constraints to the parameters, though? I'm trying to apply something of the sort of NMinimize[ Plus @@ Norm /@ {(testFunction[a, b] - testExperimentalData), a < 0}, {a, b}] but without much luck. $\endgroup$
    – Sousky
    Jan 30 '13 at 14:13
  • 1
    $\begingroup$ Try Minimize[{Plus @@ Norm /@ (testFunction[a, b] - testData), a < 0}, {a, b}], with the opening { before Plus. Otherwise you apply plus to your constraint as well. Also notice the warning message, since there is no real minimum for that particular constraint. $\endgroup$
    – einbandi
    Jan 30 '13 at 14:22
  • $\begingroup$ Ah, perfect, thanks once again. Now, let's see if I can apply this beyond the toy example :) $\endgroup$
    – Sousky
    Jan 30 '13 at 14:34

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.