declaration foo distributes over bar



argument against:
slows down simplifier.
R
Jf

----- Original Message -----
From: Robert Dodier <robert.dodier at gmail.com>
Date: Friday, June 8, 2007 10:21 pm
Subject: declaration foo distributes over bar

> Hello,
> 
> Here's a thought. How about making it possible to declare that
> some operator distributes over some other operator.
> The point of this would be to obviate special-case code
> that looks for lists, matrices, sums, etc.
> E.g. trigrat at present triggers an error if applied to a matrix;
> instead of patching the code, we could just make a declaration.
> 
> Here's an example session.
> 
> (%i1) load ("./distributes_over.mac");
> (%o1)                ./distributes_over.mac
> (%i2) declare (foo distributes_over bar);
> (%o2)               foo distributes_over bar
> (%i3) foo (bar (x, y, z));
> (%o3)              bar(foo(x), foo(y), foo(z))
> (%i4) declare (foo distributes_over [matrix, set, "["]);
> (%o4) [foo distributes_over matrix, foo distributes_over set,
>                                          foo distributes_over []
> (%i5) foo (matrix ([1, 2], [a, b]));
>                       [ foo(1)  foo(2) ]
> (%o5)                  [                ]
>                       [ foo(a)  foo(b) ]
> (%i6) foo ({a, b, c});
> (%o6)               {foo(a), foo(b), foo(c)}
> (%i7) foo ([a, b, c]);
> (%o7)               [foo(a), foo(b), foo(c)]
> (%i8) declare (foo distributes_over ["+", "*"]);
> (%o8)   [foo distributes_over +, foo distributes_over *]
> (%i9) foo (a + b + c);
> (%o9)               foo(c) + foo(b) + foo(a)
> (%i10) foo (a * b * c);
> (%o10)                foo(a) foo(b) foo(c)
> (%i11) foo (a*b + c*d);
> (%o11)            foo(c) foo(d) + foo(a) foo(b)
> 
> Notes.
> (1) distributes_over is implemented as a simplification.
> Each left-hand (outer) operator gets a rule.
> Right-hand (inner) operators are stored as a property.
> (2) distributes_over as implemented below doesn't know
> what to do if the left-hand (outer) operator takes multiple
> arguments. I guess the matchdeclare and tellsimp need
> to be more complicated.
> (3) There is some code in share to declare operators
> as "threadable". I think that existing code can be improved
> in 2 ways. I think "distributes_over" is a more widely understood
> name. Also I think it is better to allow specifying the set of
> operators over which to distribute.
> (4) declare(f, distributes_over(g)) would be more like the
> existing declaration syntax, but I've never shared Maxima's
> hankering for paired arguments. Just put all the arguments
> into one predicate expression.
> (5) The code as it stands doesn't have any effect on
> user-defined infix, prefix, or postfix operators.
> I don't know why that is. I'll look into it some more.
> (6) I guess there should be corresponding
> featurep(f distributes_over g) and remove(f distributes_over g)
> but I haven't gotten to that yet.
> (7) Loopy declarations such as declare(foo distributes_over bar)
> and declare(bar distributes_over foo) cause stack overflow.
> I guess I'll have to fix that.
> 
> FWIW
> Robert Dodier
> 
> PS. Here's the code, as it stands.
> --------------- distributes_over.mac
> fix ("distributes_over");
> 
> load ("distributes_over.lisp");
> 
> declare_distributes_over (f, g) :=
>    if listp (f)
>    then map (lambda ([f1], declare_distributes_over (f1, g)), f)
>    elseif listp (g)
>    then map (lambda ([g1], declare_distributes_over (f, g1)), g)
>    else
>       (get (f, "distributes_over"),
>        if %% = false
>        then
>           (put (f, [g], "distributes_over"),
>            buildq ([f], lambda ([e], not atom (e) and member (op (e),
> get (f, "distributes_over")))),
>            apply (matchdeclare, [g_expr, %%]),
>            buildq ([f, g], [f (g_expr), apply (op (g_expr), map (f,
> args (g_expr)))]),
>            apply (tellsimp, %%))
>        elseif not member (g, %%)
>        then put (f, cons (g, %%), "distributes_over"),
>        f distributes_over g);
> 
> --------------- distributes_over.lisp
> (let (($declare-original (get '$declare 'mfexpr*)))
>  (defmspec $declare (expr)
>    (let ((x (cadr expr)))
>      (if (and (not (atom x)) (eq (caar x) '$distributes_over))
>        (meval `(($declare_distributes_over) ,@(cdr x)))
>        (apply $declare-original (list expr))))))
> _______________________________________________
> Maxima mailing list
> Maxima at math.utexas.edu
> http://www.math.utexas.edu/mailman/listinfo/maxima
>