Sindbad~EG File Manager

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

/*
M. Beeson, for Mathpert
Original date 9.27.92
last modified 8.15.98
9.3.07 modified eliminate to swap xmin and xmax if necessary, rather than presuming a < b.
9.6.07 modified eliminate in case a or b is not seminumerical
*/


#include <string.h>
#include <assert.h>
#include <math.h>
#include "globals.h"
#include "graphstr.h"
#include "mpdoc.h"
#include "prover.h"
#include "sing.h"      /* get_sing */
#include "deval.h"
#include "elim.h"
#include "ssolve.h"

#include "display1.h"
#include "bigrect.h"
#include "lterm.h"  /* interval_as_and */

int elim2(term t, term x, term a, term b, term *ans);
/*___________________________________________________________________*/
int eliminate(term t, term x, term a, term b, term *ans)
/* Assumes a and b are seminumerical; if they are not it just returns 1.
Eliminate an existential parameter from t, returning an equation or
OR of equations not involving the existential parameter, enumerating
all possible values of t that lie between a and b (inclusive).  Return
0 for success, nonzero for failure.   x is the eigenvariable.   If a 
and b are seminumerical, it uses their numerical values to do this.
*/
{ double xmin,xmax,z;
  double *outarray;
  term u,c;
  long kk;
  term *restrictions;
  int dimrestrictions;
  int err,i,mm;
  int nextassumption;
  unsigned short m,f;
  err = deval(a,&xmin);
  if(err)
     return 1;
  err = deval(b,&xmax);
  if(err)
     return 1;
  if(xmin > xmax)
     { double temp = xmax;
       xmax = xmin;
       xmin = temp;
     }
  /* We will use get_sing, originally written for finding singularities.
     It needs a list of any restrictions on the integer parameter */
  nextassumption = get_nextassumption();
  assert(nextassumption >= 0);
    /* it's a crash if you call this while nextassumption has been
       temporarily set to -1  */
  if(nextassumption == 0)
     { restrictions = NULL;
       dimrestrictions = 0;
     }
  else  /* put all inequalities in the assumptions list into 'restrictions' */
     { restrictions = callocate(2*nextassumption,sizeof(term));
          /* factor of 2 because some of the assumptions may be
             interval_as_and terms that give rise to two restrictions */
       if(restrictions==NULL)
          { nospace();
            return 1;
          }
       dimrestrictions = 0;
       for(i=0;i<nextassumption;i++)
          { u = get_assumption(i);
            f = FUNCTOR(u);
            if(interval_as_and(u))
               { restrictions[dimrestrictions] = ARG(0,u);
                 restrictions[dimrestrictions+1] = ARG(1,u);
                 dimrestrictions += 2;
               }
            else if(INEQUALITY(f))
               { restrictions[dimrestrictions] = u;
                 ++dimrestrictions;
               }
          }
     }
  err = get_sing(xmin,xmax,x,&t,1,restrictions,dimrestrictions,&outarray,&mm);
  if(restrictions)
     free2(restrictions);
  if(err)
     return 1;
  if(mm==0)  /* no solutions in the interval */
     { /* outarray hasn't been allocated, so don't free it */
       *ans = falseterm;
       return 0;
     }
  if(mm > 100)  /* 100 is arbitrary here */
     { free2(outarray);
       return 2;
     }
  m = (unsigned short)mm;
  *ans = make_term(OR,m);  /* even if m == 1 */
  for(i=0;i<m;i++)
     { z = outarray[i];
       if(i==0 && fabs((z-xmin)/(xmax-xmin)) < VERYSMALL)
          /* z is really the left endpoint except for roundoff error */
          ARGREP(*ans,i,equation(x,a));
       else if(i==m-1 && fabs((z-xmax)/(xmax-xmin)) < VERYSMALL)
          /* z is really the right endpoint except for roundoff error */
          ARGREP(*ans,i,equation(x,b));
       else if(nearint(12*z/PI_DECIMAL,&kk))
          {  /* z is kk * pi/12; let c be kk/12 in lowest terms */
            int sign = 1;
            if(kk < 0)
               { kk = -kk;
                 sign = -1;
               }
            if(kk % 12 == 0)
               c = kk==12 ? pi_term : product(make_int(kk/12),pi_term);
            else if(kk % 6 == 0)
               c = kk==6 ?  make_fraction(pi_term,two) :
                            product(make_fraction(make_int(kk/6),two),pi_term);
            else if(kk % 3 == 0)
               c = kk==3 ? make_fraction(pi_term,four) :
                           product(make_fraction(make_int(kk/3),four),pi_term);
            else if(kk % 2 == 0)
               c = kk==2 ? make_fraction(pi_term,six) :
                           product(make_fraction(make_int(kk/2),six),pi_term);
            else
               c = product(make_fraction(make_int(kk),make_int(12)),pi_term);
            if(sign == -1)
               c = tnegate(c);
            ARGREP(*ans,i,equation(x,c));
          }
       else
          ARGREP(*ans,i,equation(x,make_double(z)));
     }
  free2(outarray);
  if(m==1)
     { term temp = ARG(0,*ans);
       RELEASE(*ans);
       *ans = temp;
     }
  if(FUNCTOR(*ans)== '=' && CHECKED(t))
     SETCHECKED(*ans);
  if(FUNCTOR(*ans) == OR && CHECKED(t))
     { for(i=0;i<ARITY(*ans);i++)
          SETCHECKED(ARG(i,*ans));
     }
  return 0;
}
/*___________________________________________________*/
term lnegate(term t)
/* Return the strong logical negation of t.
   If t is an OR of equations, return an AND of NE terms, etc.
*/
{ unsigned short n;
  int i;
  term ans;
  unsigned short f = FUNCTOR(t);
  switch(f)
     { case '=':
          return ne(ARG(0,t),ARG(1,t));
       case NE:
          return equation(ARG(0,t),ARG(1,t));
       case '<':
          return le(ARG(1,t),ARG(0,t));
       case LE:
          return lessthan(ARG(1,t),ARG(0,t));
       case '>':
          return le(ARG(0,t),ARG(1,t));
       case GE:
          return lessthan(ARG(0,t),ARG(1,t));
     }
  if(f == OR || f == AND)
     { n = ARITY(t);
       if(f == OR)
          ans = make_term(AND,n);
       else
          ans = make_term(OR,n);
       for(i=0;i<n;i++)
          ARGREP(ans,i,lnegate(ARG(i,t)));
       return ans;
     }
  if(f == IMPLIES)
     return and(ARG(0,t),lnegate(ARG(1,t)));
  if(f == NOT)
     return ARG(0,t);
  ans = make_term(NOT,1);
  ARGREP(ans,0,t);
  return ans;
}

/*___________________________________________________________________________*/
int elim2(term t, term x, term a, term b, term *ans)
/* It is assumed that either a is seminumerical and b is not, and b does not contain x,
or both and b are not seminumerical and do not contain x.
   It is assumed that t is an equation x = f(n) where f is monotone increasing in n,
and does not contain x.  
   The return value is  a term dom, such that if dom is assumed, then there are no possible 
values of f(n) between a and b.  Example:  eliminate(zerovals(SIN), t, pi_term/2, x,&ans)
should return   0 < x < pi.   (And of course dom should be
the weakest possible such assumption.)   If neither a nor b is 
seminumerical then, if the possible values of t are equally space as 
they are in the example,  the answer will not actually eliminated the 
existential variable.  For example eliminate(zerovals(SIN), t, x,y, &ans)
should return  n pi <= x  && x <=y &&  y <= (n+1)pi.
   If t is too complicated, return false in ans, and 1 for the return value.
Return value of 0 means success.   
   As of Sept. 6, 2007,  t will always be zerovals(SIN) or zerovals(COS),
but that is not assumed. 
*/
{  term *atomlist;
   term n,solved,lo,hi,K,J;
   int err;
   double z;
   long k;
   int nvars = variablesin(ARG(1,t),&atomlist);
   /* atomlist should now just contain the single existential variable. */
   if(nvars > 1)
       { *ans = falseterm;
         return 1;
       }
   n = atomlist[0];
   free2(atomlist);
   /* Now we have the existential variable n */
   /* Hopefully t has the form x = f(n) for some increasing f,  e.g. x = n pi or x = n pi/2 + pi/2, etc. */
   if(FUNCTOR(t) != '=' || !equals(ARG(0,t),x) || contains(ARG(1,t),FUNCTOR(x)) || 
      contains(a,FUNCTOR(x)) || contains(b,FUNCTOR(x))
     )
       { *ans = falseterm;
         return 1;
       }
   if(!seminumerical(a))
       { /* then ans should be f(n) < a <= b < f(n+1) */
         K = ARG(1,t);
         subst(sum(n,one),n,K,&J);
         *ans = and3(lessthan(K,a), le(a,b),lessthan(b,J));
         return 0;
       }
   /* find the value k of n such that  f(n) <= a <= f(n+1) */
   err = ssolve(equation(a,ARG(1,t)),n, &solved);
   if(err) 
      { *ans = falseterm;
        return 1;
      }
   /* the desired value of n is the floor of the solution */ 
   deval(ARG(1,solved),&z);
   z = floor(z);
   nearint(z,&k);
   /* The lower and upper values of b desired are f(k) and f(k+1) */
   K = make_int(k);
   J = make_int(k+1);
   subst(K,n,ARG(1,t),&lo);
   subst(J,n,ARG(1,t),&hi);
   *ans = lpt(and(le(lo,b),le(b,hi)));  /* return the closed interval */
   return 0;
}   
   
   
           
        

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