24

14

I intend to write a function which calculates the result and the error for any formula with any amount of variables using the Gauß Error Propagation.

The error $\mathrm{d}R$ for a function $A(a,b,c)$ and the corresponding errors $\mathrm{d}a, \mathrm{d}b$, and $\mathrm{d}c$ are calculated with

$$\mathrm{d}R=\left[\left(\partial_{a}A\,\mathrm{d}a\right)^2+\left(\partial_{b}A\,\mathrm{d}b\right)^2+\left(\partial_{c}A\,\mathrm{d}c\right)^2\right]^{1/2}$$

Since there is huge amount of formulas one could wish to use with different amounts of variables, the function has to be adaptive.

My first shot is the following function, which already does the job pretty well.

```
Gaus[φ_, data_?MatrixQ] := (
Do[Evaluate[Symbol["x" <> ToString[i]]] = data[[i, 1]], {i, Length[data]}];
α = Norm[Derivative[##][φ][Sequence @@
Evaluate[Table[Symbol["x" <> ToString[i]], {i, Length[data]}]]] &
@@@ IdentityMatrix[Length[data]]*data[[All, 2]]];
Α = φ[Sequence @@ Evaluate[Table[Symbol["x" <> ToString[i]], {i, Length[data]}]]];
Print[{N[Α], N[α]}]
)
```

It accepts a function $\phi$ with a layout like

```
R[a_, b_, c_] := a*b/c
```

and a list of {value,error} pairs. Then it creates an corresponding amount of intermediate variables x1,...,xn with n being the number of pairs. These are used to calculate the error $\alpha$ and the value A, which are then printed.

And now to my problem. I really want the intermediate variables xi and $\alpha$ and A to be local. Currently they are global, which isn't a problem for the function, as existing variables are overwritten, but proved to be annoying in other calculations.

My first try was to use Module similar to this

```
Module[{Evaluate[Table[Symbol["x" <> ToString[i]], {i, 2}]], a, b}, a + b]
```

Module::lvsym : "Local variable specification {Evaluate[Table[Symbol["x" <> ToString[i]], {i, 2}]], a, b} contains Evaluate[Table[Symbol["x" <> ToString[i]], {i, 2}]], which is not a symbol or an assignment to a symbol.

which produces only the error message above. I could of course define the variables x1 to x10 directly, as I will rarely have more than ten values per formula, but this would be terribly inelegant.

Several futile tries later I am running out of possibilities to rephrase my search, since I neither am a native speaker nor have significant programming background.

So I would be happy, if someone could provide an idea to create adaptive amount of local variables.

**Update:**
Thanks to the answer of Jens about the use of downvalues, i could modify my code to the following.

```
Gaus[ϕ_, data_?MatrixQ] := Module[{df, f, x},
Do[x[i] = data[[i, 1]], {i, Length[data]}];
df = Norm[Derivative[##][ϕ] [Sequence @@ Array[x, Length[data]]
] & @@@ IdentityMatrix[Length[data]]*data[[All, 2]]];
f = ϕ[Sequence @@ Array[x, Length[data]]];
Print[{N[f], N[df]}]
]
```

For some reason I had to get rid of the Elavaluate[..] Function, although, from what I understand of it, there no reason for an error. This basically answers my introductory question.

The comment of acl and a night of sleep made me realize that the approach is indeed wrong, as the task can be achieved without using intermediate variables just using sequence, which somehow eluded me.

```
Gauss[ϕ_, data_?MatrixQ] := Module[{df, f},
df = Norm[Derivative[##][ϕ] [Sequence @@ data[[All, 1]]
] & @@@ IdentityMatrix[Length[data]]*data[[All, 2]]];
f = ϕ[Sequence @@ data[[All, 1]]];
Print[{N[f], N[df]}]
]
```

This seems to me like much cleaner and easier function.

I'd go for

`x/@Range[2]`

. But yes I agree and, as I say in my answer, this is almost certainly the wrong approach. – acl – 2012-12-21T22:46:52.740@acl I just think

`Array`

is more readable, so why not use it? – Jens – 2012-12-21T22:50:41.387Certainly; I'm not implying it's better to use

`Map`

. I find`x/@Range[2]`

more readable myself, for some reason. – acl – 2012-12-21T22:54:36.763Thank you for your answer, i wasn't aware of the possibility of downvalues. I just assumed that I would need a new symbol for every value. I adjusted my code accordingly The track, which lead to this approach started with the problem, that the derivate function doesn't accept lists as arguments and my first idea was to use variables as intermediate. In addition the comment from acl about the wrong approach got me thinking and I realized, that the sequence solves the problem, avoiding the variables. – Crown42 – 2012-12-22T07:55:00.157