I recently ran into this same question and came up with a slightly more convenient solution based on Jens answer that I think is different enough to be worth sharing. First I define two functions, RandomVariableQ
and MakeRandomVariable
(*atoms are not RVs unless explicitly marked*)
RandomVariableQ[expr_?AtomQ] := False
(*recurse down expression tree until we reach an atom or expectation value*)
RandomVariableQ[expr_ /; (!AtomQ[expr]) && (Head[expr] =!= AngleBracket)] := Or @@ Map[RandomVariableQ,List @@ expr]
(*expectation values are not RVs*)
RandomVariableQ[expr__AngleBracket] := False
(*make a symbol into a RV*)
MakeRandomVariable[x__Symbol] := (# /: RandomVariableQ[#] := True;) & /@ List[x]
MakeRandomVariable
can be used to mark a particular symbol as being a random variable that cannot be factored out of an expectation. RandomVariableQ
returns true if an expression contains a random variable that is not wrapped in an expectation value.
I then define AngleBracket
as the expectation value
(*Linear*)
AngleBracket[expr_Plus] := AngleBracket /@ expr
AngleBracket[Times[x_, y__]] /; !RandomVariableQ[x] := x AngleBracket[Times[y]]
(*Expectation values only operate on RVs*)
AngleBracket[expr_ /; !RandomVariableQ[expr]] := expr
(*Expand before taking expectation values*)
AngleBracket[Power[expr_Plus, n_]] := AngleBracket[Expand[Power[expr, n]]]
AngleBracket[Times[expr_Plus, x_?RandomVariableQ]] := AngleBracket[Expand[expr x]]
Note here I am using RandomVariableQ
instead of FreeQ
. This allows the code to correctly recognize that arbitrary functions of expectation values can be factored out of an expectation value, i.e $\left\langle f(\left\langle x \right\rangle) \right \rangle = f(\left\langle x \right\rangle)$
We can test the code by computing the first 5 central moments of a random variable
MakeRandomVariable[x];
Table[AngleBracket[(x - AngleBracket[x])^n], {n, 2, 5}] // TableForm
which produces
$$
\begin{array}{c}
\left\langle x^2\right\rangle -\langle x\rangle ^2 \\
\left\langle x^3\right\rangle -3 \left\langle x^2\right\rangle \langle x\rangle +2 \langle x\rangle ^3 \\
\left\langle x^4\right\rangle -4 \left\langle x^3\right\rangle \langle x\rangle +6 \left\langle x^2\right\rangle \langle x\rangle
^2-3 \langle x\rangle ^4 \\
\left\langle x^5\right\rangle -5 \left\langle x^4\right\rangle \langle x\rangle +10 \left\langle x^3\right\rangle \langle x\rangle
^2-10 \left\langle x^2\right\rangle \langle x\rangle ^3+4 \langle x\rangle ^5 \\
\end{array}
$$
as desired. This is an improvement on the current solution which cannot simplify expressions such as expect[expect[randX[1]]^2 randX[1]]
because it does not recognize that expect[randX[1]]^2 can be pulled out of the expectation value. This also works as expected with multiple random variables.
expect
function would operate,randX[1]^5 * randX[2]^0 * randX[3]^4
would be changed torandX[1]^5 * randX[3]^4
? $\endgroup$expect[randX[1]^2]
to the associated moments of the random variables that you're considering. This example (assuming that the moments exist) would result in $\sigma^2+\mu^2$ (if $\sigma^2$ is the variance ofrandX[1]
and $\mu$ is the mean ofrandX[1]
. Do you have a convention for naming the moments of X[i] and Y[i] and the expectations of their products? $\endgroup$