Subject: askinteger: Look in the database for facts
From: Dieter Kaiser
Date: Sun, 15 Nov 2009 21:39:13 +0100
I have worked on the bug report ID: 1038624 - "askinteger ignores
asksign database".
askinteger calls the functions maxima-integerp and nonintegerp to
determine, if the argument is definitely an integer or a noninteger.
Therefore, is not a weakness of askinteger to ignore facts like
assume(equal(x,0)) but of the called functions.
Both functions do not look completely for facts in the database. This
can be improved. Here are two small routines which do a bit more of the
needed work:
;; Look into the database for symbols which are declared to be equal
;; to an integer or an expression which is an integer.
(defun check-integer-facts (x)
(do ((factsl (cdr (facts1 x)) (cdr factsl)))
((null factsl) nil)
(cond ((eq (caar (car factsl)) '$equal)
(cond ((and (symbolp (cadr (car factsl)))
(eq (cadr (car factsl)) x))
;; Case equal(x,expr): Test expr to be an integer.
(return (maxima-integerp (caddr (car factsl)))))
((and (symbolp (caddr (car factsl)))
(eq (caddr (car factsl)) x))
;; Case equal(expr,x): Test expr to be integer.
(return (maxima-integerp (cadr (car factsl))))))))))
;; Look into the database for symbols which are declared to be equal
;; to a noninteger or an expression which is a noninteger.
(defun check-noninteger-facts (x)
(do ((factsl (cdr (facts1 x)) (cdr factsl)))
((null factsl) nil)
(cond ((eq (caar (car factsl)) '$equal)
(cond ((and (symbolp (cadr (car factsl)))
(eq (cadr (car factsl)) x))
;; Case equal(x,expr): Test expr to be an integer.
(return (nonintegerp (caddr (car factsl)))))
((and (symbolp (caddr (car factsl)))
(eq (caddr (car factsl)) x))
;; Case equal(expr,x): Test expr to be integer.
(return (nonintegerp (cadr (car factsl))))))))))
We can call these routines in maxima-integerp and nonintegerp, e.g.
(defun maxima-integerp (x &aux factsl)
(cond ((integerp x))
((mnump x) nil)
((and (symbolp x)
(or (kindp x '$integer)
(kindp x '$even)
(kindp x '$odd)
---> (check-integer-facts x))))
....
With these extensions, we get the following:
(%i1) assume(equal(a,0), equal(b,2), equal(c,1/3), equal(d,1.5),
equal(e,3.0b0))$
(%i2) map(askinteger,[a,b,c,d,e]);
(%o2) [yes, yes, no, no, no]
(%i3) assume(equal(x,2*b), equal(y,b/2), equal(z,e))$
(%i4) map(askinteger, [x,y,z]);
(%o4) [yes, yes, no]
It is only a small extension and it works not as general as is desired:
The following works as expected:
(%i12) askinteger(b);
(%o12) yes
(%i13) askinteger(2*b);
(%o13) yes
(%i14) askinteger(b+2);
(%o14) yes
(%i15) askinteger(2*b+2);
(%o15) yes
But not this expression:
(%i16) askinteger(b/2+2);
Is (b+4)/2 an integer?
y;
(%o16) yes
The testsuite and share_testsuite have no problems.
Further work is possible.
Dieter Kaiser