Re: What's this Mathematica function called?

*To*: mathgroup at christensen.cybernetics.net*Subject*: [mg952] Re: What's this Mathematica function called?*From*: villegas (Robert Villegas)*Date*: Thu, 4 May 1995 02:04:01 -0400*Organization*: Wolfram Research, Inc.

In article <3npos0$od2 at news0.cybernetics.net> martind at carleton.edu (D<martind at carleton.edu>M) writes: > First let me apologize for what I'm pretty certain is a question > that I could find if only I searched through the big black book > long enough. However, I am unable to find an answer anywhere in > the index, so I'll ask it here. > > What is Mathematica function that determines if one expression > depends on another? i.e. if this function were called Depends, it > would give output something like this: > > Depends[x + 3, x] > ==> True > > Depends[y, x] > ==> False > > y := x^2 > > Depends[y, x] > ==> True > > Depends[f[g[x]], x] > ==> True > > Depends[f[g[y]], x] > ==> True > > Clear[y]; Depends[f[g[y]], x] > ==> False If the variable x (or whatever expression) that you want to find occurs as an operand in a sum, product, or the like, or is an argument of a function, then MemberQ will detect it. At its default, MemberQ checks only the main elements (level 1), so in (x + y^2 + ArcSinh[z]) it will find x, but it will miss y and z because they are deeper than level 1. In[1]:= MemberQ[x + y^2 + ArcSinh[z], x] Out[1]= True In[2]:= MemberQ[x + y^2 + ArcSinh[z], y] Out[2]= False In[3]:= MemberQ[x + y^2 + ArcSinh[z], z] Out[3]= False However, we can tell MemberQ to sweep through every level of the expression looking for x, from the whole down to the atoms, by giving an extra argument of {0, -1} (called the _level specification_). Here are some examples of finding symbols, or more complex objects, in some expressions. In[4]:= MemberQ[x, x, {0, -1}] Out[4]= True In[5]:= MemberQ[x + 3, x, {0, -1}] Out[5]= True In[6]:= MemberQ[x + y^2 + ArcSinh[z], z, {0, -1}] Out[6]= True Let's try a case where the item we want is submerged pretty far: In[7]:= cont = Nest[1 + (1 + 1/#^2)^-1 &, x, 4] 1 Out[7]= 1 + ------------------------------------------- 1 -2 1 + (1 + -------------------------------) 1 -2 1 + (1 + -------------------) 1 -2 1 + (1 + -------) -2 1 + x In[8]:= MemberQ[cont, 1 + x^-2, {0, -1}] Out[8]= True Position tells us how many coordinates it takes to pinpoint the object, and hence how deep it is: In[9]:= Position[cont, 1 + x^-2] Out[9]= {{2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1}} In[10]:= Length @ First[%] Out[10]= 14 See pp. 197-199 of the second edition of the Mathematica book for a discussion of levels. Section 2.3 talks about MemberQ and related things. MemberQ, like its cousins Cases, Position, et al, can deal with a pattern, too. Examples of more generic searches: In[11]:= MemberQ[cont, 1 + x^_, {0, -1}] Out[11]= True In[12]:= MemberQ[cont, 1 + _^-2, {0, -1}] Out[12]= True What I gave won't detect the p in T[p][x, y], though. Here, the p is inside the head T[p] of the expression, but MemberQ ignores heads. You can tell it not to with the option Heads->True. In[13]:= MemberQ[T[p][x, y], p, {0, -1}] Out[13]= False In[14]:= MemberQ[T[p][x, y], p, {0, -1}, Heads->True] Out[14]= True A possibly undesirable side-effect is that it also finds T, which is likely thought of as the function, of which p is a parameter that could just as easily have been an argument along with x, say T[p, x, y]. If the spirit of your question was to find x when it occurs as a "variable" but not as a "function", then I think you could put a test on the position of a match. Here's one possibility (I haven't even defined the problem to my satisfaction, yet, so I don't know if it will do what you want): ElementButNotHeadQ[expr_, patt_] := Not[ Or @@ Map[MatchQ[#, {___, 0}]&, Position[expr, patt]] ] Here's how it behaves on something that has functions in the head and elements: In[20]:= expr = T[x[a, b], y[c, d]] [ u[p, q], v[r, s] ] Out[20]= T[x[a, b], y[c, d]][u[p, q], v[r, s]] (* variables = True: *) In[21]:= ElementButNotHeadQ[expr, p] Out[21]= True In[22]:= ElementButNotHeadQ[expr, c] Out[22]= True (* functions = False: *) In[23]:= ElementButNotHeadQ[expr, T] Out[23]= False In[24]:= ElementButNotHeadQ[expr, v] Out[24]= False (* Possibly silly, possibly not: *) In[26]:= ElementButNotHeadQ[expr, y[c, d]] Out[26]= True If you can give a precise definition of "depends on" for your purposes, then something in this direction ought to work. Robby Villegas P.S. If you really want to play around with it some more, here is a function I used to help myself see whether my ElementButNotHeadQ was really doing what I wanted on all the different parts of the expression, heads and all. You could use something like it when you are trying your own tests. It's scary-looking, but all it does is go through and test every subexpression, and print the outcome of the test, with indentation to make the results easier to read (if you don't want the indentation, throw out MapIndexed and use MapAll, but the output might be a bit harder to read). result[part_, position_] := ( Print[""]; Print[Indent[2 Length[position]], part, " ===> ", ElementButNotHeadQ[expr, part]]; part ) In[31]:= MapIndexed[result, expr, {0, -1}, Heads->True] T ===> False x ===> False a ===> True b ===> True x[a, b] ===> True [... lines deleted ...] Out[31]= T[x[a, b], y[c, d]][u[p, q], v[r, s]]