assume:problems with fractions or multiples of %pi and %e
Subject: assume:problems with fractions or multiples of %pi and %e
From: Dieter Kaiser
Date: Fri, 02 Oct 2009 23:59:12 +0200
We have a bug report ID: 2477795 for the problem that assume can not
handle fractions or multiplies of %pi or %e completely.
The problem occurs with every constant expression, e.g. see
(%i1) assume(x<sin(1));
(%o1) [sin(1) > x]
(%i2) is(x<sin(1));
(%o2) true
(%i3) is(x<2*sin(1));
(%o3) unknown
The last result should be true too.
The reason is that Maxima puts the constant expression into the
database. Later in $sign constant expressions are numerically evaluated
in float or bigfloat precision, but not the facts already put into the
database.
Therefore Maxima evaluates the numerical value of 2*sin(1), but does not
know that x is assumed to be less than the value of sin(1). The database
only compares against the expression sin(1).
The following routine does the equivalent calculation to $sign and puts
the numerically evaluated facts into the database too.
(defun learn-numer (pat flag)
(let (dum expr patnew)
(do ((x (cdr pat) (cdr x)))
((null x) (setq patnew (reverse patnew)))
(setq dum (constp (car x))
expr (car x))
(cond ((or (numberp (car x))
(ratnump (car x))))
((eq dum 'bigfloat)
(if (prog2
(setq dum ($bfloat (car x)))
($bfloatp dum))
(setq expr dum)))
((eq dum 'float)
(if (and (setq dum (numer (car x)))
(numberp dum))
(setq expr dum)))
((and (member dum '(numer symbol) :test #'eq)
(prog2
(setq dum (numer (car x)))
(or (null dum)
(and (numberp dum)
(prog2
(setq expr dum)
(< (abs dum) 1.0e-6))))))
(cond ($signbfloat
(and (setq dum ($bfloat (car x)))
($bfloatp dum)
(setq expr dum))))))
(setq patnew (cons expr patnew))
(setq patnew (cons (car pat) patnew))
(if (not (alike (cdr pat) (cdr patnew)))
(learn patnew flag))
nil))
When we call this routine in the routine learn all problems reported in
the above bug report will vanish, e.g.
(%i6) assume(a>0,a<%pi/2);
(%o6) [a > 0,%pi/2 > a]
(%i7) is(a>%pi/2);
(%o7) false
(%i8) is(a>%pi);
(%o8) false
(%i9) assume(b>0,b<2*%pi);
(%o9) [b > 0,2*%pi > b]
(%i10) is(b>3*%pi);
(%o10) false
The example given in this posting will work too:
(%i1) assume(x<sin(1));
(%o1) [sin(1) > x]
(%i2) is(x<2*sin(1));
(%o2) true
There is one point which can be improved. Because I have added the
numerically evaluated facts to the user database '$initial, the
additional facts are seen by the user.
(%i3) facts();
(%o3) [.8414709848078965 > x,sin(1) > x]
I have tried to use the '$global context. assume and forget will work
fine. But we have a problem with the command kill. The additional facts
are still present after the command kill.
I have tried to introduce a new context which handles only facts which
are added by the routine learn-numer, but I have not found a good
solution at this time.
But nevertheless I think that the introduction of the routine
learn-numer will improve assume.
By the way: We get no problems with the testsuite and the
share_testsuite, but a lot of more expression which will work can be put
into the database.
Dieter Kaiser