Sindbad~EG File Manager
/* M. Beeson, for the Otter-lambda to MathXpert link */
/* ExternalSimplify takes clauses in string form and passes them to MathXpert for simplification, returning answers also in string form. The input strings are readable
by MathXpert and the output strings are readable by Otter.
*/
/* This same pattern can be followed to link any external program to Otter to
process clauses, changing them into "reduced" equivalent versions of the same clauses.
Since the results are used by Otter in the same way as demodulation, the answers should
be equivalent to the input, rather than just consequences, although if they are merely
consequences, deductions will still be sound, we just might lose some desired conclusions.
If you want to make deductions externally rather than reductions, the architecture
that calls ExternalSimplify should be modified to retain the original clauses too.
*/
/* Last modified 1.17.06
3.20.06 removed superfluous include heaps.h, function.h, printdialog.h, freeptr.h
changed pem to ParserErrorMessage
7.2.06 added init_optable call.
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h> // fprintf
#include <assert.h>
#define EXTERNALSIMP_DLL
#include "externalsimplify.h"
#include "export.h"
#include "globals.h"
#include "graphstr.h"
#include "document.h"
#include "userfunc.h"
#include "parser.h"
#include "ssolve.h"
#include "activate.h"
#include "cflags.h"
#include "mpmem.h"
#include "prover.h"
#include "mpstring.h"
#include "optable.h"
#include "probtype.h" // SIMPLIFY
#include "mathpertlink.h"
#include "englpem.h" /* ParserErrorMessage */
#include "automode.h" /* init_optable */
static PDOCDATA pProofData;
PDOCDATA GetDocData(void)
{ return pProofData;
}
/*___________________________________________________________*/
static void select_eigenvariable(term t)
/* choose the first non-bound variable in varlist that
occurs in t, and call set_eigenvariable to make it the
eigenvariable. If there's no such variable, just take
the first variable in varlist; if there are no variables
at all, do nothing.
*/
{ term *varlist = get_varlist();
varinf *varinfo = get_varinfo();
int i;
int n = get_nvariables();
for(i=0;i<n;i++)
{ if(varinfo[i].scope != BOUND && contains(t,FUNCTOR(varlist[i])))
{ set_eigenvariable(i);
return;
}
}
/* t is a constant term, so just pick SOME non-bound variable */
for(i=0;i<n;i++)
{ if(varinfo[i].scope != BOUND )
{ set_eigenvariable(i);
return;
}
}
/* the entire clause has no non-bound variables */
if(n > 0)
set_eigenvariable(0); // even if it's bound
// and if there are no variables at all don't do anything.
}
/*___________________________________________________________*/
static char *term_string(term t)
{ int m = mpsize(t);
char *ans = calloc(m+20,sizeof(char)); /* m+1 should be fine, but just in case.. */
mpstring(t,ans,m+1);
return ans;
}
/*___________________________________________________________*/
static int almost_equals(term a, term b)
/* return 1 if one has the form not(a=b)and the other has the form ne(u,v);
return 0 otherwise.
*/
{ if(FUNCTOR(a) == NOT && FUNCTOR(b) == NE)
{ SETFUNCTOR(b,'=',2);
return equals(ARG(0,a),b);
}
if(FUNCTOR(b) == NOT && FUNCTOR(a) == NE)
{ SETFUNCTOR(a,'=',2);
return equals(a,ARG(0,b));
}
return 0;
}
/*___________________________________________________________*/
static term negation(term t)
{ if(FUNCTOR(t) == NOT)
return ARG(0,t);
if(FUNCTOR(t) == NE)
return equation(ARG(0,t),ARG(1,t));
if(FUNCTOR(t) == LE)
return lessthan(ARG(1,t),ARG(0,t));
if(FUNCTOR(t) == '<')
return le(ARG(1,t),ARG(0,t));
if(FUNCTOR(t) == '=')
return ne(ARG(0,t),ARG(1,t));
return not(t);
}
/*___________________________________________________________*/
int MEXPORT_EXTERNALSIMP ExternalSimplify(int nlits, char **atoms, char *signs,
int *nNewLits, char **NewAtoms, char *NewSigns)
/* The first three parameters represent an Otter clause in string form,
namely, the number of literals, an array of strings, one for each atom,
holding a term in string form, terminated by a period, and an array
of the signs of the literals. The entries in the sign array are those
used in Otter: 0 for negation, 1 for positive occurrence.
The last three parameters similarly represent the output, the result of
simplifying the input clause. The number of literals can change; it comes
back in *nNewLits. NewAtoms is an array of strings, each entry of
which contains an atom in string form (must be parseable by Otter), ending
in a period. Newsigns is an array of the signs of those literals.
The dimension of these two output arrays is given by the initial value
of *newLits.
Return 0 if some simplification took place. If not, return 1.
Return -1 if memory for the MathXpert heap can't be found.
Space for the output strings is created using calloc. This function
leaves the MathXpert heaps in the same condition it found them.
*/
{ int i,j,err,k,flag,r;
int next_assumption, save_domain_assumptions;
term *input;
term *output;
char *rest;
term t,q;
int outputsize;
int max_outup = *nNewLits;
int heapsize = 1 << 15; /* in units of 16 bytes, yielding 512 kb total*/
pProofData = (PDOCDATA) malloc(sizeof(DOCDATA));
memset(pProofData,0,sizeof(DOCDATA));
pProofData->currenttopic = _epsilon_delta;
pProofData->docnumber = 1;
// init_optable();
err = init_doc_data(SYMBOLDOC, pProofData);
if(err == 1)
{ printf("init_doc_data failed");
free(pProofData);
return 1;
}
activate(pProofData);
set_polyvalfactorflag(0); // don't content-factor
set_polyvalfactorflag2(0);
set_problemtype(SIMPLIFY);
gensym(1);
input = (term *) calloc(nlits, sizeof(term));
outputsize = 5*nlits + 20;
if (outputsize > max_outup)
outputsize = max_outup;
output = (term *) calloc(outputsize, sizeof(term));
if(!input || !output)
{ fprintf(stderr, "Out of memory in ExternalSimplify\n");
release_doc_data(pProofData);
free(pProofData);
return 1;
}
for(i=0;i<nlits;i++)
{ // parse atoms[i]; negate the result if signs[i] == 0;
// then put this term in input[i];
err = mparse(&t, atoms[i],&rest);
if(err)
{ fprintf(stderr,"Parser error parsing %s\n", atoms[i]);
fprintf(stderr,"Unparsed part is %s\n",rest);
fprintf(stderr,ParserErrorMessage(err));
release_doc_data(pProofData);
free(pProofData);
return 1;
}
if(signs[i] == 0)
t = negation(t);
permcopy(t,&input[i]);
vaux(input[i]);
set_valuepointers(&input[i]);
}
for(i=0;i<nlits;i++)
{ term q = input[i];
if(FUNCTOR(q) == NOT)
q = ARG(0,q);
if(INEQUALITY(FUNCTOR(q))) // includes the case '='
{ check(domain(ARG(0,q)));
check(domain(ARG(1,q)));
}
else
err = check(domain(input[i]));
if(err == 1) // one literal can't be defined
{ // so nothing you could say about it could be true, e.g.
// sqrt(-1) = sqrt(-1) is false
permfree(&input[i]);
permcopy(make_term(FALSEFUNCTOR,0),&input[i]);
}
if(err != 0)
assert(0); // check can only return 2 if problemtype is SOLVE but now it's SIMPLIFY
}
save_domain_assumptions = get_nextassumption();
k=0;
flag = 0; // set when some literal actually simplifies
for(i=0;i<nlits;i++)
{ // assume the negations of all the input[j] for j > i
// and the negations of the output[j] for 0 <= j < k
// then simplify input[i] using lpt
if(k==outputsize)
{ flag = 0; // fail, but don't cause an abend.
fprintf(stdout,"\nSimplification failed: too many literals\n");
goto out;
}
for(j=i+1;j<nlits;j++)
assume(negation(input[j]));
for(j=0;j<k;j++)
{ if(NewSigns[j] == 0)
assume(output[j]);
else
assume(negation(output[j]));
}
next_assumption = get_nextassumption();
select_eigenvariable(input[i]);
t = lpt(input[i]);
if(!equals(t,input[i]) && !almost_equals(t,input[i]))
flag = 1;
if( FUNCTOR(t) == TRUEFUNCTOR)
{ // one literal is TRUE so whole clause is TRUE
NewAtoms[0] = "0=0"; // not 'true', so it will be subsumed in Otter
NewSigns[0] = 1; // 7.5.05
*nNewLits= 1;
release_doc_data(pProofData); // this also destroys the MathXpert heap
free(pProofData);
return 0;
}
if(FUNCTOR(t) == FALSEFUNCTOR)
{ // skip this clause
for(j=save_domain_assumptions;j< get_nextassumption();j++)
permfree(&get_assumptions()[j]);
set_nextassumption(save_domain_assumptions);
continue;
}
if(FUNCTOR(t) == NOT)
{ t = ARG(0,t);
NewSigns[k] = 0;
}
else if(FUNCTOR(t) == NE)
{ t = equation(ARG(0,t),ARG(1,t));
NewSigns[k] = 0;
}
else if(FUNCTOR(t) == OR)
{ for(r=0;r<ARITY(t);r++)
{ q = ARG(r,t);
if(FUNCTOR(q) == NOT)
{ q = ARG(0,q);
NewSigns[k] = 0;
}
else
NewSigns[k] = 1;
NewAtoms[k] = term_string(q);
permcopy(q,&output[k]);
++k;
}
continue;
}
else
NewSigns[k] = 1;
NewAtoms[k] = term_string(t);
permcopy(t,&output[k]);
++k;
for(j=next_assumption; j < get_nextassumption(); j++)
{ // put in the negation of any new assumptions
// but not the domain assumptions or the negations of the other literals
NewSigns[k] = 1;
NewAtoms[k] = term_string(get_assumption(j));
permcopy(get_assumption(j),&output[k]);
++k;
}
set_nextassumption(save_domain_assumptions); // back to where only domains were assumed.
reset_heap(NULL); // assumptions are in perm memory so not on heap
}
/* free the MathXpert document that was created for this call */
release_doc_data(pProofData);
// delete_document(pProofData);
out:
if(!flag)
{ free(input);
free(output);
free(pProofData);
return 1;
}
*nNewLits = k;
free(pProofData); // it was malloc'ed above
free(input);
free(output);
return 0;
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists