MathGroup Archive 1999

[Date Index] [Thread Index] [Author Index]

Search the Archive

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



  • Prev by Date: Re: Kronecker product of matrices
  • Next by Date: Re: Kronecker product of matrices
  • Previous by thread: [Q] Implementing identities as rules
  • Next by thread: Re: [Q] Implementing identities as rules