6

The command

Variables[poly]

gives me a list of all variables that appear in the expression poly, which involved sums, products, and rational powers. Sadly, it doesn't work for more complicated expressions, such as trigonometric functions. I was wondering if there is another command that can handle expressions such as $\sin(x)+\cos(y)$.

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
user1337
  • 1,068
  • 6
  • 13

5 Answers5

5

Using Nasser's expression code as an example:

expr = Sin[x] + Cos[y] + z^3 + Exp[d] + h + 3 h^2 + 4 h^3 + 
   Integrate[Exp[p], p] + 
   D[Sin[m]^Exp[f], m]*Series[Sin[g], {g, 0, 3}] + 
   2 (E^a BesselK[0, 2 Sqrt[E^a]]) C[2]/D[Gamma[w], {w, 2}];

You might use:

Variables @ Level[expr, {-1}]
{a, d, f, g, h, m, p, w, x, y, z}

To extract indexed variables such as C[2] you could use:

Cases[expr, _[_Integer], {-2}]
{C[2]}
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • I almost overlooked your answer because it's so short... but it's obviously the easiest way! – Jens Aug 07 '13 at 22:28
  • @Jens I used the method here as well, but there I used -1 rather than {-1} because I wanted to allow for indexed variables like x[1]. Do you think I should try to extend my answer to handle both in Sin[z] + x[1], that is include z and x[1] in the output list? – Mr.Wizard Aug 07 '13 at 22:38
  • The OP was looking for an analogue of Variables for polynomials, and that limits what he means by variables. But indeed, that would also include things like x[1]! – Jens Aug 07 '13 at 22:49
  • +1 But what about something a term like Integrate[Sqrt[1 + Exp[p^2]], {p, 0, 1}], which doesn't evaluate but is a constant? Just live with it? – Michael E2 Aug 07 '13 at 22:52
  • @MichaelE2 I guess it all depends on what you need; this is intended as the "simple" answer to complement more involved ones such as what Daniel linked to. Most of the time I think it works OK. – Mr.Wizard Aug 07 '13 at 22:55
  • I couldn't think of one and was just curious if there was an easy solution. I love the elegance and efficacy of this one. -- Aha! Found something: Apply Pick[#, Normal@D[expr, #] =!= 0 & /@ #] & to results. – Michael E2 Aug 08 '13 at 00:04
  • @MichaelE2 I don't understand; what should I be seeing? (Sorry, I only noticed this comment now.) – Mr.Wizard Aug 12 '13 at 22:35
  • I meant if one replaces the integral in expr with a definite integral like Integrate[Sqrt[1 + Exp[p^2]], {p, 0, 1}], then Pick[#, Normal @ D[expr, #] =!= 0 & /@ #] &@ Variables @ Level[expr, {-1}] returns {a, d, f, g, h, m, w, x, y, z} -- no p, which is only a "dummy" variable of integration. (My two previous comments are meant to go together.) – Michael E2 Aug 12 '13 at 22:54
  • @MichaelE2 Got it; thanks. – Mr.Wizard Aug 12 '13 at 22:57
4
ClearAll[x, y, z, d, h, p, m, f, g, a, w];

expr = Sin[x] + Cos[y] + z^3 + Exp[d] + h + 3 h^2 + 4 h^3 + 
   Integrate[Exp[p], p] + 
   D[Sin[m]^Exp[f], m]*Series[Sin[g], {g, 0, 3}] + 
   2 (E^a BesselK[0, 2 Sqrt[E^a]]) C[2]/D[Gamma[w], {w, 2}];

Cases[Variables[Level[expr, -1]], x_ /; AtomQ[x] :> x]

(* {a, d, f, g, h, m, p, w, x, y, z} *)
Nasser
  • 143,286
  • 11
  • 154
  • 359
  • Nice - but you could use Level[expr, {-1}], right? – Jens Aug 07 '13 at 22:06
  • @Jens That's what I did in my answer. Nasser, forgive me but your current form doesn't make sense; you're effectively testing for indivisibility twice now: once with {-1} and once with AtomQ. You should either just subsume/supplant my answer or go back to the original form. (You're the one who encouraged me to post an answer; I'd have been glad to simply edit yours.) – Mr.Wizard Aug 07 '13 at 22:26
  • Yes, both -1 and {-1} will work in your code; that's my point. With {-1} the AtomQ becomes redundant; that's why it's not in my answer. – Mr.Wizard Aug 07 '13 at 22:29
4
Clear[GetVariables]
SetAttributes[GetVariables, HoldFirst];
GetVariables[expr_, f_:Identity,  excludedContexts:{__String}:{"System`"}]:=
Cases[Unevaluated[expr], 
  a_Symbol/;!Or[
       MemberQ[excludedContexts, Context[a]],
       MemberQ[Attributes[a], Locked | ReadProtected]
    ] :> f[a], 
  {0, Infinity}
]//DeleteDuplicates

It is used like

GetVariables @ {Exp[f[x]], Sin[x y^2]}
(* {x, y} *)

or, if you need to

GetVariables[{Exp[f[x]], Sin[x y^2]}, Hold]
(* {Hold[x], Hold[y]} *)

By default, it excludes the System` context, but other contexts can be specified, too.

rcollyer
  • 33,976
  • 7
  • 92
  • 191
3
sr = {Exp[v_] :> v, v1_^v2_ :> {v1, v2}};
variables[expr_] := FixedPoint[Replace[Variables[# /. sr], _[x_] :> x, {1}] &, expr]

variables[Sin[Subscript[x, 1]] + Cos[Subscript[x, 2]]]
(*  {Subscript[x, 1], Subscript[x, 2]} *)

variables[Sin[x] + Cos[y] + z^3 + Exp[d] + h + 3 h^2 + 4 h^3 + 
Integrate[Exp[p], p] + D[Sin[m]^Exp[f], m]]
(* {d, f, h, m, p, x, y, z} *)
Suba Thomas
  • 8,716
  • 1
  • 17
  • 32
  • Looking at the other answers I realize that Exp gives the slip with this approach. So I have updated it accordingly. I hope there are not that many cases! – Suba Thomas Aug 07 '13 at 20:46
  • Added the rule to handle your case. Probably the OP does not need this level of complexity. – Suba Thomas Aug 07 '13 at 21:21
1

Perhaps what you are looking for is as simple as

vars[expr_] := DeleteDuplicates@Cases[expr, _Symbol, \[Infinity]]

vars[1 + y^2 + Sin[x] + Cos[x]]

{y, x}

Probably there are expressions on which this will fail, but it might handle those you are interested in.

m_goldberg
  • 107,779
  • 16
  • 103
  • 257