Subject: The global variable var, Schatchen and $specint
From: Dieter Kaiser
Date: Fri, 09 Apr 2010 21:51:04 +0200
Because we had a discussion about the many special variables in Maxima I
had a look at the code of hypgeo.lisp to find a way to eliminate or to
reduce the use of special variables.
One of the most interesting problem is the usage of the special variable
VAR. This variable is needed because the pattern matcher Schatchen
seems to work only with this special variable.
Therefore, I had a look at Schatchen to find a way to get pattern
matching without the usage of the global special variable VAR. It is
possible, but we have to change one function a bit.
At first the problem in Schatchen:
A variable pattern should have the following form
(var pred arg2 arg3 ... )
I would expect that we can build up any arbitrary variable pattern using
any desired predicate function. But there is a problem.
These are examples which work:
(m2 'x '(a equal 2) nil) -> NIL
(m2 2 '(a equal 2) nil) -> ((A . 2))
(m2 'x '(a alike1 2) nil) -> NIL
(m2 2 '(a alike1 2) nil) -> ((A . 2))
(m2 '((%sin) $x) '(a alike1 ((%sin) $x)) nil) -> ((A (%sin) $X))
The problem is, that we cannot pass a symbol as an argument of a
predicate.
(m2 'x '(a equal x) nil) -> Lisp Error
(m2 'x '(a alike1 x) nil) -> Lisp Error
The reason is in the routine findthem in schatc.lisp. At this place the
arguments of the predicate function are determined. The arguments are
evaluated, which causes the Lisp error if we try to pass an unbound
symbol. The following shows the routine with an extension to generalize
schatchen:
(defun findthem (exp args)
(cons exp
(mapcar #'(lambda (q)
(cond ((symbolp q)
(or (cdr (assoc q ans :test #'eq))
;; Get the value of the symbol.
;; E.g. for the global VAR
(and (boundp q) (eval q))
;; But do not evaluate in general.
q))
(q)))
args)))
With this extension we no longer get a Lisp error, but the expected
behaviour:
(m2 'x '(a equal x) nil) -> ((A . X))
(m2 'x '(a alike1 x) nil) -> ((A . X))
Now, the reason why we need a more general pattern matching routine. The
following is a typical pattern match used in Maxima. It uses the
predicate functions freevar and hasvar. (By the way: freevar is not
really a function, but a special symbol in the routine testa*.
Therefore, it is e.g. not possible to redefine the functionality of this
predicate).
Both predicate functions test against the global special variable VAR.
;; Recognize c*u^v + a and a=0.
(defun arbpow1 (exp)
(m2 exp
'((mplus)
((coeffpt)
(c freevar)
((mexpt)(u hasvar)(v freevar)))
((coeffpp)(a zerp)))
nil))
My aim was to allow the following definition which should be completely
independent of global variables. We no longer use freevar and hasvar,
but the predicate functions free and has and pass the variable we need
for the check.
(The function FREE is defined in simp.lisp. The function HAS must be
defined e.g. (defun has (x y) (not (free x y))
;; A pattern match which does not use the global VAR.
(defun arbpow1 (expr var1)
(m2 expr
`((mplus)
((coeffpt)
(c free ,var1)
((mexpt) (u has ,var1) (v free ,var1)))
((coeffpp) (a zerp)))
nil))
This way the magic functionality of VAR is removed. The pattern works as
expected and we can use much more general predicate functions too.
I have already started to introduce this scheme in hypgeo.lisp and it
works.
By the way:
We have a general bug in hypgeo.lisp. Almost all of the pattern for
special functions are too general, e.g. for one Bessel J function we
have:
;; Recognize bessel_j(v,w)
(defun onej (exp)
(m2 exp
'((mplus)
((coeffpt)
(u nonzerp)
((%bessel_j) (v true) (w true)))
((coeffpp) (a zerp)))
nil))
We match all Bessel J functions because of the predicate TRUE for the
arguments. But this is wrong, e.g. we get:
(%i20) specint(exp(-s*t)*bessel_j(1,x),t);
(%o20) 'specint(bessel_j(1,x)*%e^-(s*t),t)
Because the Bessel function does not depend on the integration variable
the correct result is:
(%i6) specint(exp(-s*t)*bessel_j(1,x),t);
(%o6) bessel_j(1,x)/s
This is a more correct pattern. I have already removed the dependency on
the global variable VAR:
;; Recognize bessel_j(v,w)
(defun m2-onej (expr var1)
(m2 expr
`((mplus)
((coeffpt)
(u nonzerp)
((%bessel_j) (v free ,var1) (w has ,var1)))
((coeffpp) (a zerp)))
nil))
My question: Should we extend the functionality of Schatchen as
described and try to remove as an example the dependency of the special
variable VAR from hypgeo.lisp?
Dieter Kaiser