Sindbad~EG File Manager

Current Path : /usr/home/beeson/MathXpert/prover/
Upload File :
Current File : /usr/home/beeson/MathXpert/prover/interval.c

/* M. Beeson, for use in Mathpert's prover */
/*  interval_implication is needed so addundefinedpoints will work
    right in minmax problems.  It's called by lpt to simplify
    inequalities.  */

/*
Original date 8.13.93
 modified 8.30.98
 5.5.13 made interval_implication static
 12.11.23 added include lterm.h and display1.h and bigrect.h
*/

#include <assert.h>
#include <math.h>
#include "globals.h"
#include "deval.h"
#include "polynoms.h"
#include "sturm.h"
#include "algaux.h"
#include "prover.h"
#include "pvalaux.h"  /* strongnegate */
#include "display1.h"
#include "bigrect.h"
#include "lterm.h"  /* interval_as_and */

static int interval_implication(term u, term t, term *ans);
static int interval_implication(term u, term t, term *ans);

/*________________________________________________________________________*/
static int interval_implication(term u, term t, term *ans)
/* u is an interval_as_and, t is an inequality (< or LE, not an equation).
Return *ans as a simplified form of t using u as an assumption.
Return 0 for success, 1 for failure to simplify t.
   It is not guaranteed that *ans is different from t.
*/

/* Examples:
    -1 \le  x \le  2 => x^2 < 9 ; here t is x^2 < 9 and *ans = true
    -3 < x \le  3 => x^2 < 9   isn't quite true;  we get  x!=3 returned in *ans
    -1 \le  x \le  2 => 9 < x^2   gives *ans= falseterm
    -1 \le  x \le  3 => 9 \le  x^2   gives  x=3 returned in *ans
*/


{ term a = ARG(0,ARG(0,u));
  term b = ARG(1,ARG(1,u));
  term x = ARG(1,ARG(0,u));
  term p;
  POLYnomial q;
  unsigned f = FUNCTOR(ARG(0,u));
  unsigned g = FUNCTOR(ARG(1,u));
  unsigned h = FUNCTOR(t);
  term uu = ARG(0,t);
  term vv = ARG(1,t);
  term *atomlist;
  int natoms,err;
  double saveit,aval,bval,leftval,rightval,midval;
  if(h != LE && h != '<' && h != NE)
     return 1;
  if(!ISATOM(x))
     return 1;
  if(!contains(t,FUNCTOR(x)))
     return 1;
  natoms = atomsin(t,&atomlist);
  if(natoms > 1 || !equals(atomlist[0],x))
     { free2(atomlist);
       return 1;
     }
  if(!ZERO(uu))
     polyval(sum(vv,strongnegate(uu)),&p);
  else
     p = uu;

  /* Now the task is to (prove or) reduce the proposition
     that p is positive (or non-negative or nonzero) */

  if(!seminumerical(a) || !seminumerical(b))
     return 1;
  deval(a,&aval);
  if(aval == BADVAL)
     return 1;
  deval(b,&bval);
  if(bval == BADVAL)
     return 1;
  saveit = VALUE(x);
  if(bval < aval)
     { /* false implies anything */
       *ans = trueterm;
       return 0;
     }
  SETVALUE(x,aval);
  deval(p,&leftval);
  if(leftval == BADVAL)
     { SETVALUE(x,saveit);
       return 1;
     }
  if(fabs(bval-aval) < VERYSMALL)
     { if(f == '<' && g == '<')  /* u is false then */
          { *ans = trueterm;
            return 0;
          }
       if(h == '<' && leftval > 0.0)
          { *ans = trueterm;
            return 0;
          }
       if(h == LE  && leftval > -VERYSMALL)
          { *ans = trueterm;
            return 0;
          }
       *ans = falseterm;
       return 0;
     }
  SETVALUE(x,bval);
  deval(p,&rightval);
  if(rightval == BADVAL)
     { SETVALUE(x,saveit);
       return 1;
     }
  if(leftval * rightval < 0)
    /* The sign will come out right even if there is overflow in the
       multiplication */
    /* p changes sign on the interval */
     { SETVALUE(x,saveit);
       return 1;
     }

  /* Now for the heart of the matter:  does p have a zero in (a,b),
     or doesn't it?   */
  err = makepoly(p,x,&q);
  if(err)
     return 1;  /* can't handle non-polynomials at all, unfortunately */
  err = nroots_interval(q,a,b);
  if(err)
     return 1;  /* it does have a root, or there was a deval error */
  /* Now it DOESN'T have a zero in (a,b) */
  SETVALUE(x,saveit);
  if(h == NE && f == '<' && g == '<')
     { *ans = trueterm;
        return 0;  /* we don't care about the sign of p on the interval */
     }
  if(fabs(leftval) < VERYSMALL || fabs(rightval) < VERYSMALL)
     {  /* is p positive or negative on (a,b) ? */
       if(fabs(leftval) < VERYSMALL && fabs(rightval) < VERYSMALL)
        /* zero at both ends */
          { if(h == NE)
               { *ans = (f == '<' && g == '<') ? trueterm :
                         f == '<' ? lessthan(a,x) :
                         g == '<' ? lessthan(x,b) :
                         and(lessthan(a,x),lessthan(x,b));
                 return 0;
               }
            SETVALUE(x, (aval + bval)/2.0);
            deval(p,&midval);
            SETVALUE(x,saveit);
            if(midval == BADVAL)
               return 1;
            if(h == '<' && midval > 0.0)
               { *ans =  (f == '<' && g == '<') ? trueterm:
                         f == '<' ? lessthan(a,x):
                         g == '<' ? lessthan(x,b):
                         and(lessthan(a,x),lessthan(x,b));
                 return 0;
               }
            if(h == '<' && midval < 0.0)
               { *ans = falseterm;
                 return 0;
               }
            assert(midval != 0.0);  /* there is no root in (a,b) */
            if(h == LE && midval > 0.0)
               { *ans = trueterm;
                 return 0;
               }
            if(h == LE)
               { *ans = (f == '<' && g == '<') ? trueterm:
                         f == '<' ? equation(x,b) :
                         g == '<' ? equation(x,a):
                         or(equation(x,a),equation(x,b));
                 return 0;
               }
          }
       if(fabs(leftval) < VERYSMALL)
          { /*  p is zero at a but not at b  */
            if(h == NE)
               { *ans = f == '<' ? trueterm : lessthan(a,x);
                 return 0;
               }
            if(rightval > 0.0)
               { if(f == '<' || h == LE)
                    { *ans =  trueterm;
                      return 0;
                    }
                 *ans = lessthan(a,x);
                 return 0;
               }
            if(rightval < 0.0)   /* negative */
               { if(f == LE && h == LE)
                    { *ans = equation(x,a);
                      return 0;
                    }
                 *ans = falseterm;
                 return 0;
               }
          }
       if(fabs(rightval) < VERYSMALL)
          { /*  p is zero at b but not at a  */
            if(h == NE)
               { *ans = g == '<' ? trueterm : lessthan(x,b);
                 return 0;
               }
            if(leftval > 0.0)
               { if(g == '<' || h == LE)
                    { *ans = trueterm;
                      return 0;
                    }
                 *ans = le(x,b);
                 return 0;
               }
            if(leftval < 0.0)
               { if(g == LE && h == LE)
                    { *ans = equation(x,b);
                       return 0;
                    }
                 *ans = falseterm;
                 return 0;
               }
          }
     }
  if(leftval < 0 && h != NE)  /* p is negative on (a,b) */
     *ans = falseterm;
  else  /* p is positive on (a,b), or h == NE */
     *ans = trueterm;
  return 0;
}
/*______________________________________________________________*/
int sturm_reduce(term t, term *ans)
/* t is an inequality.  Reduce t using the assumptions to a simpler
form using Sturm's theorem and related algorithms of
Sylvester and Coste-Roy, see sturm.c */
{ int i,err;
  term u;
  int nextassumption = get_nextassumption();
  assert(INEQUALITY(FUNCTOR(t)));
  for(i=0;i<nextassumption;i++)
     { u = get_assumption(i);
       if(!interval_as_and(u) || PROVISIONAL(u))
          continue;
       err = interval_implication(u,t,ans);
       if(!err && !equals(*ans,t))
          return 0;
     }
  return 1;
}

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists