Re: [Q] Implementing identities as rules
- To: mathgroup at smc.vnet.net
- Subject: [mg18687] Re: [mg18608] [Q] Implementing identities as rules
- From: "Wolf, Hartmut" <hwolf at debis.com>
- Date: Thu, 15 Jul 1999 01:46:04 -0400
- Organization: debis Systemhaus
- References: <199907130501.BAA09558@smc.vnet.net.>
- Sender: owner-wri-mathgroup at wolfram.com
Dear Kevin, Kevin Jaffe schrieb: > > During symbolic manipulations it often important to be able to use > both sides of an identity or definition. For example, let f be a > function defined by > > In[1]:= f = Function[{x, y}, Exp[x^2 + y^2]]; > > Its partial derivative with respect to x is: > > In[2]:= D[f[x, y], x] > > 2 2 > x + y > Out[2]= 2 E x > > Now, I want to recast this result in the form 2 x f[x, y], i.e. I want > to revert to the "left-hand side" of the original definition of f[x, > y]. How does one do this in Mathematica? I know that if I try the > rule > > In[3]:= %2 /. Exp[a_^2 + b_^2] :> f[a, b] > > 2 2 > x + y > Out[3]= 2 E x > > I get the original expression, because when the pattern is replace, > f[a, b] is immediately evaluated to reproduce the original expression. > (I know that the replacement occurs because if instead I use a rule > whose right hand side cannot be evaluated further > > In[4]:= %2 /. Exp[a_^2 + b_^2] :> g[a, b] > > Out[4]= 2 x g[x, y] > > I get the desired result.) > > Is there a way to instruct Mathematica not to evaluate the expression > after the replacement has been made? > Well, Kevin, to do what you want, you have clearly to create *different* execution environments for (1) doing your basic operations (differentiation in your case) and for (2) converting your results back in terms of the unevaluated function. I can't see how to do that in a general case (if that is possible at all), but for your problem (and hopefully some similar ones) I found a way: The function doDefsUndo[{definitions},body] will do it when 'definitions' are one or more function definitions (separated by commas) and body is the statement (or compound statement) you want to execute. doDefsUndo extracts the functional symbols from definitions, and then executes the definitions within a Block with guarded symbols. So far nothing particular, but then the result is 'converted back' by rules which are essentially the reverted definitions. This is of course the crucial step, and will not do well in any case, but I think it will work if the rhs of your definitions are e.g.'simple' algebraic expressions. The patterns at the lhs must be "simple", that is like in f[x_,y_]. In your case it works In[4]:= doDefsUndo[{f[x_,y_]=Exp[x^2+y^2]}, D[f[x,y],x]] Out[4]= 2 x f[x,y] or else In[6]:= doDefsUndo[{f[x_,y_]=Exp[x^2+y^2]}, D[f[x,y],{x,2},y]]//Factor Out[6]= 4 (1 + 2 x^2) y f[x, y] * Of course you must have no definition for f in your dialog environment, * * else it will work forward again, and you gained nothing! * Now what is doDefsUndo? Well, it's just a hack (which I have no time to make more elegant, or even do more testing) but you may recognize the general idea of the attempt: ---------------------------------------------------------------------- In[2]:= doDefsUndo[{definitions__},body_]:= With[{heldDefs= List@@Map[Hold, Hold[definitions]/.{Literal[lhs_=rhs_]:>{lhs,rhs}, Literal[lhs_:=rhs_]:>{lhs,rhs}},{2}],heldBody=Hold[body], defCE=Hold[CompoundExpression[definitions]]}, (*Print["heldDefs:\t",heldDefs,"\nheldBody:\t",heldBody,"\ndefCE:\t", defCE];*) With[{heldlhs=First/@heldDefs,heldrhs=Part[#,2]&/@heldDefs}, (*{heldrhs,heldlhs}*) With[{lhsSymbols= Thread[Cases[heldlhs,Verbatim[Hold][foo_[___]|foo_]:>Hold[foo]], Hold],execBody= Replace[Thread[{defCE,heldBody},Hold], Hold[{s___}]->Hold[CompoundExpression[s]] ]}, (*Print["lhsSymbols:\t",lhsSymbols,"\nexecBody:\t",execBody];*) With[{ heldPatterns= Thread[Extract[heldlhs, Position[heldlhs, Verbatim[Pattern][x_,Verbatim[Blank][___]]],Hold],Hold], heldPatternVars= Thread[Cases[heldlhs, Verbatim[Pattern][x_,Verbatim[Blank][___]]:>Hold[x], Infinity],Hold]}, (*{heldPatternVars,heldPatterns}*) With[{ swRules=Thread[ Replace[Thread[{heldPatternVars,heldPatterns},Hold], Hold[{l_,r_}]:>RuleDelayed[l,r]]]}, (*swRules*) With[{backRules=Thread[ Replace[ Thread[{Thread[heldrhs/.swRules,Hold], Thread[ heldlhs/.Verbatim[Pattern][x_, Verbatim[Blank][___]]:>x,Hold]},Hold], Hold[{l_,r_}]:>RuleDelayed[l,r]] ]}, (*Print["backRules:\t",backRules];*) Block@@Join[lhsSymbols,execBody]/.backRules ]]]]]] ---------------------------------------------------------------------- As you see there are lots of 'Hold's in it and 'Thread's (to interchange the 'Hold' with 'List' and vice versa) To me it would be nice to learn of examples, working and not working; kind regards, hw
- References:
- [Q] Implementing identities as rules
- From: "Kevin Jaffe" <kj0@mailcity.com>
- [Q] Implementing identities as rules