Utility to extract variables from an expression - wolfram-mathematica

I'm looking for a utility that would take an expression and extract all variables in that expression.
Following five examples cover pretty much all of my variable patterns
a,Subscript[a,....],Subscript[a,...][...],a[...],a[...][...]
Here are two test cases.
expr1 = -Log[Subscript[\[Mu], 2][]] Subscript[\[Mu], 2][] -
Log[Subscript[\[Mu], 2][2]] Subscript[\[Mu], 2][2] +
Log[Subscript[\[Beta], 1, 2][]] Subscript[\[Beta], 1, 2][] +
Log[2] Subscript[\[Beta], 1, 2][1] +
Log[Subscript[\[Beta], 1, 2][1]] Subscript[\[Beta], 1, 2][1] +
Log[2] Subscript[\[Beta], 1, 2][2] +
Log[Subscript[\[Beta], 1, 2][2]] Subscript[\[Beta], 1, 2][2] +
Log[Subscript[\[Beta], 2, 3][]] Subscript[\[Beta], 2, 3][] +
Log[Subscript[\[Beta], 2, 3][2]] Subscript[\[Beta], 2, 3][2] +
Log[2] Subscript[\[Beta], 2, 3][3] +
Log[Subscript[\[Beta], 2, 3][3]] Subscript[\[Beta], 2, 3][3];
expr2 = Log[\[Beta][{1, 2}][{}]] \[Beta][{1, 2}][{}] +
Log[2] \[Beta][{1, 2}][{1}] +
Log[\[Beta][{1, 2}][{1}]] \[Beta][{1, 2}][{1}] +
Log[2] \[Beta][{1, 2}][{2}] +
Log[\[Beta][{1, 2}][{2}]] \[Beta][{1, 2}][{2}] +
Log[\[Beta][{2, 3}][{}]] \[Beta][{2, 3}][{}] +
Log[\[Beta][{2, 3}][{2}]] \[Beta][{2, 3}][{2}] +
Log[2] \[Beta][{2, 3}][{3}] +
Log[\[Beta][{2, 3}][{3}]] \[Beta][{2, 3}][{3}] -
Log[\[Mu][{2}][{}]] \[Mu][{2}][{}] -
Log[\[Mu][{2}][{2}]] \[Mu][{2}][{2}]
On[Assert];
Assert[Union#extractVariables#expr1 === Union[Variables[expr1][[9 ;;]]]]
Assert[Union#extractVariables#expr2 === Union[Variables[expr2][[9 ;;]]]]
Here's MrWizard's solution
extractVariables[formula_] := (
pat = _Symbol[___][___] | Subscript[_Symbol, __][___] | Subscript[_Symbol, __] | _Symbol;
Union#Cases[formula, pat, -1]
);

Here is some code I use to get at "variables" in various types of expression (lists, equations, inequalities, and inside numeric functions).
headlist = {Or, And, Equal, Unequal, Less, LessEqual, Greater,
GreaterEqual, Inequality};
getAllVariables[f_?NumericQ] := Sequence[]
getAllVariables[{}] := Sequence[]
getAllVariables[t_] /; MemberQ[headlist, t] := Sequence[]
getAllVariables[ll_List] :=
Flatten[Union[Map[getAllVariables[#] &, ll]]]
getAllVariables[Derivative[n_Integer][f_][arg__]] :=
getAllVariables[{arg}]
getAllVariables[f_Symbol[arg__]] :=
Module[{fvars},
If[MemberQ[Attributes[f], NumericFunction] || MemberQ[headlist, f],
fvars = getAllVariables[{arg}],(*else*)fvars = f[arg]];
fvars]
getAllVariables[other_] := other
One example from provided tests:
In[36]:= getAllVariables[expr2]
Out[36]= {[Beta][{1, 2}][{}], [Beta][{1, 2}][{1}], [Beta][{1,
2}][{2}], [Beta][{2, 3}][{}], [Beta][{2, 3}][{2}], [Beta][{2,
3}][{3}], [Mu][{2}][{}], [Mu][{2}][{2}]}
This could be extended to handle a larger class of expressions, e.g. Boolean, math with dummy variables (e.g. Sum or Integrate), some programmatic constructs. Expect thorny issue to appear.
Anecdote: Way back in the last millenium someone in the Kernel Dept scheduled a meeting to discuss the issue of "What is a variable?" This was within the setting of Mathematica, not general math or CS. All the same, it is an elusive thing to pin down because different functions seem to have different requirements for such entities. My own take on it was to reply that I would be sick that day (of the intended meeting). I do not recall if I was asked how I knew that in advance...
Daniel Lichtblau

The obvious (but presumably incorrect) approach would be:
pat = _Symbol[___][___] | Subscript[_Symbol, __][___] | Subscript[_Symbol, __] | _Symbol;
Cases[expr1, pat, -1]
Cases[expr2, pat, -1]
But frankly I don't understand you question well enough to know where this goes wrong.
If that actually works for you, then I recommend:
extractVariables[formula_] :=
With[{pat = _Symbol[___][___] | Subscript[_Symbol, __][___] | Subscript[_Symbol, __] | _Symbol},
Union#Cases[formula, pat, -1]
]

Related

Speed up symbolic claculation with mathematica

I have wirtten the following code. It is a code for mathematica and I would like to do some "simple" linear algebra with symbols.
The code sets up a matrix (called A) and a vector (called b). Then it solves the euqation A*k=b for k.
Unfortunately, my code is super slow, e.g. for n=5 it takes hours.
Is there any better way for solving this problem? I am not that familiar with mathematica and my code is rather unprofessional, so do you have any hints for speeding things up?
Here is my code.
clear[all];
n = 3;
MM = Table[Symbol["M" <> ToString#i], {i, 1, n}];
RB = Table[
Symbol["RA" <> FromCharacterCode[65 + i] <> ToString#(i + 1)], {i,
1, n - 1}];
mA = Table[Symbol["mA" <> FromCharacterCode[65 + i]], {i, 1, n - 1}];
mX = Table[
Symbol["m" <> FromCharacterCode[65 + i] <> "A"], {i, 1, n - 1}];
R = Table[
Symbol["R" <> FromCharacterCode[64 + i] <> ToString#(j + 1)], {i,
1, n}, {j, 1, n - 1}];
b = Table[-MM[[1]]*(1/(mA[[i]]*(R[[1, i]] - RB[[i]])) -
1/(mX[[i]]*(-R[[i + 1, i]] + RB[[i]]))), {i, 1, n - 1}];
A = Table[
MM[[j + 1]]*(R[[1, j]]/(mA[[i]]*(R[[1, i]] - RB[[i]])) -
R[[i + 1, j]]/(mX[[i]]*(-R[[i + 1, i]] + RB[[i]]))), {i, 1,
n - 1}, {j, 1, n - 1}];
K = LinearSolve[A, b];
MatrixForm[K]
Thanks for any hints!
P.S. The code should run!
You have lots of variables and lots of denominators, both of which can often make things very slow.
Let's try a simpler faster method that solves a generic form of your problem and then substitutes in all your variables and denominators.
n = 5;
MM = ...
...
A = ...
m={{m1,m2,m3,m4},{m5,m6,m7,m8},{m9,m10,m11,m12},{m13,m14,m15,m16}};
sol=Inverse[m].b/.Thread[Rule[Flatten[m],Flatten[A]]]
which gives a solution in fraction of a second. But you need to carefully check this to justify that there are no zero denominators hiding in your problem or this solution.
This method is faster than Inverse[A].b and far faster than LinearSolve[A, b] for your problem, but that time is only for the calculation of the solution and does not include any potentially large amount of time spent using the solution. It also does not include any of the programming hidden inside LinearSolve to deal with potential problems and special cases.
But I am not certain as your n grows larger and your forest of denominators grows far larger that this will continue to be fast or feasible.
Test this carefully before you assume everything works.
P.S. Thank you for the code that actually ran! (I didn't even use the clear[all])

How to input continuation '...' in Matheamtica

I am trying to compute an equation x = (a/(1+r)^1) + (a/(1+r)^2) + (a/(1+r)^3) ... (to infinity); (or to some point like ... +(a/(1+r)^10)
How to input those dots which matheamtica can understand?
Also, how can it, using same or somewhat similar technique understand the input for some simpler expression like 1+3+5+7...+113 (which should be sum of first 114/2 odd numbers)
Thank you
Try these
x = Sum[a/(1 + r)^i, {i, 1, Infinity}]
x = Sum[a/(1 + r)^i, {i, 1, 10}]
x = Sum[2*i - 1, {i, 1, 114/2}]

Create a symbolic orthonormal matrix in mathematica

I need to create a 3 by 3 real orthonormal symbolic matrix in Mathematica.
How can I do so?
Not that I recommend this, but...
m = Array[a, {3, 3}];
{q, r} = QRDecomposition[m];
q2 = Simplify[q /. Conjugate -> Identity]
So q2 is a symbolic orthogonal matrix (assuming we work over reals).
You seem to want some SO(3) group parametrization in Mathematica I think. You will only have 3 independent symbols (variables), since you have 6 constraints from mutual orthogonality of vectors and the norms equal to 1. One way is to construct independent rotations around the 3 axes, and multiply those matrices. Here is the (perhaps too complex) code to do that:
makeOrthogonalMatrix[p_Symbol, q_Symbol, t_Symbol] :=
Module[{permute, matrixGeneratingFunctions},
permute = Function[perm, Permute[Transpose[Permute[#, perm]], perm] &];
matrixGeneratingFunctions =
Function /# FoldList[
permute[#2][#1] &,
{{Cos[#], 0, Sin[#]}, {0, 1, 0}, {-Sin[#], 0, Cos[#]}},
{{2, 1, 3}, {3, 2, 1}}];
#1.#2.#3 & ## MapThread[Compose, {matrixGeneratingFunctions, {p, q, t}}]];
Here is how this works:
In[62]:= makeOrthogonalMatrix[x,y,z]
Out[62]=
{{Cos[x] Cos[z]+Sin[x] Sin[y] Sin[z],Cos[z] Sin[x] Sin[y]-Cos[x] Sin[z],Cos[y] Sin[x]},
{Cos[y] Sin[z],Cos[y] Cos[z],-Sin[y]},
{-Cos[z] Sin[x]+Cos[x] Sin[y] Sin[z],Cos[x] Cos[z] Sin[y]+Sin[x] Sin[z],Cos[x] Cos[y]}}
You can check that the matrix is orthonormal, by using Simplify over the various column (or row) dot products.
I have found a "direct" way to impose special orthogonality.
See below.
(*DEFINITION OF ORTHOGONALITY AND SELF ADJUNCTNESS CONDITIONS:*)
MinorMatrix[m_List?MatrixQ] := Map[Reverse, Minors[m], {0, 1}]
CofactorMatrix[m_List?MatrixQ] := MapIndexed[#1 (-1)^(Plus ## #2) &, MinorMatrix[m], {2}]
UpperTriangle[ m_List?MatrixQ] := {m[[1, 1 ;; 3]], {0, m[[2, 2]], m[[2, 3]]}, {0, 0, m[[3, 3]]}};
FlatUpperTriangle[m_List?MatrixQ] := Flatten[{m[[1, 1 ;; 3]], m[[2, 2 ;; 3]], m[[3, 3]]}];
Orthogonalityconditions[m_List?MatrixQ] := Thread[FlatUpperTriangle[m.Transpose[m]] == FlatUpperTriangle[IdentityMatrix[3]]];
Selfadjunctconditions[m_List?MatrixQ] := Thread[FlatUpperTriangle[CofactorMatrix[m]] == FlatUpperTriangle[Transpose[m]]];
SO3conditions[m_List?MatrixQ] := Flatten[{Selfadjunctconditions[m], Orthogonalityconditions[m]}];
(*Building of an SO(3) matrix*)
mat = Table[Subscript[m, i, j], {i, 3}, {j, 3}];
$Assumptions = SO3conditions[mat]
Then
Simplify[Det[mat]]
gives 1;...and
MatrixForm[Simplify[mat.Transpose[mat]]
gives the identity matrix;
...finally
MatrixForm[Simplify[CofactorMatrix[mat] - Transpose[mat]]]
gives a Zero matrix.
========================================================================
This is what I was looking for when I asked my question!
However, let me know your thought on this method.
Marcellus
Marcellus, you have to use some parametrization of SO(3), since your general matrix has to reflect the RP3 topology of the group. No single parametrization will cover the whole group without either multivaluedness or singular points. Wikipedia has a nice page about the various charts on SO(3).
Maybe one of the conceptually simplest is the exponential map from the Lie algebra so(3).
Define an antisymmetric, real A (which spans so(3))
A = {{0, a, -c},
{-a, 0, b},
{c, -b, 0}};
Then MatrixExp[A] is an element of SO(3).
We can check that this is so, using
Transpose[MatrixExp[A]].MatrixExp[A] == IdentityMatrix[3] // Simplify
If we write t^2 = a^2 + b^2 + c^2, we can simplify the matrix exponential down to
{{ b^2 + (a^2 + c^2) Cos[t] , b c (1 - Cos[t]) + a t Sin[t], a b (1 - Cos[t]) - c t Sin[t]},
{b c (1 - Cos[t]) - a t Sin[t], c^2 + (a^2 + b^2) Cos[t] , a c (1 - Cos[t]) + b t Sin[t]},
{a b (1 - Cos[t]) + c t Sin[t], a c (1 - Cos[t]) - b t Sin[t], a^2 + (b^2 + c^2) Cos[t]}} / t^2
Note that this is basically the same parametrization as RotationMatrix gives.
Compare with the output from
RotationMatrix[s, {b, c, a}] // ComplexExpand // Simplify[#, Trig -> False] &;
% /. a^2 + b^2 + c^2 -> 1
Although I really like the idea of Marcellus' answer to his own question, it's not completely correct. Unfortunately, the conditions he arrives at also result in
Simplify[Transpose[mat] - mat]
evaluating to a zero matrix! This is clearly not right. Here's an approach that's both correct and more direct:
OrthogonalityConditions[m_List?MatrixQ] := Thread[Flatten[m.Transpose[m]] == Flatten[IdentityMatrix[3]]];
SO3Conditions[m_List?MatrixQ] := Flatten[{OrthogonalityConditions[m], Det[m] == 1}];
i.e. multiplying a rotation matrix by its transpose results in the identity matrix, and the determinant of a rotation matrix is 1.

How to make DifferenceRoot and RecurrenceTable useful for non-numeric difference equations?

In answering a physics forum question this morning, I ran into really bad performance of DifferenceRoot and RecurrenceTable compared to calculating the expressions by naively taking derivatives of an exponential generating functional. A very small amount of digging showed that DifferenceRoot and RecurrenceTable do not simplify expressions as they go.
For example, look at the following output of RecurrenceTable and how it simplifies by just Expanding the result:
In[1]:= RecurrenceTable[f[n] == a f[n - 1] + (a - 1) f[n - 2] &&
f[0] == 0 && f[1] == 1,
f, {n, 6}]
% // Expand
Out[1]= {0, 1, a, -1+a+a^2, -a+a^2+a (-1+a+a^2), 1-a-a^2+a (-1+a+a^2)+a (-a+a^2+a (-1+a+a^2))}
Out[2]= {0, 1, a, -1+a+a^2, -2 a+2 a^2+a^3, 1-2 a-2 a^2+3 a^3+a^4}
This quickly gets out of hand, as the leaf count of the 20th iteration (calculated using DifferenceRoot) shows:
dr[k_] := DifferenceRoot[Function[{f, n},
{f[n] == a f[n - 1] + (a - 1) f[n - 2], f[0] == 0, f[1] == 1}]][k]
In[2]:= dr20 = dr[20]; // Timing
dr20Exp = Expand[dr20]; // Timing
Out[2]= {0.26, Null}
Out[3]= {2.39, Null}
In[4]:= {LeafCount[dr20], LeafCount[dr20Exp]}
Out[4]= {1188383, 92}
Which can be compared to the memoized implementation
In[1]:= mem[n_] := a mem[n-1] + (a-1) mem[n-2] // Expand
mem[0] = 0; mem[1] = 1;
In[3]:= mem20 = mem[20];//Timing
LeafCount[mem20]
Out[3]= {0.48, Null}
Out[4]= 92
So my question is:
Are there any options/tricks to get DifferenceRoot and RecurrenceTable to apply a (simplifying) function as they go and thus make them useful for non-numeric work?
Edit: A Sjoerd pointed out below, I foolishly chose an example with a RSolveable closed form solution. In this question I'm primarily concerned with the behaviour of DifferenceRoot and RecurrenceTable. If it helps, imagine the the f[n-2] term is multiplied by n, so that there is no simple closed form solution.
I can't really help with your question as I haven't used those functions until now, and the docs don't give a clue. But why don't you just use RSolve here? It gives a closed form solution for each of the table's elements:
sol = f /. RSolve[f[n] == a f[n - 1] + (a - 1) f[n - 2] &&
f[0] == 0 && f[1] == 1, f, n
][[1, 1]]
sol#Range[6] // Simplify

Summation up to a variable integer: How to get the coefficients?

This is an example. I want to know if there is a general way to deal with this kind of problems.
Suppose I have a function (a ε ℜ) :
f[a_, n_Integer, m_Integer] := Sum[a^i k[i],{i,0,n}]^m
And I need a closed form for the coefficient a^p. What is the better way to proceed?
Note 1:In this particular case, one could go manually trying to represent the sum through Multinomial[ ], but it seems difficult to write down the Multinomial terms for a variable number of arguments, and besides, I want Mma to do it.
Note 2: Of course
Collect[f[a, 3, 4], a]
Will do, but only for a given m and n.
Note 3: This question is related to this other one. My application is different, but probably the same methods apply. So, feel free to answer both with a single shot.
Note 4:
You can model the multinomial theorem with a function like:
f[n_, m_] :=
Sum[KroneckerDelta[m - Sum[r[i], {i, n}]]
(Multinomial ## Sequence#Array[r, n])
Product[x[i]^r[i], {i, n}],
Evaluate#(Sequence ## Table[{r[i], 0, m}, {i, 1, n}])];
So, for example
f[2,3]
is the cube of a binomial
x[1]^3+ 3 x[1]^2 x[2]+ 3 x[1] x[2]^2+ x[2]^3
The coefficient by a^k can be viewed as derivative of order k at zero divided by k!. In version 8, there is a function BellY, which allows to construct a derivative at a point for composition of functions, out of derivatives of individual components. Basically, for f[g[x]] and expanding around x==0 we find Derivative[p][Function[x,f[g[x]]][0] as
BellY[ Table[ { Derivative[k][f][g[0]], Derivative[k][g][0]}, {k, 1, p} ] ]/p!
This is also known as generalized Bell polynomial, see wiki.
In the case at hand:
f[a_, n_Integer, m_Integer] := Sum[a^i k[i], {i, 0, n}]^m
With[{n = 3, m = 4, p = 7},
BellY[ Table[{FactorialPower[m, s] k[0]^(m - s),
If[s <= n, s! k[s], 0]}, {s, 1, p}]]/p!] // Distribute
(*
Out[80]= 4 k[1] k[2]^3 + 12 k[1]^2 k[2] k[3] + 12 k[0] k[2]^2 k[3] +
12 k[0] k[1] k[3]^2
*)
With[{n = 3, m = 4, p = 7}, Coefficient[f[a, n, m], a, p]]
(*
Out[81]= 4 k[1] k[2]^3 + 12 k[1]^2 k[2] k[3] + 12 k[0] k[2]^2 k[3] +
12 k[0] k[1] k[3]^2
*)
Doing it this way is more computationally efficient than building the entire expression and extracting coefficients.
EDIT The approach here outlined will work for symbolic orders n and m, but requires explicit value for p. When using it is this circumstances, it is better to replace If with its Piecewise analog, e.g. Boole:
With[{p = 2},
BellY[Table[{FactorialPower[m, s] k[0]^(m - s),
Boole[s <= n] s! k[s]}, {s, 1, p}]]/p!]
(* 1/2 (Boole[1 <= n]^2 FactorialPower[m, 2] k[0]^(-2 + m)
k[1]^2 + 2 m Boole[2 <= n] k[0]^(-1 + m) k[2]) *)

Resources