2 Copyright
2006 by Barton Willis
4 This is free software
; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
,
6 http
://www.gnu.org
/copyleft
/gpl.html.
8 This software has NO WARRANTY
, not even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 Declaring a function to be multiadditive makes it additive
14 in all of its arguments
; declaring a function to be additive
15 makes it additive in just its first argument. Examples
:
17 (%i1
) load
("multiadditive")$
18 (%i2
) declare
(f,multiadditive
);
21 (%o3
) f
(y,b
)+f
(y,a
)+f
(x,b
)+f
(x,a
)
23 (%o4
) f
(z,b
)+f
(z,a
)+f
(y,b
)+f
(y,a
)+f
(x,b
)+f
(x,a
)
24 (%i5
) declare
(g,additive
)$
26 (%o6
) g
(y,b
+a
)+g
(x,b
+a
)
28 The order of
*opers-list matters. For example
, if f is threadable and
29 an involution
, then f
(f([1,2])) would simplify to f
([f
(1),f
(2)]) if
30 the threadable rule was used first
, or it would simplify to
[1,2] if
31 the the involution rule was used first. A user doesn
't have any control
32 over the order the rules are applied. There is a user-level list $opproperties
,
33 but re-ordering $opproperties doesn
't change the order the rules are applied.
36 ;; As of 2 June 2006, simplifya doesn't check for a subscripted function
37 ;; before sending it to oper-apply. I don't think this is what we want:
38 ;; declare(f,multiadditive), f[x+y] --> f[x] + f[y]. And f[x+y](a+b) --> error.
39 ;; For now, these functions check for subscripted arguments.
40 ;; TODO: MOVE THIS BUG FIX TO SIMPLIFYA OR OPER-APPLY !!
42 ;; When e is a mapatom, the function call (oper-apply e z) gives an
43 ;; error. I think oper-apply should be changed so that its first
44 ;; argument can be a mapatom. Till then:
45 ;; TODO: MOVE THIS BUG FIX TO SIMPLIFYA OR OPER-APPLY !!
47 (defun protected-oper-apply (e z
)
48 (if ($mapatom e
) e
(oper-apply e z
)))
50 (defun multiadditive (e)
51 (cond ((and (not ($subvarp e
)) (some #'(lambda (s) (op-equalp s
'mplus
)) (margs e
)))
52 (let ((op (mop e
)) (args (margs e
)))
53 (setq args
(mapcar #'(lambda (s) (if (op-equalp s
'mplus
) (margs s
) (list s
))) args
))
54 (setq args
(apply 'cartesian-product args
))
55 (setq args
(mapcar #'(lambda (s) (simplify `((,op
) ,@s
))) args
))
59 ;; ((op) bag) --> map(op bag).
62 (let ((arg (margs e
)) (fop) (bop)) ;; fop = function operator and bop = bag operator.
63 (cond ((and (= 1 (length arg
)) (not ($subvarp e
))
64 (or (mbagp (first arg
)) (op-equalp (first arg
) '$set
)))
65 (setq arg
(first arg
))
68 `((,bop
) ,@(mapcar #'(lambda (s) (mfuncall fop s
)) (margs arg
))))
71 ;; ((op) ((op) x)) --> ((op) x).
72 ;; Good test: declare(f,idempotent), f[5](x).
75 (if (and (not ($subvarp e
))
76 (= 1 (length (margs e
)))
77 (not ($mapatom
(first (margs e
))))
78 (eq (mop e
) (mop (first (margs e
)))))
81 ;; ((op) ((op) x)) --> x.
82 ;; Good test: declare(f,involution), f[5](x).
85 (if (and (not ($subvarp e
))
86 (= 1 (length (margs e
)))
87 (not ($mapatom
(first (margs e
))))
88 (eq (mop e
) (mop (first (margs e
))))
89 (= 1 (length (margs (first (margs e
))))))
90 (first (margs (first (margs e
)))) e
))