Simplifying x^a*y^a to (x*y)^a



This code looks great to me. Stavros questioned if the scanmap was needed--you might try

  expcontract(z) := block([logexpand: 'super],
     if atom(z) then z else exp_log_to_power(exp(logcontract(log(z)))));

The log function automatically maps over list and matrix elements, but not not sets.
The special case for an atom prevents an error from taking the log of zero--try
expcontract(0) with out the check for an atom.


--Barton
________________________________

So is it right?

exp_log_to_power(expr) := block([logconcoeffp: lambda([s],true)], logcontract(expr))$
expcontract(expr) := block([logexpand: 'super],
     scanmap(lambda([z], if atom(z) then z else (exp_log_to_power(exp(logcontract(log(z)))))), expr)
)$

I do not know the condition of not-atom when it exclude.
It also works. At least I think:

expcontract(expr) := block([logexpand: 'super],
     scanmap(lambda([z], exp_log_to_power(exp(logcontract(log(z))))), expr)
)$

Derka

Dne 20.5.2013 17:21, Stavros Macrakis napsal(a):
Derka, nice trick, using logcontract in two different regimes.

A few additional minor comments on the code:

* There is no reason to put _s and _z in the block variables. They are local to their lambdas already.
* If you do want to define exp_log_to_power locally, you need to add local(exp_log_to_power) after the block variable declaration.
* But I agree with Barton that you might as well make it global.  If it is strictly a helper function, useless for anyone else, you can call it something like expcontract_exp_log_to_power.
* It's good practice to always quote symbolic constants: logexpand: 'super
* You probably want to restrict to something more than just not-atom in the scanmap lambda; logcontract(log(...)) won't do anything useful for function calls, subscripted variables, etc.  It won't do any damage either, but by that reasoning, you can just remove the 'if atom' clause.  On the other hand, you probably want to protect against constructing log(0) in e.g. expcontract of [0] or atan2(x,0).

           -s



On Mon, May 20, 2013 at 10:12 AM, Barton Willis <willisb at unk.edu<mailto:willisb at unk.edu>> wrote:
You might consider:

(1) placing the assignment  logexpand: super  inside a block--your code globally alters logexpand

(2) moving the definition of exp_log_to_power to outside the body of expcontract--the definition of
     exp_log_to_power is global--it gets redefined everytime expcontract is called.

And by the way: if you like the leading underscores on variable, that's OK. But for this code, there is
no need to wartify the variable names. Actually, I think that leading underscores makes code harder
to read, and it makes me more likely to make errors (one place _z another z).

--Barton

________________________________________

I have a idea (combined previous)

expcontract(_expr):=block([_z],
     exp_log_to_power(_e):= block([_s, logconcoeffp: lambda([_s],true)],
logcontract(_e)),
     logexpand: super,
     scanmap(lambda([_z],if atom(_z) then _z else (
         exp_log_to_power(exp(logcontract(log(_z))))
     )),_expr)
)$

expr: x^a*y^a$
expcontract(expr);
  ->  (x*y)^a

expr: (a^d*b^d+c^a*a^a)/(d^b*e^b+a^b*c^b)$
expcontract(expr);
  -> ((a*b)^d+(a*c)^a)/((d*e)^b+(a*c)^b)

Derka




_______________________________________________
Maxima mailing list
Maxima at math.utexas.edu<mailto:Maxima at math.utexas.edu>
http://www.math.utexas.edu/mailman/listinfo/maxima


_______________________________________________
Maxima mailing list
Maxima at math.utexas.edu<mailto:Maxima at math.utexas.edu>
http://www.math.utexas.edu/mailman/listinfo/maxima