Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to have a variable argument list in Mathematica

Right now I have code where some function func executes the way I want it to when I give it specific arguments in its definition (so I make it func[x1_,x2_]:=... and then later I make it func[x1_,x2_,x3_]:=... without changing anything else and it works the way I would like it to). Is there a way to automatically substitute whatever arguments I specify for this function?

UPDATE:

I haven't isolated the problem code yet, but this code here does not do what I want:

(* Clear all stuff each time before running, just to be safe! *)
\
Clear["Global`*"]

data = {{238.2, 0.049}, {246.8, 0.055}, {255.8, 0.059}, {267.5, 
    0.063}, {280.5, 0.063}, {294.3, 0.066}, {307.7, 0.069}, {318.2, 
    0.069}};
errors = {{x1, 0.004}, {x2, 0.005}};

getX[x1_, x2_] := 1/x2^2

getY[x__] = 
 Evaluate[Simplify[
   Sqrt[Sum[(D[getX[x], errors[[i]][[1]]] errors[[i]][[2]])^2, {i, 
      Length[errors]}]]]]

map[action_, list_] := action @@@ list

y = map[getY, data];
y

getY[2, 3]

This code here does: (gives {67.9989, 48.0841, 38.9524, 31.994, 31.994, 27.8265, 24.3525, 24.3525} for y)

(* Clear all stuff each time before running, just to be safe! *) \ Clear["Global`*"]

data = {{238.2, 0.049}, {246.8,
0.055}, {255.8, 0.059}, {267.5, 
    0.063}, {280.5, 0.063}, {294.3, 0.066}, {307.7, 0.069}, {318.2, 
    0.069}}; errors = {{x2, 0.004}, {x1, 0.005}};

getX[x1_, x2_] := 1/x2^2

getY[x1_, x2_] :=   Evaluate[Simplify[ Sqrt[Sum[(D[getX[x1, x2], errors[[i]][[1]]] 
        errors[[i]][[2]])^2, {i, Length[errors]}]]]]

map[action_, list_] := action @@@ list

y = map[getY, data]; y

getY[2, 3]

UPDATE 2:

My math:

I intend to take the square root of the sum of the squares of all the partial derivatives of the getX function. Thus the body of the getY function. Then I want to evaluate that expression for different values of x1 and x2. Thus I have the arguments for getY.

like image 356
wrongusername Avatar asked Apr 21 '11 16:04

wrongusername


2 Answers

Use __, e.g.

In[4]:= f[x__] = {x}
Out[4]= {x}

In[5]:= f[1,2,3,4,5,6]
Out[5]= {1, 2, 3, 4, 5, 6}

In[6]:= f[a,b,c]
Out[6]= {a, b, c}
like image 51
kennytm Avatar answered Oct 10 '22 04:10

kennytm


Well the issue is that in the first version, with explicit number of arguments, you have used Evaluate to evaluate the right hand side. You can not do this when the number of arguments is variable, because evaluator does not know which signature of getX to use.

So the solution is to replace getY with the following:

getY[x__] := (Simplify[
    Sqrt[(D[getX @@ 
          errors[[1 ;; Length[{x}], 1]], {errors[[All, 1]]}]. 
        errors[[All, 2]])^2]]) /. 
  Thread[errors[[1 ;; Length[{x}], 1]] -> {x}]

This would first use variables from errors list exactly as many as you have supplied in the arguments of getY, compute the derivative symbolically, and then perform the Dot, instead of Sum which is faster. Then the outputs will be the same.

Notice that in your two versions of the code, errors have different values.

Alternatively, you can use Derivative like so:

getY2[x__] := 
 Abs[(Derivative[##][getX][x] & @@@ 
     IdentityMatrix[Length[{x}]].errors[[All, 2]])]

Using it gives the same result.

like image 21
Sasha Avatar answered Oct 10 '22 04:10

Sasha