1
$\begingroup$

I'd like to fit a model where one of the inputs is a variable length list.

For example

FindFit[{{1, {0, 1}, 3}, {2, {1, 1}, 6}, {3, {1, 0, 1}, 8}}, c1*x + c2*Plus @@ y, {c1, c2}, {x, y}]

Returns the error FindFit: First argument [...] in FindFit is not a list or a rectangular array. I guess another function should be used instead of FindFit.

What's the best way to do it?

$\endgroup$
  • 1
    $\begingroup$ your data is not in any of the forms allowed. See first 2 lines in help. $\endgroup$ – Nasser May 23 at 12:29
  • $\begingroup$ @Nasser What function should be used instead for such a function with variable length lists as a variable? $\endgroup$ – Robe May 23 at 12:36
  • 1
    $\begingroup$ I am not really sure. As I do not understand what your data represents in this context of fitting. But as you can see, Mathematica's FindFit does not accept this structure of your data. May be someone else knows more and can help. $\endgroup$ – Nasser May 23 at 12:38
  • $\begingroup$ @Nasser I want to find certain coefficients (fitting), in the example c1 and c2, which are in a function (in the example c1*x+c2*Plus@@y) whose inputs can be lists of variable length. The data is just an example $\endgroup$ – Robe May 23 at 13:20
  • 4
    $\begingroup$ Do the processing Plus @@ y on the data, not in the model. $\endgroup$ – Marius Ladegård Meyer May 23 at 13:21
1
$\begingroup$

Do the summation on your data before modeling, then fit to a simpler model:

FindFit[
  {#1, Plus @@ #2, #3}& @@@ {{1, {0, 1}, 3}, {2, {1, 1}, 6}, {3, {1, 0, 1}, 8}},
  c1 x + c2  y,
  {c1, c2},
  {x, y}
]

{* Out: {c1 -> 2., c2 -> 1.} *)

In passing, I would also recommend that you upgrade to LinearModelFit or NonlinearModelFit for your data fitting needs: you will get access to a lot of interesting statistical descriptors together with the results of the fit.

| improve this answer | |
$\endgroup$
0
$\begingroup$

Not sure whether I got your point, Assuming the second part of your list is of varying length and the values are positive integers you can do a kind of Gödelisation. To encode the list:

codeIt[list_] := Module[{len = Length@list, primes},
  primes = Prime[Range@len];
  Times @@ (primes^list)
  ]

so the list {1, 0, 3} is encoded to 250. To decode use:

decodeIt[input_Integer] := Module[{temp = FactorInteger[input],
   largestPrime, (* largest prime in list *)
   outPrimes, (* 
   list of primes up to largestPrime*)
   res 
   },
  largestPrime = First[Last[temp]];
  outPrimes = Prime[Range@PrimePi[largestPrime]];
  res = Join[Join[{#}, {0}] & /@ Complement[outPrimes, First /@ temp],
     temp];
  Last /@ SortBy[res, First]
  ]

(this could be written in fewer lines but less readable). So test

    decodeIt[250]
(*{1, 0, 3}*)

Then we have your input:

list = {{1, {0, 1}, 3}, {2, {1, 1}, 6}, {3, {1, 0, 1}, 8}}

encode it:

inputFit = MapAt[codeIt, list, {All, 2}]

Do the fitting-job

    FindFit[inputFit, c1 *x + c2*y, {c1, c2}, {x, y}]
(*{c1 -> 6., c2 -> -1.}*)

then you can use the fitted function and decode the output to get lists again (Gödel must have been a tough guy).

| improve this answer | |
$\endgroup$

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