#ifdef DOC_BUILD_INTERNAL
#endif
#include "lmodel.h"
const int lmodel_STATUS_TRUE = -1;
const int lmodel_STATUS_FALSE = -3;
const int lmodel_STATUS_CLEAN = -4;
const int lmodel_STATUS_BAD = -8;
const int lmodel_STATUS_BLANK = -16;
int lmodel_StatusTrue(void) { return lmodel_STATUS_TRUE; }
int lmodel_StatusFalse(void) { return lmodel_STATUS_FALSE; }
int lmodel_StatusClean(void) { return lmodel_STATUS_CLEAN; }
int lmodel_StatusBad(void) { return lmodel_STATUS_BAD; }
int lmodel_StatusBlank(void) { return lmodel_STATUS_BLANK; }
int lmodel_GreedyComplete(void) { return lmodel_STATUS_BLANK+lmodel_STATUS_TRUE; }
int lmodel_GreedyReject(void) { return lmodel_STATUS_BLANK+lmodel_STATUS_FALSE; }
int lmodel_AllPositive(void) { return lmodel_STATUS_TRUE; }
int lmodel_AllNegative(void) { return lmodel_STATUS_FALSE; }
static int lmodel_CompareSymbolByArity(POINTER A, POINTER B, POINTER Symbstate)
{
  SYMBSTATE symbstate;
  SYMBOL sa, sb;
  int xa, xb;
  symbstate = (SYMBSTATE)Symbstate;
  sa = *(SYMBOL*)A;
  sb = *(SYMBOL*)B;
  xa = symbol_GetArity(symbstate, sa);
  xb = symbol_GetArity(symbstate, sb);
  return (xa == xb ? sa - sb : xa - xb);
}
LMODSTATE lmodel_Init(SCLSTATE Sclstate)
{
  LMODSTATE lmodstate;
  MEMORY mem;
  SYMBSTATE symbstate;
  ARRAY predicates, functions, constants;
  SYMBOL symb, symbMin, symbMax;
  unsigned i;
  const int verbose = LMODEL_GLOBAL_VERBOSITY;
  mem = state_GetMemory(Sclstate);
  lmodstate = (LMODSTATE)memory_Malloc(mem, sizeof(LMODSTATE_NODE));
  lmodstate->sclstate = Sclstate;
  symbstate = lmodel_GetSymbstate(lmodstate);
  predicates = state_GetPredicates(Sclstate);
  functions = state_GetFunctions(Sclstate);
  constants = state_GetConstants(Sclstate);
  lmodstate->cfidToSymb = array_Create(mem, array_GetSize(constants)
                                       + array_GetSize(functions));
  symbMin = 0;
  symbMax = -1e9;
  if (verbose > 1) printf("\nLMODEL_INIT: Predicates: ");
  for (i=0;i<array_GetSize(predicates);i++) {
    symb = (SYMBOL)(predicates)[i];
    if (symb < symbMin) symbMin = symb;
    if (symb > symbMax) symbMax = symb;
    if (verbose > 1) symbol_Print(symbstate, symb);
    if (verbose > 1) printf(" %li  ", symb);
  }
  if (verbose > 1) printf("\nLMODEL_INIT: Fol Constants: ");
  for (i=0;i<array_GetSize(constants);i++) {
    symb = (SYMBOL)(constants)[i];
    if (symb < symbMin) symbMin = symb;
    if (symb > symbMax) symbMax = symb;
    array_AddNoGrow(lmodstate->cfidToSymb, symb);
    if (verbose > 1) symbol_Print(symbstate, symb);
    if (verbose > 1) printf(" %li  ", symb);
  }
  if (verbose > 1) printf("\nLMODEL_INIT: Fol Functions: ");
  for (i=0;i<array_GetSize(functions);i++) {
    symb = (SYMBOL)(functions)[i];
    if (symb < symbMin) symbMin = symb;
    if (symb > symbMax) symbMax = symb;
    array_AddNoGrow(lmodstate->cfidToSymb, symb);
    if (verbose > 1) symbol_Print(symbstate, symb);
    if (verbose > 1) printf(" %li  ", symb);
  }
  if (verbose > 1) printf("\nLMODEL_INIT: symbMin %li symbMax %li\n", symbMin, symbMax);
  lmodstate->symbOffset = -symbMin;
  lmodstate->symbToID = array_CreateNoInit(mem, symbMax - symbMin + 2);
  array_Claim(lmodstate->symbToID);
  for (i=0;i<array_GetSize(lmodstate->symbToID);++i) {
    array_SetElement(lmodstate->symbToID, i, (intptr_t)-1e9);
  }
  srtg_AMergeSortWithState(mem,
                           lmodstate->cfidToSymb,
                           lmodstate->cfidToSymb,
                           lmodstate->cfidToSymb+array_GetSize(lmodstate->cfidToSymb)-1,
                           lmodel_CompareSymbolByArity,
                           (POINTER)symbstate);
  for (i=0;i<array_GetSize(lmodstate->cfidToSymb);i++) {
    symb = (SYMBOL)(lmodstate->cfidToSymb)[i];
    lmodel_SetSymbID(lmodstate, symb, i);
  }
  for (i=0;i<array_GetSize(predicates);i++) {
    symb = (SYMBOL)(predicates)[i];
    lmodel_SetSymbID(lmodstate, symb, i);
  }
  if (verbose > 1) {
    printf("\nLMODEL_INIT: sorted const+func: ");
    for (i=0;i<array_GetSize(lmodstate->cfidToSymb);i++) {
      symb = (SYMBOL)(lmodstate->cfidToSymb)[i];
      symbol_Print(symbstate, symb);
      printf(" %li  ", symb);
      lmodel_SetSymbID(lmodstate, symb, i);
    }
    for (i=0;i<array_GetSize(predicates);i++) {
      symb = (SYMBOL)(predicates)[i];
      lmodel_SetSymbID(lmodstate, symb, i);
    }
    printf("\nLMODEL_INIT: IDs const+func: ");
    for (i=0;i<lmodel_MaxCFID(lmodstate);++i) {
      symb = lmodel_CFIDToSymb(lmodstate, i);
      symbol_Print(symbstate, symb);
      printf(" %li  ", symb);
    }
    printf("\nLMODEL_INIT: IDs predicates: ");
    for (i=0;i<lmodel_MaxPredID(lmodstate);++i) {
      symb = lmodel_PredIDToSymb(lmodstate, i);
      symbol_Print(symbstate, symb);
      printf(" %li  ", symb);
    }
  }
  lmodstate->maxVar = 0;
  lmodstate->bindings = NULL;
  lmodel_ReserveBinding(lmodstate, symbol_GetMaxVars(symbstate));
  lmodstate->boundVars = array_Create(mem, 6);
  lmodstate->bindingDepths = array_Create(mem, 6);
  lmodstate->nextVar = 0;
  lmodstate->currentBindingDepth = 0;
  if (verbose > 1) printf("\nLMODEL_INIT: Finished.\n");
  return lmodstate;
}
unsigned lmodel_SymbID(LMODSTATE Lmodstate, SYMBOL Symb)
{
  return array_GetElement(Lmodstate->symbToID, Symb + Lmodstate->symbOffset);
}
void lmodel_SetSymbID(LMODSTATE Lmodstate, SYMBOL Symb, unsigned ID)
{
  array_SetElement(Lmodstate->symbToID, Symb + Lmodstate->symbOffset, (intptr_t)ID);
}
unsigned lmodel_MaxCFID(LMODSTATE Lmodstate)
{
  return array_GetSize(Lmodstate->cfidToSymb);
}
unsigned lmodel_MaxPredID(LMODSTATE Lmodstate)
{
  return array_GetSize(state_GetPredicates(lmodel_GetSclstate(Lmodstate)));
}
SYMBOL lmodel_PredIDToSymb(LMODSTATE Lmodstate, unsigned ID)
{
  return (SYMBOL)array_GetElement(state_GetPredicates(lmodel_GetSclstate(Lmodstate)), ID);
}
SYMBOL lmodel_CFIDToSymb(LMODSTATE Lmodstate, unsigned ID)
{
  return (SYMBOL)array_GetElement(Lmodstate->cfidToSymb, ID);
}
unsigned lmodel_SymbolArity(LMODSTATE Lmodstate, SYMBOL Symb)
{
  return symbol_GetArity(lmodel_GetSymbstate(Lmodstate), Symb);
}
void lmodel_SymbolPrint(LMODSTATE Lmodstate, SYMBOL Symb)
{
  symbol_Print(lmodel_GetSymbstate(Lmodstate), Symb);
}
void lmodel_TermPrint(LMODSTATE Lmodstate, TERM Term, BOOL ShowVariables)
{
  unsigned i;
  if (term_TopSymbol(Term) > 0) {
    if (ShowVariables) {
      lmodel_SymbolPrint(Lmodstate, term_TopSymbol(Term));
    }
    else {
      printf("_");
    }
  }
  else if (term_IsComplex(Term)) {
    lmodel_SymbolPrint(Lmodstate, term_TopSymbol(Term));
    putchar('(');
    for (i = 0; i < term_GetArity(Term); i++) {
      lmodel_TermPrint(Lmodstate, term_GetArgument(Term, i), ShowVariables);
      if (i < term_GetArity(Term)-1) putchar(',');
    }
    putchar(')');
  } else {
    if (term_IsValueConstant(lmodel_GetTermstate(Lmodstate), Term)) {
      symbol_GetPrintFunc(lmodel_GetSymbstate(Lmodstate), term_TopSymbol(Term))
        (stdout, term_GetValue(lmodel_GetTermstate(Lmodstate), Term));
    }
    else {
      lmodel_SymbolPrint(Lmodstate, term_TopSymbol(Term));
    }
  }
}
void lmodel_IndentDepth(LMODSTATE Lmodstate)
{
  unsigned i;
  for (i=0; i<Lmodstate->depth && i<20; ++i)
    printf(" ");
}
void lmodel_Free(LMODSTATE Lmodstate)
{
  MEMORY mem;
  unsigned i;
  mem = lmodel_GetMemory(Lmodstate);
  array_Delete(mem, Lmodstate->symbToID);
  array_Delete(mem, Lmodstate->cfidToSymb);
  array_Delete(mem, Lmodstate->boundVars);
  array_Delete(mem, Lmodstate->bindingDepths);
  for (i=0; i<Lmodstate->maxVar; ++i) {
    term_Free(lmodel_GetTermstate(Lmodstate), lmodel_GetBinding(Lmodstate, i)->dummyVar);
  }
  memory_Free(mem, (POINTER)Lmodstate->bindings,
              sizeof(LMODEL_BINDING_NODE)*Lmodstate->maxVar);
  memory_Free(mem, (POINTER)Lmodstate, sizeof(LMODSTATE_NODE));
}
SCLSTATE lmodel_GetSclstate(LMODSTATE Lmodstate)
{
  return Lmodstate->sclstate;
}
FOLSTATE lmodel_GetFolstate(LMODSTATE Lmodstate)
{
  return state_GetFolstate(lmodel_GetSclstate(Lmodstate));
}
TERMSTATE lmodel_GetTermstate(LMODSTATE Lmodstate)
{
  return state_GetTermstate(lmodel_GetSclstate(Lmodstate));
}
SYMBSTATE lmodel_GetSymbstate(LMODSTATE Lmodstate)
{
  return state_GetSymbstate(lmodel_GetSclstate(Lmodstate));
}
MEMORY lmodel_GetMemory(LMODSTATE Lmodstate)
{
  return state_GetMemory(lmodel_GetSclstate(Lmodstate));
}
void lmodel_ResizeBinding(LMODSTATE Lmodstate, unsigned NewMax)
{
  MEMORY mem;
  SYMBSTATE symbstate;
  unsigned i, oldSize, newSize;
  TERM term;
  mem = lmodel_GetMemory(Lmodstate);
  symbstate = lmodel_GetSymbstate(Lmodstate);
  if (NewMax <= Lmodstate->maxVar) return;
  if (NewMax > (unsigned)symbol_GetMaxVars(symbstate)) {
    symbol_AdjustStateMaxVarsLimit(symbstate, NewMax);
  }
  oldSize = sizeof(LMODEL_BINDING_NODE)*Lmodstate->maxVar;
  newSize = sizeof(LMODEL_BINDING_NODE)*NewMax;
  if (oldSize == 0) {
    Lmodstate->bindings = memory_Malloc(mem, newSize);
  }
  else {
    Lmodstate->bindings = memory_Realloc(mem, Lmodstate->bindings, oldSize, newSize);
  }
  memset(Lmodstate->bindings + Lmodstate->maxVar, 0, newSize-oldSize);
  for (i = Lmodstate->maxVar, Lmodstate->maxVar = NewMax; i<NewMax; ++i) {
    term = term_CreateArity(lmodel_GetTermstate(Lmodstate), i, 0);
    lmodel_GetBinding(Lmodstate, i)->dummyVar = term;
  }
}
void lmodel_ReserveBinding(LMODSTATE Lmodstate, unsigned AtLeast)
{
  unsigned long long pow;
  if (AtLeast <= Lmodstate->maxVar) return;
  for (pow=1; pow < AtLeast;) pow *=2;
  lmodel_ResizeBinding(Lmodstate, pow);
}
LMODEL_BINDING lmodel_GetBinding(LMODSTATE Lmodstate, SYMBOL Var)
{
#ifdef SPASS_CHECK
  if (Var < 0 || Var >= Lmodstate->maxVar) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: Not a variable or larger than max: %li", __func__, Var);
    misc_FinishErrorReport();
  }
#endif
  return Lmodstate->bindings + Var;
}
LMODEL_BINDING lmodel_CreateBinding(LMODSTATE Lmodstate, SYMBOL Var, SYMBOL Symb, unsigned Arity)
{
  LMODEL_BINDING bind;
  lmodel_ReserveBinding(Lmodstate, Lmodstate->nextVar + Arity);
  bind = lmodel_GetBinding(Lmodstate, Var);
#ifdef SPASS_CHECK
  if (bind->symb != 0) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: variable already has a binding: %li", __func__, Var);
    misc_FinishErrorReport();
  }
#endif
  bind->symb = Symb;
  bind->arity = Arity;
  bind->idx = Lmodstate->nextVar;
  Lmodstate->nextVar += Arity;
  Lmodstate->boundVars = array_Add(lmodel_GetMemory(Lmodstate),
                                       Lmodstate->boundVars, Var);
  Lmodstate->bindingDepths = array_Add(lmodel_GetMemory(Lmodstate),
                                       Lmodstate->bindingDepths, Lmodstate->currentBindingDepth);
  unsigned depth = lmodel_CreateBindingHypotheticalDepth(Lmodstate, Var, Symb, Arity);
  if (Lmodstate->currentBindingDepth < depth) {
    Lmodstate->currentBindingDepth = depth;
  }
  for (unsigned i=bind->idx; i<bind->idx+bind->arity; ++i) {
    lmodel_GetBinding(Lmodstate, i)->depth = depth;
  }
  return bind;
}
unsigned lmodel_CreateBindingHypotheticalDepth(LMODSTATE Lmodstate, SYMBOL Var,
                                               SYMBOL Symb, unsigned Arity)
{
  return lmodel_GetBinding(Lmodstate, Var)->depth + (Arity > 0 ? 1 : 0);
}
void lmodel_UndoLastBinding(LMODSTATE Lmodstate)
{
  SYMBOL var;
  LMODEL_BINDING bind;
#ifdef SPASS_CHECK
  if (array_GetSize(Lmodstate->boundVars) == 0) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: no last binding to undo!", __func__);
    misc_FinishErrorReport();
  }
#endif
  var = array_Pop(Lmodstate->boundVars);
  Lmodstate->currentBindingDepth = array_Pop(Lmodstate->bindingDepths);
  bind = lmodel_GetBinding(Lmodstate, var);
  bind->symb = 0;
  bind->arity = 0;
  Lmodstate->nextVar = bind->idx;
  bind->idx = 0;
}
void lmodel_PrintBindingEntry(LMODSTATE Lmodstate, unsigned Idx)
{
  LMODEL_BINDING bind;
  unsigned i;
  bind = lmodel_GetBinding(Lmodstate, Idx);
  printf("%u:", bind->depth);
  lmodel_SymbolPrint(Lmodstate, term_TopSymbol(bind->dummyVar));
#ifdef SPASS_CHECK
  if (bind->symb > 0) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: Don't bind variable to another variable!", __func__);
    misc_FinishErrorReport();
  }
#endif
  if (bind->symb == 0) {
    printf("=(NULL)");
  }
  else {
    printf("=");
    lmodel_SymbolPrint(Lmodstate, bind->symb);
    if (bind->arity != 0) {
      printf("(");
      for (i=0; i<bind->arity; ++i) {
        TERM arg = lmodel_GetBinding(Lmodstate, bind->idx + i)->dummyVar;
        lmodel_SymbolPrint(Lmodstate, term_TopSymbol(arg));
        printf("%s", (i == bind->arity-1 ? ")" : ","));
      }
    }
  }
}
void lmodel_PrintDefinedBindings(LMODSTATE Lmodstate)
{
  unsigned i, var;
  printf(" BINDINGS (d=%u):", Lmodstate->currentBindingDepth);
  for (i=0; i<array_GetSize(Lmodstate->boundVars); ++i) {
    var = array_GetElement(Lmodstate->boundVars, i);
    printf(" ");
    lmodel_PrintBindingEntry(Lmodstate, var);
  }
}
TERM lmodel_FormBoundTerm(LMODSTATE Lmodstate, unsigned Var)
{
  TERMSTATE termstate;
  TERM term, arg;
  LMODEL_BINDING bind;
  unsigned i;
  termstate = lmodel_GetTermstate(Lmodstate);
  bind = lmodel_GetBinding(Lmodstate, Var);
  if (bind->symb == 0) return NULL;
  term = term_CreateArity(termstate, bind->symb, bind->arity);
  for (i=0; i<term_GetArity(term); ++i) {
    arg = lmodel_FormBoundTerm(Lmodstate, bind->idx + i);
    if (arg == NULL) {
      arg = term_CreateArity(termstate, bind->idx + i, 0);
    }
    term_SetArgument(term, i, arg);
  }
  return term;
}
const char* lmodel_StatusString(int Status)
{
  if (Status >= 0)
    return "I:";
  else if (Status == lmodel_StatusTrue())
    return " +";
  else if (Status == lmodel_StatusFalse())
    return " -";
  else if (Status == lmodel_StatusClean())
    return "O:";
  else if (Status == lmodel_StatusBad())
    return "B:";
  else
    return "E:";
}
LMODLIT lmodlit_Create(MEMORY Mem, TERM Root, int Status)
{
  LMODLIT lmodlit;
  lmodlit = (LMODLIT)memory_Malloc(Mem, sizeof(LMODLIT_NODE));
  lmodlit->status = Status;
  lmodlit->front = 0;
  lmodlit->arr = array_Create(Mem, 6);
  array_AddNoGrow(lmodlit->arr, (intptr_t)Root);
  return lmodlit;
}
LMODLIT lmodlit_CreateFromFOL(FOLSTATE Folstate, TERM Lit)
{
  return lmodlit_Create(fol_GetMemory(Folstate),
                        fol_GetAtom(Folstate, Lit),
                        (fol_IsNot(Folstate, Lit)
                         ? lmodel_StatusFalse()
                         : lmodel_StatusTrue()));
}
void lmodlit_Free(MEMORY Mem, LMODLIT Lit)
{
  array_Delete(Mem, Lit->arr);
  memory_Free(Mem, (POINTER)Lit, sizeof(LMODLIT_NODE));
}
int lmodlit_GetStatus(LMODLIT Lit)
{
  return Lit->status;
}
void lmodlit_SetStatus(LMODLIT Lit, int Status)
{
  Lit->status = Status;
}
unsigned lmodlit_GetFront(LMODLIT Lit) {
  return Lit->front;
}
void lmodlit_SetFront(LMODLIT Lit, unsigned Front)
{
#ifdef SPASS_DEBUG
  if (Front >= lmodlit_GetBack(Lit)) {
    misc_StartErrorReport();
    misc_ErrorReport("\n %s: Unexpected: Front %u >= Back %u", __func__, Front, lmodlit_GetBack(Lit));
    misc_FinishErrorReport();
  }
#endif
  Lit->front = Front;
}
void lmodlit_IncrementFront(LMODLIT Lit, int Inc)
{
  lmodlit_SetFront(Lit, Inc + lmodlit_GetFront(Lit));
}
unsigned lmodlit_GetBack(LMODLIT Lit)
{
  return (unsigned)array_GetSize(Lit->arr);
}
void lmodlit_SetBack(LMODLIT Lit, unsigned Back)
{
#ifdef SPASS_DEBUG
  if (Back >= array_GetSize(Lit)) {
    misc_StartErrorReport();
    misc_ErrorReport("\n %s: don't expect to increase back with this function. ",
                     __func__);
    misc_FinishErrorReport();
  }
#endif
  array_SetSize(Lit->arr, Back);
}
TERM lmodlit_GetTerm(LMODLIT Lit, unsigned Idx)
{
  return (TERM)array_GetElement(Lit->arr, Idx);
}
void lmodlit_SetTerm(LMODLIT Lit, unsigned Idx, TERM Term)
{
  array_SetElement(Lit->arr, Idx, (intptr_t)Term);
}
SYMBOL lmodlit_GetSymbol(LMODLIT Lit, unsigned Idx)
{
  return term_TopSymbol(lmodlit_GetTerm(Lit, Idx));
}
TERM lmodlit_GetFrontTerm(LMODLIT Lit)
{
  return lmodlit_GetTerm(Lit, lmodlit_GetFront(Lit));
}
void lmodlit_SetFrontTerm(LMODLIT Lit, TERM Term)
{
  lmodlit_SetTerm(Lit, lmodlit_GetFront(Lit), Term);
}
SYMBOL lmodlit_GetFrontSymbol(LMODLIT Lit)
{
  return term_TopSymbol(lmodlit_GetFrontTerm(Lit));
}
void lmodlit_UnfoldFrontTerm(MEMORY Mem, LMODLIT Lit)
{
  TERM front;
  unsigned i;
  front = lmodlit_GetFrontTerm(Lit);
  for (i=0; i<term_GetArity(front); ++i) {
    Lit->arr = array_Add(Mem, Lit->arr,
                         (intptr_t)term_GetArgument(front, i));
  }
  lmodlit_IncrementFront(Lit, 1);
}
void lmodlit_UnfoldFrontBinding(LMODSTATE Lmodstate, LMODLIT Lit)
{
  MEMORY mem;
  LMODEL_BINDING bind;
  TERM arg;
  unsigned i;
  mem = lmodel_GetMemory(Lmodstate);
  if (lmodlit_GetFrontSymbol(Lit) < 0) {
    lmodlit_UnfoldFrontTerm(mem, Lit);
  }
  else {
    bind = lmodel_GetBinding(Lmodstate, lmodlit_GetFrontSymbol(Lit));
    for (i=0; i<bind->arity; ++i) {
      arg = lmodel_GetBinding(Lmodstate, bind->idx + i)->dummyVar;
      Lit->arr = array_Add(mem, Lit->arr, (intptr_t)arg);
    }
    lmodlit_IncrementFront(Lit, 1);
  }
}
BOOL lmodlit_CompareByFrontSymbol(POINTER A, POINTER B)
{
  LMODLIT litA, litB;
  SYMBOL symbA, symbB;
  int cmp;
  litA = *(LMODLIT*)A;
  litB = *(LMODLIT*)B;
  symbA = lmodlit_GetFrontSymbol(litA);
  symbB = lmodlit_GetFrontSymbol(litB);
  cmp = symbA - symbB;
  return (cmp > 0 ? TRUE : FALSE);
}
int lmodlit_CompareBySymbolAt(POINTER A, POINTER B, POINTER Idx)
{
  LMODLIT litA, litB;
  SYMBOL symbA, symbB;
  unsigned idx;
  idx = (unsigned)((intptr_t)Idx);
  litA = *(LMODLIT*)A;
  litB = *(LMODLIT*)B;
  symbA = lmodlit_GetSymbol(litA, idx);
  symbB = lmodlit_GetSymbol(litB, idx);
  return symbA - symbB;
}
LMODLIT lmodlit_Copy(LMODSTATE Lmodstate, LMODLIT Lit)
{
  TERMSTATE termstate;
  MEMORY mem;
  LMODLIT copy;
  TERM term;
  SYMBOL symb;
  unsigned i, arity;
  termstate = lmodel_GetTermstate(Lmodstate);
  mem = lmodel_GetMemory(Lmodstate);
  copy = (LMODLIT)memory_Malloc(mem, sizeof(LMODLIT_NODE));
  copy->status = Lit->status;
  copy->front = Lit->front;
  copy->arr = array_Create(mem, array_GetCapacity(Lit->arr));
  array_SetSize(copy->arr, array_GetSize(Lit->arr));
  for (i=0; i<array_GetSize(Lit->arr); ++i) {
    term = lmodlit_GetTerm(Lit, i);
    if (term != NULL && term_TopSymbol(term) < 0) {
      symb = term_TopSymbol(term);
      arity = term_GetArity(term);
      term = term_CreateArityNullInit(termstate, symb, arity);
      lmodlit_SetTerm(copy, i, term);
    }
  }
  return copy;
}
void lmodlit_PrintRoot(LMODSTATE Lmodstate, LMODLIT Lit, BOOL ShowVariables)
{
  if (Lit == NULL) {
    printf("(NULL)");
  }
  else {
    printf("%s", lmodel_StatusString(lmodlit_GetStatus(Lit)));
    lmodel_TermPrint(Lmodstate, lmodlit_GetTerm(Lit, 0), ShowVariables);
  }
}
void lmodlit_PrintLong(LMODSTATE Lmodstate, LMODLIT Lit)
{
  TERM t;
  intptr_t i;
  lmodel_IndentDepth(Lmodstate);
  printf("Cap %li  Front %u  Back %u  Status %s",
         array_GetCapacity(Lit->arr),
         lmodlit_GetFront(Lit),
         lmodlit_GetBack(Lit),
         lmodel_StatusString(lmodlit_GetStatus(Lit)));
  printf("  Symbols:");
  for (i=0; i<lmodlit_GetFront(Lit); ++i) {
    t = (TERM)lmodlit_GetTerm(Lit, i);
    printf(" ");
    if (t == NULL) {
      printf("_");
    }
    else {
      lmodel_SymbolPrint(Lmodstate, term_TopSymbol(t));
    }
  }
  printf(" |");
  for (i=lmodlit_GetFront(Lit); i<lmodlit_GetBack(Lit); ++i) {
    t = (TERM)lmodlit_GetTerm(Lit, i);
    printf(" ");
    if (t == NULL) {
      printf("_");
    }
    else {
      lmodel_SymbolPrint(Lmodstate, term_TopSymbol(t));
    }
  }
  puts("");
}
unsigned lmodlit_RepairTerms(LMODSTATE Lmodstate, LMODLIT Lit, unsigned VarNr)
{
  TERMSTATE termstate;
  TERM term, arg;
  unsigned i, l, r, oldFront, oldBack;
  termstate = lmodel_GetTermstate(Lmodstate);
  oldFront = lmodlit_GetFront(Lit);
  oldBack = lmodlit_GetBack(Lit);
  for (l=0, r=1; l<r; ++l) {
    lmodlit_SetFront(Lit, l);
    lmodlit_SetBack(Lit, r);
    term = lmodlit_GetTerm(Lit, l);
    if (term == NULL) {
      term = term_CreateArity(termstate, VarNr++, 0);
      lmodlit_SetTerm(Lit, l, term);
    }
    for (i=0; i<term_GetArity(term); ++i,++r) {
      lmodlit_SetBack(Lit, r+1);
      arg = lmodlit_GetTerm(Lit, r);
      if (arg == NULL) {
        arg = term_CreateArity(termstate, VarNr++, 0);
        lmodlit_SetTerm(Lit, r, arg);
      }
      else if (term_TopSymbol(arg) >= 0) {
      }
      term_SetArgument(term, i, arg);
    }
  }
  lmodlit_SetFront(Lit, oldFront);
  lmodlit_SetBack(Lit, oldBack);
  return VarNr;
}
ARRAY lmodlit_GrabLiterals(FOLSTATE Folstate, TERM Term, ARRAY Acc)
{
  MEMORY mem;
  unsigned i;
  mem = fol_GetMemory(Folstate);
  if (Acc == NULL) Acc = array_Create(mem, 6);
  if (fol_IsLiteral(Folstate, Term)) {
    Acc = array_Add(mem, Acc, (intptr_t)lmodlit_CreateFromFOL(Folstate, Term));
  }
  else {
    for (i=0; i<term_GetArity(Term); ++i) {
      Acc = lmodlit_GrabLiterals(Folstate, term_GetArgument(Term, i), Acc);
    }
  }
  return Acc;
}
const int lmodel_NODE_STATUS = -1;
const int lmodel_NODE_PRINTABLE = -2;
#ifdef LMODEL_PRINTABLE_REPRESENTATION
const unsigned lmodel_NODE_EXTRA = 2;
#else
const unsigned lmodel_NODE_EXTRA = 1;
#endif
LMODEL_I lmodel_NodeCreate(LMODSTATE Lmodstate)
{
  MEMORY mem;
  LMODEL_I node;
  unsigned bytes;
  mem = lmodel_GetMemory(Lmodstate);
  bytes = sizeof(intptr_t)*(lmodel_NODE_EXTRA+lmodel_MaxCFID(Lmodstate));
  node = (LMODEL_I)memory_Malloc(mem, bytes);
  memset(node, 0, bytes);
  node += lmodel_NODE_EXTRA;
  lmodel_NodeSetStatus(node, lmodel_StatusBlank());
  return node;
}
void lmodel_NodeFree(LMODSTATE Lmodstate, LMODEL_I Node)
{
  MEMORY mem;
  unsigned bytes;
  mem = lmodel_GetMemory(Lmodstate);
  bytes = sizeof(intptr_t)*(lmodel_NODE_EXTRA+lmodel_MaxCFID(Lmodstate));
  Node -= lmodel_NODE_EXTRA;
  memory_Free(mem, (POINTER)Node, bytes);
}
int lmodel_NodeGetStatus(LMODEL_I Node)
{
  return (int)Node[lmodel_NODE_STATUS];
}
void lmodel_NodeSetStatus(LMODEL_I Node, int Status)
{
  Node[lmodel_NODE_STATUS] = (intptr_t)Status;
}
LMODEL_I lmodel_NodeGetChild(LMODEL_I Node, unsigned ID)
{
  return (LMODEL_I)Node[ID];
}
void lmodel_NodeSetChild(LMODEL_I Node, unsigned ID, LMODEL_I Child)
{
  Node[ID] = (intptr_t)Child;
}
LMODLIT lmodel_NodeGetPrintable(LMODEL_I Node)
{
#ifdef LMODEL_PRINTABLE_REPRESENTATION
  return (LMODLIT)Node[lmodel_NODE_PRINTABLE];
#else
  return NULL;
#endif
}
void lmodel_NodeSetPrintable(LMODEL_I Node, LMODLIT Printable)
{
#ifdef LMODEL_PRINTABLE_REPRESENTATION
  Node[lmodel_NODE_PRINTABLE] = (intptr_t)Printable;
#else
  return;
#endif
}
void lmodel_NodePrint(LMODSTATE Lmodstate, LMODEL_I Node, BOOL ShowVariables)
{
  TERM repr;
  repr = lmodlit_GetTerm(lmodel_NodeGetPrintable(Node), 0);
  lmodel_TermPrint(Lmodstate, repr, ShowVariables);
}
static void lmodel_NodeSetStatusAccordingToCleanBehaviour(LMODEL Model, LMODEL_I Node,
                                                          int LiteralStatus)
{
  if (Model->cleanBehaviour == lmodel_AllPositive()) {
    lmodel_NodeSetStatus(Node, lmodel_StatusTrue());
  }
  else if (Model->cleanBehaviour == lmodel_AllNegative()) {
    lmodel_NodeSetStatus(Node, lmodel_StatusFalse());
  }
  else if (Model->cleanBehaviour == lmodel_GreedyComplete()) {
    lmodel_NodeSetStatus(Node, LiteralStatus);
  }
  else {
    lmodel_NodeSetStatus(Node, (LiteralStatus==lmodel_StatusTrue()
                                ? lmodel_StatusFalse() : lmodel_StatusTrue()));
  }
}
LMODEL_I lmodel_NodeCreateAccordingToCleanBehaviour(LMODSTATE Lmodstate, LMODEL Model,
                                                    int LiteralStatus)
{
  LMODEL_I node;
  node = lmodel_NodeCreate(Lmodstate);
  lmodel_NodeSetStatusAccordingToCleanBehaviour(Model, node, LiteralStatus);
  return node;
}
static void lmodel_DeleteRec(LMODSTATE Lmodstate, LMODEL_I Node)
{
  LMODLIT repr;
  unsigned i;
  if (Node == NULL) return;
  if (lmodel_NodeGetStatus(Node) >= 0) {
    for (i=0; i<lmodel_MaxCFID(Lmodstate); ++i) {
      lmodel_DeleteRec(Lmodstate, lmodel_NodeGetChild(Node, i));
    }
  }
  repr = lmodel_NodeGetPrintable(Node);
  if (repr != NULL) {
    term_Delete(lmodel_GetTermstate(Lmodstate), lmodlit_GetTerm(repr, 0));
    lmodlit_Free(lmodel_GetMemory(Lmodstate), repr);
  }
  lmodel_NodeFree(Lmodstate, Node);
}
void lmodel_Delete(LMODSTATE Lmodstate, LMODEL Model)
{
  unsigned i;
  MEMORY mem;
  mem = lmodel_GetMemory(Lmodstate);
  for (i=0; i<array_GetSize(Model->literals); ++i) {
    lmodlit_Free(mem, (LMODLIT)array_GetElement(Model->literals, i));
  }
  array_Delete(mem, Model->literals);
  for (i=0; i<lmodel_MaxPredID(Lmodstate); ++i) {
    Lmodstate->depth = 0;
    lmodel_DeleteRec(Lmodstate, Model->predRoots[i]);
  }
  memory_Free(mem, (POINTER)Model->predRoots,
              sizeof(LMODEL_I)*lmodel_MaxPredID(Lmodstate));
  memory_Free(mem, (POINTER)Model, sizeof(LMODEL_NODE));
}
static BOOL lmodel_FrontIsUnifiable(LMODSTATE Lmodstate, unsigned NCohort, LMODLIT *Cohort)
{
  TERM a, b;
  if (NCohort <= 1) return TRUE;
  a = lmodlit_GetFrontTerm(Cohort[0]);
  b = lmodlit_GetFrontTerm(Cohort[1]);
  if (term_Equal(lmodel_GetTermstate(Lmodstate), a, b)) {
    return lmodel_FrontIsUnifiable(Lmodstate, NCohort-1, Cohort+1);
  }
  else return FALSE;
}
static LMODEL_I lmodel_BuildRec(LMODSTATE Lmodstate, unsigned NCohort, LMODLIT *Cohort)
{
  MEMORY mem;
  unsigned i, l, r, nPositiveLiterals, depth;
  LMODEL_I node;
  SYMBOL symb;
  int verbose = LMODEL_GLOBAL_VERBOSITY;
  mem = lmodel_GetMemory(Lmodstate);
  node = lmodel_NodeCreate(Lmodstate);
  depth = Lmodstate->depth++;
#ifdef SPASS_CHECK
  if (NCohort == 0) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: Don't expect an empty cohort.", __func__);
    misc_FinishErrorReport();
  }
#endif
  if (verbose) {
    lmodel_IndentDepth(Lmodstate);
    printf("Building node for this cohort:\n");
    for (i=0; i<NCohort; ++i) {
      lmodlit_PrintLong(Lmodstate, Cohort[i]);
    }
  }
  nPositiveLiterals = 0;
  for (i=0; i<NCohort; ++i) {
    if (lmodlit_GetStatus(Cohort[i]) == lmodel_StatusTrue())
      ++nPositiveLiterals;
  }
  if (verbose) {
    lmodel_IndentDepth(Lmodstate);
    printf("NCohort %u PosLits %u\n", NCohort, nPositiveLiterals);
  }
  if (nPositiveLiterals == 0 || nPositiveLiterals == NCohort) {
    if (verbose) {
      lmodel_IndentDepth(Lmodstate);
      printf("Rule Solve applies\n");
    }
    lmodel_NodeSetStatus(node, (nPositiveLiterals == 0
                                ? lmodel_StatusFalse() : lmodel_StatusTrue()));
  }
  else {
    lmodel_NodeSetStatus(node, 0);
    for (;;) {
#ifdef SPASS_CHECK
      if (lmodlit_GetFront(Cohort[0]) == lmodlit_GetBack(Cohort[0])) {
        misc_StartErrorReport();
        misc_ErrorReport("\n In %s: Input clauses are inconsistent!!!", __func__);
        misc_FinishErrorReport();
      }
#endif
      if (lmodel_FrontIsUnifiable(Lmodstate, NCohort, Cohort)) {
        if (verbose) {
          lmodel_IndentDepth(Lmodstate);
          printf("Cohort unifiable at front variable position\n");
        }
        lmodel_NodeSetStatus(node, lmodel_NodeGetStatus(node)+1);
        for (i=0; i<NCohort; ++i) {
          lmodlit_IncrementFront(Cohort[i], 1);
        }
      }
      else {
        if (verbose) {
          lmodel_IndentDepth(Lmodstate);
          printf("Rule Refine applies at the front now.\n");
        }
        break;
      }
    }
    for (i=0; verbose && i<NCohort; ++i) {
      lmodel_IndentDepth(Lmodstate);
      printf("%u BEFORE SORTING ", i);
      lmodlit_PrintLong(Lmodstate, Cohort[i]);
    }
    srtg_AMergeSortCompare(mem,
                           (intptr_t*)Cohort,
                           (intptr_t*)Cohort,
                           (intptr_t*)(Cohort + NCohort - 1),
                           lmodlit_CompareByFrontSymbol);
    for (i=0; verbose && i<NCohort; ++i) {
      lmodel_IndentDepth(Lmodstate);
      printf("%u AFTER  SORTING ", i);
      lmodlit_PrintLong(Lmodstate, Cohort[i]);
    }
    for (l=0; l<NCohort; l=r) {
      symb = lmodlit_GetFrontSymbol(Cohort[l]);
      for (r=l; (r < NCohort
                 && (symb == lmodlit_GetFrontSymbol(Cohort[r])));
           ++r) {
        lmodlit_UnfoldFrontTerm(mem, Cohort[r]);
      }
      if (verbose) {
        printf("Recursing for function/constant ");
        lmodel_SymbolPrint(Lmodstate, symb);
        printf(" with a cohort of size %u, in [%u, %u)\n", r - l, l, r);
      }
      lmodel_NodeSetChild(node, lmodel_SymbID(Lmodstate, symb),
                          lmodel_BuildRec(Lmodstate, r-l, Cohort+l));
    }
  }
  Lmodstate->depth = depth;
  return node;
}
LMODEL lmodel_BuildFromLmodlits(LMODSTATE Lmodstate, ARRAY Literals, int CleanBehaviour)
{
  TERMSTATE termstate;
  MEMORY mem;
  LMODEL model;
  TERM term;
  unsigned i, l, r;
  LMODLIT lit;
  SYMBOL symb;
  termstate = lmodel_GetTermstate(Lmodstate);
  mem = lmodel_GetMemory(Lmodstate);
  const int verbose = LMODEL_GLOBAL_VERBOSITY;
  if (verbose) printf("Building model from %li literals:\n", array_GetSize(Literals));
  srtg_AMergeSortCompare(mem,
                         Literals,
                         Literals,
                         Literals + array_GetSize(Literals) - 1,
                         lmodlit_CompareByFrontSymbol);
  for (i=0; verbose && i<array_GetSize(Literals); ++i) {
    lit = (LMODLIT)array_GetElement(Literals, i);
    term = lmodlit_GetFrontTerm(lit);
    printf("%u %s ", i, (term_IsGround(termstate, term) ? "GROUND" : "NONGRD"));
    lmodlit_PrintRoot(Lmodstate, lit, TRUE);
    puts("");
  }
  model = (LMODEL)memory_Malloc(mem, sizeof(LMODEL_NODE));
  model->literals = Literals;
  model->cleanBehaviour = CleanBehaviour;
  model->predRoots = (LMODEL_I*)memory_Malloc(mem,
                                                   sizeof(LMODEL_I)*lmodel_MaxPredID(Lmodstate));
  for (i=0; i<lmodel_MaxPredID(Lmodstate); ++i) model->predRoots[i] = NULL;
  for (l=0; l<array_GetSize(Literals); l=r) {
    symb = lmodlit_GetFrontSymbol((LMODLIT)array_GetElement(Literals, l));
    for (r=l; (r<array_GetSize(Literals))
           && (symb == lmodlit_GetFrontSymbol((LMODLIT)array_GetElement(Literals, r)));
         ++r) {
      lmodlit_UnfoldFrontTerm(mem, (LMODLIT)array_GetElement(Literals, r));
    };
    if (verbose) {
      printf("Building the model for predicate ");
      lmodel_SymbolPrint(Lmodstate, symb);
      printf(" with a cohort of size %u\n", r - l);
    }
    Lmodstate->depth = 0;
    model->predRoots[lmodel_SymbID(Lmodstate, symb)] =
      lmodel_BuildRec(Lmodstate, r-l, (LMODLIT*)Literals + l);
  }
  for (i=0; i<lmodel_MaxPredID(Lmodstate); ++i) {
    if (model->predRoots[i] == NULL) {
    }
  }
  lmodel_ResetPruningDepth(Lmodstate);
  lmodel_RepresentModel(Lmodstate, model);
  return model;
}
LMODEL lmodel_BuildFromTrail(LMODSTATE Lmodstate, TRAIL Trail, int CleanBehaviour)
{
  unsigned i;
  int polarity;
  TERM atom;
  LMODLIT lit;
  ARRAY literals;
  literals = array_Create(lmodel_GetMemory(Lmodstate), trail_GetSize(Trail));
  array_Claim(literals);
  for (i=0; i<trail_GetSize(Trail);++i) {
    polarity = (trail_IsPositiveFromTrailPos(Trail, i)
                ? lmodel_StatusTrue() : lmodel_StatusFalse());
    atom = trail_GetAtomFromTrailPos(Trail, i);
    lit = lmodlit_Create(lmodel_GetMemory(Lmodstate), atom, polarity);
    array_SetElement(literals, i, (intptr_t)lit);
  }
  return lmodel_BuildFromLmodlits(Lmodstate, literals, CleanBehaviour);
}
LMODEL lmodel_BuildFromTrailAndProplits(LMODSTATE Lmodstate, TRAIL Trail, ARRAY Prlits, int CleanBehaviour)
{
  unsigned i;
  int polarity;
  TERM atom;
  PRLITS_ANNO_LIT prlit;
  LMODLIT lit;
  ARRAY literals;
  literals = array_Create(lmodel_GetMemory(Lmodstate), trail_GetSize(Trail)+array_GetSize(Prlits));
  for (i=0; i<trail_GetSize(Trail);++i) {
    polarity = (trail_IsPositiveFromTrailPos(Trail, i)
                ? lmodel_StatusTrue() : lmodel_StatusFalse());
    atom = trail_GetAtomFromTrailPos(Trail, i);
    lit = lmodlit_Create(lmodel_GetMemory(Lmodstate), atom, polarity);
    array_Add(lmodel_GetMemory(Lmodstate), literals, (intptr_t)lit);
  }
  for (i=0; i<array_GetSize(Prlits);++i) {
    prlit = (PRLITS_ANNO_LIT)Prlits[i];
    polarity = (prlits_GetAnnoLitValue(prlit) ? lmodel_StatusTrue() : lmodel_StatusFalse());
    atom = prlits_GetAnnoLitAtom(prlit);
    if (term_IsGround(lmodel_GetTermstate(Lmodstate),atom)) {
      lit = lmodlit_Create(lmodel_GetMemory(Lmodstate), atom, polarity);
      array_Add(lmodel_GetMemory(Lmodstate), literals, (intptr_t)lit);
    }
  }
  return lmodel_BuildFromLmodlits(Lmodstate, literals, CleanBehaviour);
}
static void lmodel_RepresentChildOfNode(LMODSTATE Lmodstate, LMODEL_I Node, unsigned Idx);
static void lmodel_RepresentNodesRec(LMODSTATE Lmodstate, LMODEL_I Node, LMODLIT Lit)
{
#ifndef LMODEL_PRINTABLE_REPRESENTATION
  return;
#endif
  unsigned i, depth;
  if (Node == NULL || Lit == NULL) return;
  depth = Lmodstate->depth++;
#ifdef SPASS_CHECK
  if (lmodel_NodeGetPrintable(Node) != NULL
      && lmodel_NodeGetPrintable(Node) != Lit) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: Weird: Node already has a printable Lit.", __func__);
    misc_FinishErrorReport();
  }
#endif
  lmodel_NodeSetPrintable(Node, Lit);
  lmodlit_SetStatus(Lit, lmodel_NodeGetStatus(Node));
  if (lmodel_NodeGetStatus(Node) >= 0) {
    for (i=0; i<lmodel_MaxCFID(Lmodstate); ++i) {
      lmodel_RepresentChildOfNode(Lmodstate, Node, i);
    }
  }
  lmodlit_RepairTerms(Lmodstate, Lit, 1);
  Lmodstate->depth = depth;
}
static void lmodel_RepresentChildOfNode(LMODSTATE Lmodstate, LMODEL_I Node, unsigned Idx)
{
#ifndef LMODEL_PRINTABLE_REPRESENTATION
  return;
#endif
  TERMSTATE termstate;
  MEMORY mem;
  LMODEL_I child;
  TERM term;
  unsigned depth, arity;
  LMODLIT lit, childLit;
  SYMBOL symb;
  termstate = lmodel_GetTermstate(Lmodstate);
  mem = lmodel_GetMemory(Lmodstate);
  if (Node == NULL)
    return;
  lit = lmodel_NodeGetPrintable(Node);
  child = lmodel_NodeGetChild(Node, Idx);
  if (lit == NULL || child == NULL || lmodel_NodeGetPrintable(child) != NULL) return;
  depth = Lmodstate->depth++;
#ifdef SPASS_CHECK
  if (lmodel_NodeGetStatus(Node) < 0) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: Expect internal parent node.", __func__);
    misc_FinishErrorReport();
  }
#endif
  symb = lmodel_CFIDToSymb(Lmodstate, Idx);
  arity = lmodel_SymbolArity(Lmodstate, symb);
  term = term_CreateArityNullInit(termstate, symb, arity);
  childLit = lmodlit_Copy(Lmodstate, lit);
  lmodlit_IncrementFront(childLit, lmodel_NodeGetStatus(Node));
  lmodlit_SetFrontTerm(childLit, term);
  lmodlit_UnfoldFrontTerm(mem, childLit);
  lmodel_RepresentNodesRec(Lmodstate, child, childLit);
  Lmodstate->depth = depth;
}
static void lmodel_RepresentNodeFromRoot(LMODSTATE Lmodstate, LMODEL_I Node, SYMBOL RootSymbol)
{
#ifndef LMODEL_PRINTABLE_REPRESENTATION
  return;
#endif
  TERMSTATE termstate;
  MEMORY mem;
  TERM term;
  unsigned arity;
  LMODLIT lit;
  termstate = lmodel_GetTermstate(Lmodstate);
  mem = lmodel_GetMemory(Lmodstate);
  if (Node == NULL) return;
  arity = lmodel_SymbolArity(Lmodstate, RootSymbol);
  term = term_CreateArityNullInit(termstate, RootSymbol, arity);
  lit = lmodlit_Create(mem, term, lmodel_StatusBlank());
  lmodlit_UnfoldFrontTerm(mem, lit);
  Lmodstate->depth = 0;
  lmodel_RepresentNodesRec(Lmodstate, Node, lit);
}
void lmodel_RepresentModel(LMODSTATE Lmodstate, LMODEL Model)
{
#ifndef LMODEL_PRINTABLE_REPRESENTATION
  return;
#endif
  LMODEL_I node;
  SYMBOL symb;
  unsigned i;
  for (i=0; i<lmodel_MaxPredID(Lmodstate); ++i) {
    node = Model->predRoots[i];
    if (node == NULL) continue;
    symb = lmodel_PredIDToSymb(Lmodstate, i);
    Lmodstate->depth = 0;
    lmodel_RepresentNodeFromRoot(Lmodstate, node, symb);
  }
}
static void lmodel_PrintNodesRec(LMODSTATE Lmodstate, LMODEL_I Node,
                                 BOOL ShowVariables, BOOL Verbose)
{
  unsigned i, depth;
  LMODLIT repr;
  if (Node == NULL) return;
  depth = Lmodstate->depth++;
  repr = lmodel_NodeGetPrintable(Node);
  if (lmodel_NodeGetStatus(Node) >= 0) {
    if (Verbose) {
      if (repr == NULL) {
        puts("(NULL)");
      }
      else {
        lmodlit_PrintLong(Lmodstate, repr);
      }
    }
    for (i=0; i<lmodel_MaxCFID(Lmodstate); ++i) {
      lmodel_PrintNodesRec(Lmodstate, lmodel_NodeGetChild(Node, i), ShowVariables, Verbose);
    }
  }
  else {
    if (repr == NULL) {
      puts("(NULL)");
    }
    else if (Verbose) {
      lmodlit_PrintLong(Lmodstate, repr);
    }
    else {
      printf("   \n");
      lmodlit_PrintRoot(Lmodstate, repr, ShowVariables);
    }
  }
  Lmodstate->depth = depth;
}
void lmodel_PrintModel(LMODSTATE Lmodstate, LMODEL Model)
{
  SYMBSTATE symbstate;
  unsigned i;
  SYMBOL symb;
  LMODEL_I node;
  LMODLIT lit;
  symbstate = lmodel_GetSymbstate(Lmodstate);
  const int verbose = LMODEL_GLOBAL_VERBOSITY;
  const BOOL showVariables = TRUE;
  if (FALSE && verbose>2) {
    printf("\n\nPrinting model for these input literals:\n");
    for (i=0; i<array_GetSize(Model->literals); ++i) {
      lit = (LMODLIT)array_GetElement(Model->literals, i);
      lmodlit_PrintLong(Lmodstate, lit);
    }
    printf("\nHere are all nodes of the models as lmodlit:\n");
    for (i=0; i<lmodel_MaxPredID(Lmodstate); ++i) {
      node = Model->predRoots[i];
      symb = lmodel_PredIDToSymb(Lmodstate, i);
      if (node == NULL) {
        printf("%u None for predicate ", i);
        symbol_Print(symbstate, symb);
        puts("");
      }
      else {
        printf("%u These for predicate ", i);
        symbol_Print(symbstate, symb);
        puts("");
        Lmodstate->depth = 0;
        lmodel_PrintNodesRec(Lmodstate, node, showVariables, TRUE);
      }
    }
  }
  if (FALSE && "print input literals") {
    printf("\nInput literals:");
    for (i=0; i<array_GetSize(Model->literals); ++i) {
      printf(" ");
      lit = (LMODLIT)array_GetElement(Model->literals, i);
      lmodlit_PrintRoot(Lmodstate, lit, TRUE);
    }
    printf("\n");
  }
  printf("Model (represented as linear literals): ");
  for (i=0; i<lmodel_MaxPredID(Lmodstate); ++i) {
    node = Model->predRoots[i];
    if (node != NULL) {
      Lmodstate->depth = 0;
      lmodel_PrintNodesRec(Lmodstate, node, showVariables, FALSE);
    }
  }
  printf("\n");
}
static ARRAY lmodel_RepresentAsArrayOfLiteralsRec(LMODSTATE Lmodstate, LMODEL_I Node, ARRAY Acc)
{
  unsigned i, depth;
  LMODLIT repr;
  TERM term;
  if (Node == NULL) return Acc;
  depth = Lmodstate->depth++;
  if (lmodel_NodeGetStatus(Node) >= 0) {
    for (i=0; i<lmodel_MaxCFID(Lmodstate); ++i) {
      Acc = lmodel_RepresentAsArrayOfLiteralsRec(Lmodstate, lmodel_NodeGetChild(Node, i), Acc);
    }
  }
  else {
    if (lmodel_NodeGetStatus(Node) == lmodel_StatusTrue()
        || lmodel_NodeGetStatus(Node) == lmodel_StatusFalse()) {
      repr = lmodel_NodeGetPrintable(Node);
      term = term_Copy(lmodel_GetTermstate(Lmodstate), lmodlit_GetTerm(repr, 0));
      if (lmodel_NodeGetStatus(Node) == lmodel_StatusFalse()) {
        term = fol_Negate(lmodel_GetFolstate(Lmodstate), term);
      }
      Acc = array_Add(lmodel_GetMemory(Lmodstate), Acc, (intptr_t)term);
    }
  }
  Lmodstate->depth = depth;
  return Acc;
}
ARRAY lmodel_RepresentAsArrayOfLiterals(LMODSTATE Lmodstate, LMODEL Model)
{
  unsigned i;
  ARRAY acc;
  LMODEL_I node;
  lmodel_RepresentModel(Lmodstate, Model);
  acc = array_Create(lmodel_GetMemory(Lmodstate), 6);
  for (i=0; i<lmodel_MaxPredID(Lmodstate); ++i) {
    node = Model->predRoots[i];
    if (node != NULL) {
      Lmodstate->depth = 0;
      acc = lmodel_RepresentAsArrayOfLiteralsRec(Lmodstate, node, acc);
    }
  }
  return acc;
}
void lmodel_BTMsg(LMODSTATE Lmodstate, unsigned long long backtrackNr, const char* Msg)
{
  lmodel_IndentDepth(Lmodstate); printf("%3llu: %s", backtrackNr, Msg);
}
static BOOL lmodel_CheckClauseRec(LMODSTATE Lmodstate, LMODEL Model,
                                  ARRAY Clause, unsigned CurrentIdx);
static BOOL lmodel_CheckLitRec(LMODSTATE Lmodstate, LMODEL Model,
                               ARRAY Clause, unsigned NextIdx,
                               LMODEL_I Node, LMODLIT Lit);
static BOOL lmodel_CheckLitRec(LMODSTATE Lmodstate, LMODEL Model,
                               ARRAY Clause, unsigned NextIdx,
                               LMODEL_I Node, LMODLIT Lit)
{
  SYMBSTATE symbstate;
  LMODEL_I child;
  unsigned i, arity, depth, front, back;
  long long unsigned backtrackNr;
  SYMBOL symb, frontSymb;
  LMODEL_BINDING bind;
  BOOL result;
  int verbose = LMODEL_GLOBAL_VERBOSITY;
  symbstate = lmodel_GetSymbstate(Lmodstate);
  depth = Lmodstate->depth++;
  backtrackNr = ++Lmodstate->backtrackNr;
  if (verbose > 1) {
    lmodel_BTMsg(Lmodstate, backtrackNr, "Begin of Node ");
    lmodlit_PrintRoot(Lmodstate, lmodel_NodeGetPrintable(Node), FALSE);
    printf("\n");
    lmodel_BTMsg(Lmodstate, backtrackNr, "Matching with ");
    lmodlit_PrintRoot(Lmodstate, Lit, TRUE);
    printf("   ");
    lmodel_PrintDefinedBindings(Lmodstate);
    printf("\n");
  }
  if (verbose > 2) {
    lmodel_BTMsg(Lmodstate, backtrackNr, "Node ");
    printf("(Status %i %s)  Lit Front %u Back %u\n",
           lmodel_NodeGetStatus(Node),
           lmodel_StatusString(lmodel_NodeGetStatus(Node)),
           lmodlit_GetFront(Lit),
           lmodlit_GetBack(Lit));
  }
  if (lmodel_NodeGetStatus(Node) >= 0) {
    lmodlit_IncrementFront(Lit, lmodel_NodeGetStatus(Node));
    frontSymb = lmodlit_GetFrontSymbol(Lit);
    if (verbose > 2) {
      lmodel_BTMsg(Lmodstate, backtrackNr, "children:");
      for (i=0; i<lmodel_MaxCFID(Lmodstate); ++i) {
        child = lmodel_NodeGetChild(Node, i);
        if (child == NULL) {
          printf(" %u#0 ", i);
        }
        else {
          symb = lmodel_CFIDToSymb(Lmodstate, i);
          arity = lmodel_SymbolArity(Lmodstate, symb);
          printf(" %u#", i);
          lmodel_SymbolPrint(Lmodstate, symb);
          printf(" ");
        }
      }
      printf("\n");
    }
    if (frontSymb >= 0) {
      bind = lmodel_GetBinding(Lmodstate, frontSymb);
#ifdef SPASS_CHECK
      if (bind->symb > 0) {
        misc_StartErrorReport();
        misc_ErrorReport("\n In %s: Don't bind variable to another variable!", __func__);
        misc_FinishErrorReport();
      }
#endif
      if (bind->symb != 0) {
        frontSymb = bind->symb;
      }
    }
    else {
      bind = NULL;
    }
    if (frontSymb >= 0) {
      if (verbose > 1) {
        lmodel_BTMsg(Lmodstate, backtrackNr, "Literal has the unbound variable ");
        printf("x%li at the current position. Check all refinements.\n", frontSymb);
      }
      result = TRUE;
      for (i=0; i<lmodel_MaxCFID(Lmodstate); ++i) {
        child = lmodel_NodeGetChild(Node, i);
        if (child == NULL) {
          if (verbose > 1) {
            lmodel_BTMsg(Lmodstate, backtrackNr, "undefined child i ");
            printf("%u, creating it.\n", i);
          }
          child = lmodel_NodeCreateAccordingToCleanBehaviour(Lmodstate, Model, lmodlit_GetStatus(Lit));
          lmodel_NodeSetChild(Node, i, child);
          lmodel_RepresentChildOfNode(Lmodstate, Node, i);
        }
        symb = lmodel_CFIDToSymb(Lmodstate, i);
        arity = lmodel_SymbolArity(Lmodstate, symb);
        lmodel_CreateBinding(Lmodstate, frontSymb, symb, arity);
        if (verbose > 1) {
          lmodel_BTMsg(Lmodstate, backtrackNr, "created binding ");
          lmodel_PrintBindingEntry(Lmodstate, frontSymb);
          printf(" and now recurse.\n");
        }
        front = lmodlit_GetFront(Lit);
        back = lmodlit_GetBack(Lit);
        lmodlit_UnfoldFrontBinding(Lmodstate, Lit);
        result = lmodel_CheckLitRec(Lmodstate, Model, Clause, NextIdx, child, Lit);
        lmodlit_SetFront(Lit, front);
        lmodlit_SetBack(Lit, back);
        if (verbose > 1) {
          lmodel_BTMsg(Lmodstate, backtrackNr, "Got result ");
        }
        if (result) {
          if (verbose > 1) {
            puts("TRUE. Literal (and clause) is true for this binding. Check the next.");
          }
          lmodel_UndoLastBinding(Lmodstate);
        }
        else {
          if (verbose > 1) {
            puts("FALSE. We're done and can unroll the entire stack.");
          }
          break;
        }
      }
    }
    else {
      i = lmodel_SymbID(Lmodstate, frontSymb);
      child = lmodel_NodeGetChild(Node, i);
      if (verbose > 1) {
        lmodel_BTMsg(Lmodstate, backtrackNr, "Literal has symbol ");
        symbol_Print(symbstate, frontSymb);
        printf(" at the current position (%s). Now unfold and recurse.\n",
               (bind == NULL ? "it came like that" : "via binding"));
      }
      if (child == NULL) {
        if (verbose > 1) {
          lmodel_BTMsg(Lmodstate, backtrackNr, "Before that, the corresponding child");
          puts(" needs to be defined in the model.");
        }
        child = lmodel_NodeCreateAccordingToCleanBehaviour(Lmodstate, Model, lmodlit_GetStatus(Lit));
        lmodel_NodeSetChild(Node, i, child);
        lmodel_RepresentNodesRec(Lmodstate, Node, lmodel_NodeGetPrintable(Node));
      }
      front = lmodlit_GetFront(Lit);
      back = lmodlit_GetBack(Lit);
      lmodlit_UnfoldFrontBinding(Lmodstate, Lit);
      result = lmodel_CheckLitRec(Lmodstate, Model, Clause, NextIdx, child, Lit);
      lmodlit_SetFront(Lit, front);
      lmodlit_SetBack(Lit, back);
      if (verbose > 1) {
        lmodel_BTMsg(Lmodstate, backtrackNr, "Got result ");
        printf("%s.\n", result?"TRUE":"FALSE");
      }
    }
  }
  else {
    if (lmodel_NodeGetStatus(Node) == lmodel_StatusTrue()
        || lmodel_NodeGetStatus(Node) == lmodel_StatusFalse()) {
      result = (lmodel_NodeGetStatus(Node) == lmodlit_GetStatus(Lit));
      if (verbose > 1) {
        lmodel_BTMsg(Lmodstate, backtrackNr, "Literal evaluation in model: ");
        if (result) {
          printf("TRUE. We're done in this branch.");
        }
        else {
          printf("FALSE. Maybe more luck in the next literal (NextIdx %u)", NextIdx);
        }
        puts("");
      }
      if (!result) {
        result = lmodel_CheckClauseRec(Lmodstate, Model, Clause, NextIdx);
      }
    }
    else if (lmodel_NodeGetStatus(Node) == lmodel_StatusClean()) {
      if (verbose > 1) {
        lmodel_BTMsg(Lmodstate, backtrackNr, "Model undetermined here. Define & try again");
      }
      lmodel_NodeSetStatusAccordingToCleanBehaviour(Model, Node, lmodlit_GetStatus(Lit));
      lmodel_RepresentNodesRec(Lmodstate, Node, lmodel_NodeGetPrintable(Node));
      result = lmodel_CheckLitRec(Lmodstate, Model, Clause, NextIdx, Node, Lit);
    }
    else {
      result = FALSE;
#ifdef SPASS_CHECK
      misc_StartErrorReport();
      misc_ErrorReport("\n In %s: This should be unreachable.", __func__);
      misc_FinishErrorReport();
#endif
    }
  }
  if (verbose > 1) {
    lmodel_BTMsg(Lmodstate, backtrackNr, "Node ");
    lmodlit_PrintRoot(Lmodstate, lmodel_NodeGetPrintable(Node), FALSE);
    printf(" finished. Result: %s    under ", result?"TRUE":"FALSE");
    lmodel_PrintDefinedBindings(Lmodstate);
    printf("\n");
  }
  Lmodstate->depth = depth;
  return result;
}
BOOL lmodel_CheckClauseRec(LMODSTATE Lmodstate, LMODEL Model, ARRAY Clause, unsigned CurrentIdx)
{
  SYMBSTATE symbstate;
  MEMORY mem;
  unsigned oldDepth;
  unsigned long long backtrackNr;
  LMODEL_I node;
  LMODLIT lit;
  BOOL result;
  SYMBOL rootSymb;
  int verbose = LMODEL_GLOBAL_VERBOSITY;
  symbstate = lmodel_GetSymbstate(Lmodstate);
  mem = lmodel_GetMemory(Lmodstate);
  backtrackNr = ++Lmodstate->backtrackNr;
  oldDepth = Lmodstate->depth;
  Lmodstate->depth = 0;
  if (verbose > 1) {
    lmodel_BTMsg(Lmodstate, backtrackNr, "Checking clause literals ");
    printf("[%u, %li)", CurrentIdx, array_GetSize(Clause));
    printf(" under ");
    lmodel_PrintDefinedBindings(Lmodstate);
    puts("");
  }
  if (CurrentIdx >= array_GetSize(Clause)) {
    if (verbose > 1) {
      lmodel_BTMsg(Lmodstate, backtrackNr,
                   "Nothing left. Clause is false (under current binding).\n");
    }
    result = FALSE;
  }
  else {
    lit = (LMODLIT)array_GetElement(Clause, CurrentIdx);
    if (verbose > 1) {
      lmodel_BTMsg(Lmodstate, backtrackNr,
                   "Continuing with literal");
      lmodlit_PrintRoot(Lmodstate, lit, TRUE);
      if (verbose > 2) {
        printf("  ");
        lmodlit_PrintLong(Lmodstate, lit);
      }
      else puts("");
    }
#ifdef SPASS_CHECK
    if (lmodlit_GetStatus(lit) != lmodel_StatusTrue()
        && lmodlit_GetStatus(lit) != lmodel_StatusFalse()) {
      misc_StartErrorReport();
      misc_ErrorReport("\n In %s: weird status of literal.", __func__);
      misc_FinishErrorReport();
    }
#endif
#ifdef SPASS_CHECK
    if (lmodlit_GetFront(lit) != 0 || lmodlit_GetBack(lit) != 1) {
      misc_StartErrorReport();
      misc_ErrorReport("\n In %s: front & back aren't set correctly...", __func__);
      misc_FinishErrorReport();
    }
#endif
    rootSymb = lmodlit_GetFrontSymbol(lit);
    node = Model->predRoots[lmodel_SymbID(Lmodstate, rootSymb)];
    if (node == NULL) {
      if (verbose > 1) {
        lmodel_BTMsg(Lmodstate, backtrackNr, "");
        printf(" Model not built yet for predicate ");
        symbol_Print(symbstate, rootSymb);
        printf(". Creating a root node for it (CleanBehaviour %i)\n", Model->cleanBehaviour);
      }
      node = lmodel_NodeCreateAccordingToCleanBehaviour(Lmodstate, Model, lmodlit_GetStatus(lit));
      lmodel_RepresentNodeFromRoot(Lmodstate, node, rootSymb);
      Model->predRoots[lmodel_SymbID(Lmodstate, rootSymb)] = node;
    }
    if (verbose > 1) {
      lmodel_BTMsg(Lmodstate, backtrackNr, "Calling CheckLitRec\n");
    }
    lmodlit_UnfoldFrontTerm(mem, lit);
    result = lmodel_CheckLitRec(Lmodstate, Model, Clause, CurrentIdx+1, node, lit);
    lmodlit_SetFront(lit, 0);
    lmodlit_SetBack(lit, 1);
    if (verbose > 1) {
      lmodel_BTMsg(Lmodstate, backtrackNr, "Got result for current literal:\n");
      lmodel_BTMsg(Lmodstate, backtrackNr, "");
      lmodlit_PrintRoot(Lmodstate, lit, TRUE);
      printf(" is %s under ", result?"TRUE":"FALSE");
      lmodel_PrintDefinedBindings(Lmodstate);
      printf("\n");
    }
    if (result) {
      if (verbose > 1) {
        lmodel_BTMsg(Lmodstate, backtrackNr, "Literal counts as true.");
        puts(" We're done in this backtracking branch");
      }
    } else {
      if (verbose > 1) {
        lmodel_BTMsg(Lmodstate, backtrackNr, "Literal counts as false.");
        puts(" Continue on checking the next one.\n");
      }
      result = lmodel_CheckClauseRec(Lmodstate, Model, Clause, CurrentIdx+1);
    }
  }
  Lmodstate->depth = oldDepth;
  return result;
}
SUBST lmodel_CheckLmodlitClause(LMODSTATE Lmodstate, LMODEL Model, ARRAY Clause, unsigned MaxVar)
{
  MEMORY mem;
  unsigned i;
  LMODLIT lit;
  BOOL result;
  SUBST subst;
  int verbose = LMODEL_GLOBAL_VERBOSITY;
  mem = lmodel_GetMemory(Lmodstate);
  Lmodstate->depth = 0;
  Lmodstate->backtrackNr = 0;
  while (array_GetSize(Lmodstate->boundVars)) {
    lmodel_UndoLastBinding(Lmodstate);
  }
  Lmodstate->nextVar = MaxVar;
  lmodel_ReserveBinding(Lmodstate, MaxVar+1);
  if (verbose > 1) {
    printf("\nChecking clause with %li literals and MaxVar %u:\n", array_GetSize(Clause), MaxVar);
    for (i=0; i<array_GetSize(Clause); ++i) {
      lit = (LMODLIT)array_GetElement(Clause, i);
      printf("  Nr. %u: ", i);
      lmodlit_PrintRoot(Lmodstate, lit, TRUE);
      if (verbose > 2) {
        printf("  ");
        lmodlit_PrintLong(Lmodstate, lit);
      }
      else puts("");
    }
#ifdef SPASS_CHECK
    if (lmodlit_GetStatus(lit) != lmodel_StatusTrue()
        && lmodlit_GetStatus(lit) != lmodel_StatusFalse()) {
      misc_StartErrorReport();
      misc_ErrorReport("\n In %s: weird status of literal.", __func__);
      misc_FinishErrorReport();
    }
#endif
    printf("Starting Backtracking with first clause.\n");
  }
  result = lmodel_CheckClauseRec(Lmodstate, Model, Clause, 0);
  if (verbose > 1) {
    printf("Complete result: %s\n", (result?"TRUE":"FALSE"));
  }
  if (result) {
    subst = NULL;
  }
  else {
    subst = subst_Create(mem, MaxVar);
    for (i=0; i<MaxVar; ++i) {
      subst_SetValue(subst, i, lmodel_FormBoundTerm(Lmodstate, i));
    }
  }
  return subst;
}
SUBST lmodel_CheckSPASSClause(LMODSTATE Lmodstate, LMODEL Model, CLAUSE Clause)
{
  TERMSTATE termstate;
  MEMORY mem;
  unsigned i;
  TERM atom;
  int polarity;
  LMODLIT lit;
  ARRAY arr;
  SUBST subst;
  const int verbose = LMODEL_GLOBAL_VERBOSITY;
  termstate = lmodel_GetTermstate(Lmodstate);
  mem = lmodel_GetMemory(Lmodstate);
  arr = array_CreateNoInit(mem, clause_GetFolLiterals(Clause));
  array_Claim(arr);
  for (i=0; i<clause_GetFolLiterals(Clause);++i) {
    atom = clause_GetAtom(Clause, i);
    polarity = (i<clause_GetPremiseLiterals(Clause) ? lmodel_StatusFalse() : lmodel_StatusTrue());
    lit = lmodlit_Create(mem, atom, polarity);
    array_SetElement(arr, i, (intptr_t)lit);
  }
  if (verbose > 1) {
    printf("\nChecking spassclause:  ");
    clause_Print(termstate, Clause);
  }
  subst = lmodel_CheckLmodlitClause(Lmodstate, Model, arr, clause_GetVariables(Clause));
  for (i=0; i<array_GetSize(arr); ++i) {
    lmodlit_Free(mem, (LMODLIT)array_GetElement(arr, i));
  }
  array_Delete(mem, arr);
  return subst;
}
static void lmodel_OnCounterexample(LMODSTATE Lmodstate, LMODEL Model, ARRAY Clause);
#define SPASSFW_PRUNE_BEFORE_BINDING 1
#define SPASSFW_PRUNE_BEFORE_LITERAL 1
#define SPASSFW_PRUNE_IN_LITERAL 1
static void lmodel_CheckClauseFully(LMODSTATE Lmodstate, LMODEL Model,
                                    ARRAY Clause, unsigned CurrentIdx);
static void lmodel_CheckLitFully(LMODSTATE Lmodstate, LMODEL Model,
                                 ARRAY Clause, unsigned NextIdx,
                                 LMODEL_I Node, LMODLIT Lit);
static void lmodel_CheckLitFully(LMODSTATE Lmodstate, LMODEL Model,
                                 ARRAY Clause, unsigned NextIdx,
                                 LMODEL_I Node, LMODLIT Lit)
{
  SYMBSTATE symbstate;
  LMODEL_I child;
  unsigned i, arity, depth, front, back;
  long long unsigned backtrackNr;
  SYMBOL symb, frontSymb;
  LMODEL_BINDING bind;
  BOOL result;
  int verbose = LMODEL_GLOBAL_VERBOSITY;
  symbstate = lmodel_GetSymbstate(Lmodstate);
#if SPASSFW_PRUNE_IN_LITERAL
  if (Lmodstate->currentBindingDepth >= lmodel_GetPruningDepth(Lmodstate)) {
    if (verbose > 1) {
      printf("Pruning: Binding depth %u >= %u",
             Lmodstate->currentBindingDepth, lmodel_GetPruningDepth(Lmodstate));
    }
    return;
  }
#else
#endif
  depth = Lmodstate->depth++;
  backtrackNr = ++Lmodstate->backtrackNr;
  if (verbose > 1) {
    lmodel_BTMsg(Lmodstate, backtrackNr, "Begin of Node ");
    lmodlit_PrintRoot(Lmodstate, lmodel_NodeGetPrintable(Node), FALSE);
    printf("\n");
    lmodel_BTMsg(Lmodstate, backtrackNr, "Matching with ");
    lmodlit_PrintRoot(Lmodstate, Lit, TRUE);
    printf("   ");
    lmodel_PrintDefinedBindings(Lmodstate);
    printf("\n");
  }
  if (verbose > 2) {
    lmodel_BTMsg(Lmodstate, backtrackNr, "Node ");
    printf("(Status %i %s)  Lit Front %u Back %u\n",
           lmodel_NodeGetStatus(Node),
           lmodel_StatusString(lmodel_NodeGetStatus(Node)),
           lmodlit_GetFront(Lit),
           lmodlit_GetBack(Lit));
  }
  if (lmodel_NodeGetStatus(Node) >= 0) {
    lmodlit_IncrementFront(Lit, lmodel_NodeGetStatus(Node));
    frontSymb = lmodlit_GetFrontSymbol(Lit);
    if (verbose > 2) {
      lmodel_BTMsg(Lmodstate, backtrackNr, "children:");
      for (i=0; i<lmodel_MaxCFID(Lmodstate); ++i) {
        child = lmodel_NodeGetChild(Node, i);
        if (child == NULL) {
          printf(" %u#0 ", i);
        }
        else {
          symb = lmodel_CFIDToSymb(Lmodstate, i);
          arity = lmodel_SymbolArity(Lmodstate, symb);
          printf(" %u#", i);
          lmodel_SymbolPrint(Lmodstate, symb);
          printf(" ");
        }
      }
      printf("\n");
    }
    if (frontSymb >= 0) {
      bind = lmodel_GetBinding(Lmodstate, frontSymb);
#ifdef SPASS_CHECK
      if (bind->symb > 0) {
        misc_StartErrorReport();
        misc_ErrorReport("\n In %s: Don't bind variable to another variable!", __func__);
        misc_FinishErrorReport();
      }
#endif
      if (bind->symb < 0) {
        frontSymb = bind->symb;
      }
    }
    else {
      bind = NULL;
    }
    if (bind != NULL && bind->depth >= lmodel_GetPruningDepth(Lmodstate)) {
      if (verbose > 1) {
        lmodel_BTMsg(Lmodstate, backtrackNr, "Literal has the variable ");
        printf("x%li at the current position, whose depth %u in the "\
               "binding reaches the pruning depth %u. Do nothing else.\n",
               frontSymb, bind->depth, lmodel_GetPruningDepth(Lmodstate));
      }
    }
    else if (frontSymb >= 0) {
      if (verbose > 1) {
        lmodel_BTMsg(Lmodstate, backtrackNr, "Literal has the unbound variable ");
        printf("x%li at the current position. Check all refinements.\n", frontSymb);
      }
      for (i=0; i<lmodel_MaxCFID(Lmodstate); ++i) {
        child = lmodel_NodeGetChild(Node, i);
        if (child == NULL) {
          if (verbose > 1) {
            lmodel_BTMsg(Lmodstate, backtrackNr, "undefined child i ");
            printf("%u, creating it.\n", i);
          }
          child = lmodel_NodeCreateAccordingToCleanBehaviour(Lmodstate, Model, lmodlit_GetStatus(Lit));
          lmodel_NodeSetChild(Node, i, child);
          lmodel_RepresentChildOfNode(Lmodstate, Node, i);
        }
        symb = lmodel_CFIDToSymb(Lmodstate, i);
        arity = lmodel_SymbolArity(Lmodstate, symb);
        int PRUNE_EMACSDOESNOTINDENTCORRECTLY = 0;
#if SPASSFW_PRUNE_BEFORE_BINDING
        if (lmodel_CreateBindingHypotheticalDepth(Lmodstate, frontSymb, symb, arity)
            >= lmodel_GetPruningDepth(Lmodstate))
          PRUNE_EMACSDOESNOTINDENTCORRECTLY = 1;
#else
        PRUNE_EMACSDOESNOTINDENTCORRECTLY = 0;
#endif
        if (!PRUNE_EMACSDOESNOTINDENTCORRECTLY) {
          bind = lmodel_CreateBinding(Lmodstate, frontSymb, symb, arity);
          if (verbose > 1) {
            lmodel_BTMsg(Lmodstate, backtrackNr, "created binding ");
            lmodel_PrintBindingEntry(Lmodstate, frontSymb);
            printf(" and now recurse.\n");
          }
          front = lmodlit_GetFront(Lit);
          back = lmodlit_GetBack(Lit);
          lmodlit_UnfoldFrontBinding(Lmodstate, Lit);
          lmodel_CheckLitFully(Lmodstate, Model, Clause, NextIdx, child, Lit);
          lmodlit_SetFront(Lit, front);
          lmodlit_SetBack(Lit, back);
          if (verbose > 1) {
            lmodel_BTMsg(Lmodstate, backtrackNr, "Finished this refined binding.\n");
          }
          lmodel_UndoLastBinding(Lmodstate);
        }
      }
    }
    else {
      i = lmodel_SymbID(Lmodstate, frontSymb);
      child = lmodel_NodeGetChild(Node, i);
      if (verbose > 1) {
        lmodel_BTMsg(Lmodstate, backtrackNr, "Literal has symbol ");
        symbol_Print(symbstate, frontSymb);
        printf(" at the current position (%s). Now unfold and recurse.\n",
               (bind == NULL ? "it came like that" : "via binding"));
      }
      if (child == NULL) {
        if (verbose > 1) {
          lmodel_BTMsg(Lmodstate, backtrackNr, "Before that, the corresponding child");
          puts(" needs to be defined in the model.");
        }
        child = lmodel_NodeCreateAccordingToCleanBehaviour(Lmodstate, Model, lmodlit_GetStatus(Lit));
        lmodel_NodeSetChild(Node, i, child);
        lmodel_RepresentNodesRec(Lmodstate, Node, lmodel_NodeGetPrintable(Node));
      }
      front = lmodlit_GetFront(Lit);
      back = lmodlit_GetBack(Lit);
      lmodlit_UnfoldFrontBinding(Lmodstate, Lit);
      lmodel_CheckLitFully(Lmodstate, Model, Clause, NextIdx, child, Lit);
      lmodlit_SetFront(Lit, front);
      lmodlit_SetBack(Lit, back);
      if (verbose > 1) {
        lmodel_BTMsg(Lmodstate, backtrackNr, "Finished this unfolded branch.\n");
      }
    }
  }
  else {
    if (lmodel_NodeGetStatus(Node) == lmodel_StatusTrue()
        || lmodel_NodeGetStatus(Node) == lmodel_StatusFalse()) {
      result = (lmodel_NodeGetStatus(Node) == lmodlit_GetStatus(Lit));
      if (verbose > 1) {
        lmodel_BTMsg(Lmodstate, backtrackNr, "Literal evaluation in model: ");
        if (result) {
          printf("TRUE. We're done in this branch.");
        }
        else {
          printf("FALSE. Maybe more luck in the next literal (NextIdx %u)", NextIdx);
        }
        puts("");
      }
      if (!result) {
        lmodel_CheckClauseFully(Lmodstate, Model, Clause, NextIdx);
      }
    }
    else if (lmodel_NodeGetStatus(Node) == lmodel_StatusClean()) {
      if (verbose > 1) {
        lmodel_BTMsg(Lmodstate, backtrackNr, "Model undetermined here. Define & try again");
      }
      lmodel_NodeSetStatusAccordingToCleanBehaviour(Model, Node, lmodlit_GetStatus(Lit));
      lmodel_RepresentNodesRec(Lmodstate, Node, lmodel_NodeGetPrintable(Node));
      lmodel_CheckLitFully(Lmodstate, Model, Clause, NextIdx, Node, Lit);
    }
    else {
#ifdef SPASS_CHECK
      misc_StartErrorReport();
      misc_ErrorReport("\n In %s: This should be unreachable.", __func__);
      misc_FinishErrorReport();
#endif
    }
  }
  if (verbose > 1) {
    lmodel_BTMsg(Lmodstate, backtrackNr, "Node ");
    lmodlit_PrintRoot(Lmodstate, lmodel_NodeGetPrintable(Node), FALSE);
    printf(" finished. current binding: ");
    lmodel_PrintDefinedBindings(Lmodstate);
    printf("\n");
  }
  Lmodstate->depth = depth;
}
void lmodel_CheckClauseFully(LMODSTATE Lmodstate, LMODEL Model, ARRAY Clause, unsigned CurrentIdx)
{
  SYMBSTATE symbstate;
  MEMORY mem;
  unsigned oldDepth;
  unsigned long long backtrackNr;
  LMODEL_I node;
  LMODLIT lit;
  SYMBOL rootSymb;
  int verbose = LMODEL_GLOBAL_VERBOSITY;
  symbstate = lmodel_GetSymbstate(Lmodstate);
  mem = lmodel_GetMemory(Lmodstate);
  backtrackNr = ++Lmodstate->backtrackNr;
  oldDepth = Lmodstate->depth;
  Lmodstate->depth = 0;
  if (verbose > 1) {
    lmodel_BTMsg(Lmodstate, backtrackNr, "Checking clause literals ");
    printf("[%u, %li)", CurrentIdx, array_GetSize(Clause));
    printf(" under ");
    puts("");
  }
  if (CurrentIdx >= array_GetSize(Clause)) {
    if (verbose > 1) {
      lmodel_BTMsg(Lmodstate, backtrackNr,
                   "Nothing left. Clause is false under current ");
      lmodel_PrintDefinedBindings(Lmodstate);
      printf("\n");
    }
    lmodel_OnCounterexample(Lmodstate, Model, Clause);
  }
  else {
    int PRUNE_EMACSDOESNOTINDENTCORRECTLY = 0;
#ifdef SPASSFW_PRUNE_BEFORE_LITERAL
    if (Lmodstate->currentBindingDepth >= lmodel_GetPruningDepth(Lmodstate))
      PRUNE_EMACSDOESNOTINDENTCORRECTLY = 1;
#else
    PRUNE_EMACSDOESNOTINDENTCORRECTLY = 0;
#endif
    if (!PRUNE_EMACSDOESNOTINDENTCORRECTLY) {
      lit = (LMODLIT)array_GetElement(Clause, CurrentIdx);
      if (verbose > 1) {
        lmodel_BTMsg(Lmodstate, backtrackNr,
                     "Continuing with literal");
        lmodlit_PrintRoot(Lmodstate, lit, TRUE);
        if (verbose > 2) {
          printf("  ");
          lmodlit_PrintLong(Lmodstate, lit);
        }
        else puts("");
      }
#ifdef SPASS_CHECK
      if (lmodlit_GetStatus(lit) != lmodel_StatusTrue()
          && lmodlit_GetStatus(lit) != lmodel_StatusFalse()) {
        misc_StartErrorReport();
        misc_ErrorReport("\n In %s: weird status of literal.", __func__);
        misc_FinishErrorReport();
      }
#endif
#ifdef SPASS_CHECK
      if (lmodlit_GetFront(lit) != 0 || lmodlit_GetBack(lit) != 1) {
        misc_StartErrorReport();
        misc_ErrorReport("\n In %s: front & back aren't set correctly...", __func__);
        misc_FinishErrorReport();
      }
#endif
      rootSymb = lmodlit_GetFrontSymbol(lit);
      node = Model->predRoots[lmodel_SymbID(Lmodstate, rootSymb)];
      if (node == NULL) {
        if (verbose > 1) {
          lmodel_BTMsg(Lmodstate, backtrackNr, "");
          printf(" Model not built yet for predicate ");
          symbol_Print(symbstate, rootSymb);
          printf(". Creating a root node for it (CleanBehaviour %i)\n", Model->cleanBehaviour);
        }
        node = lmodel_NodeCreateAccordingToCleanBehaviour(Lmodstate, Model, lmodlit_GetStatus(lit));
        lmodel_RepresentNodeFromRoot(Lmodstate, node, rootSymb);
        Model->predRoots[lmodel_SymbID(Lmodstate, rootSymb)] = node;
      }
      if (verbose > 1) {
        lmodel_BTMsg(Lmodstate, backtrackNr, "Calling CheckLitFully\n");
      }
      lmodlit_UnfoldFrontTerm(mem, lit);
      lmodel_CheckLitFully(Lmodstate, Model, Clause, CurrentIdx+1, node, lit);
      lmodlit_SetFront(lit, 0);
      lmodlit_SetBack(lit, 1);
      if (verbose > 1) {
        lmodel_BTMsg(Lmodstate, backtrackNr, "Finished this literal:\n");
        lmodel_BTMsg(Lmodstate, backtrackNr, "");
        lmodlit_PrintRoot(Lmodstate, lit, TRUE);
        printf(" with binding ");
        lmodel_PrintDefinedBindings(Lmodstate);
        printf("\n");
      }
    }
  }
  Lmodstate->depth = oldDepth;
}
static void lmodel_CheckLmodlitClauseFully(LMODSTATE Lmodstate, LMODEL Model,
                                           ARRAY Clause, unsigned MaxVar)
{
  unsigned i;
  LMODLIT lit;
  int verbose = LMODEL_GLOBAL_VERBOSITY;
  Lmodstate->depth = 0;
  Lmodstate->backtrackNr = 0;
  while (array_GetSize(Lmodstate->boundVars)) {
    lmodel_UndoLastBinding(Lmodstate);
  }
  Lmodstate->nextVar = MaxVar;
  lmodel_ReserveBinding(Lmodstate, MaxVar+1);
  Lmodstate->currentBindingDepth = 0;
  if (verbose > 1) {
    printf("\nChecking clause with %li literals and MaxVar %u:\n", array_GetSize(Clause), MaxVar);
    for (i=0; i<array_GetSize(Clause); ++i) {
      lit = (LMODLIT)array_GetElement(Clause, i);
      printf("  Nr. %u: ", i);
      lmodlit_PrintRoot(Lmodstate, lit, TRUE);
      if (verbose > 2) {
        printf("  ");
        lmodlit_PrintLong(Lmodstate, lit);
      }
      else puts("");
#ifdef SPASS_CHECK
      if (lmodlit_GetStatus(lit) != lmodel_StatusTrue()
          && lmodlit_GetStatus(lit) != lmodel_StatusFalse()) {
        misc_StartErrorReport();
        misc_ErrorReport("\n In %s: weird status of literal.", __func__);
        misc_FinishErrorReport();
      }
#endif
    }
    printf("Starting Backtracking with first clause.\n");
  }
  lmodel_CheckClauseFully(Lmodstate, Model, Clause, 0);
  if (verbose > 1) {
    printf("Finished entire backtracking\n");
  }
}
static void lmodel_OnCounterexample(LMODSTATE Lmodstate, LMODEL Model, ARRAY Clause)
{
  MEMORY mem;
  unsigned maxVar, depth;
  SUBST subst;
  int verbose = LMODEL_GLOBAL_VERBOSITY;
  mem = lmodel_GetMemory(Lmodstate);
  maxVar = Lmodstate->onCounterexample_MaxVar;
  subst = subst_Create(mem, maxVar);
  depth = 0;
  for (unsigned i=0; i<maxVar; ++i) {
    TERM term = lmodel_FormBoundTerm(Lmodstate, i);
    unsigned d = (term==NULL ? 0 : term_Depth(lmodel_GetTermstate(Lmodstate), term));
    if (d > depth) depth = d;
    subst_SetValue(subst, i, term);
  }
  if (depth > 0) --depth;
  if (verbose > 1) {
    printf("\nFound Counterexample of depth %u. (Pruning at %u.)\n",
           depth, lmodel_GetPruningDepth(Lmodstate));
    printf("SUBST: ");
    subst_Print(lmodel_GetTermstate(Lmodstate),
                lmodel_GetSymbstate(Lmodstate), subst);
    printf("\n");
  }
#ifdef SPASS_CHECK
  if (lmodel_GetPruningDepth(Lmodstate) <= depth) {
    printf("\n HERE: considered subst of depth %u >= prune depth %u!\n",
           depth, lmodel_GetPruningDepth(Lmodstate));
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: considered subst of depth %u >= prune depth %u!\n",
                     depth, lmodel_GetPruningDepth(Lmodstate));
    misc_FinishErrorReport();
  }
#endif
  if (Lmodstate->onCounterexample_subst != NULL) {
    subst_DeleteWithTerms(lmodel_GetTermstate(Lmodstate), mem,
                          Lmodstate->onCounterexample_subst);
  }
  Lmodstate->onCounterexample_subst = subst;
  lmodel_SetPruningDepth(Lmodstate, depth);
}
unsigned lmodel_GetPruningDepth(LMODSTATE Lmodstate)
{
  return Lmodstate->onCounterexample_depth;
}
void lmodel_SetPruningDepth(LMODSTATE Lmodstate, unsigned Depth)
{
  Lmodstate->onCounterexample_depth = Depth;
}
void lmodel_ResetPruningDepth(LMODSTATE Lmodstate)
{
  lmodel_SetPruningDepth(Lmodstate, (unsigned)(-2));
  Lmodstate->onCounterexample_subst = NULL;
}
SUBST lmodel_CheckSPASSClauseLowestDepth(LMODSTATE Lmodstate, LMODEL Model, CLAUSE Clause)
{
  TERMSTATE termstate;
  MEMORY mem;
  unsigned i;
  TERM atom;
  int polarity;
  LMODLIT lit;
  ARRAY arr;
  const int verbose = LMODEL_GLOBAL_VERBOSITY;
  termstate = lmodel_GetTermstate(Lmodstate);
  mem = lmodel_GetMemory(Lmodstate);
  arr = array_CreateNoInit(mem, clause_GetFolLiterals(Clause));
  array_Claim(arr);
  for (i=0; i<clause_GetFolLiterals(Clause);++i) {
    atom = clause_GetAtom(Clause, i);
    polarity = (i<clause_GetPremiseLiterals(Clause) ? lmodel_StatusFalse() : lmodel_StatusTrue());
    lit = lmodlit_Create(mem, atom, polarity);
    array_SetElement(arr, i, (intptr_t)lit);
  }
  if (verbose > 1) {
    printf("\nChecking spassclause:  ");
    clause_Print(termstate, Clause);
  }
  Lmodstate->onCounterexample_MaxVar = clause_GetVariables(Clause);
  Lmodstate->onCounterexample_subst = NULL;
  lmodel_CheckLmodlitClauseFully(Lmodstate, Model, arr, clause_GetVariables(Clause));
  for (i=0; i<array_GetSize(arr); ++i) {
    lmodlit_Free(mem, (LMODLIT)array_GetElement(arr, i));
  }
  array_Delete(mem, arr);
  SUBST ret = Lmodstate->onCounterexample_subst;
  Lmodstate->onCounterexample_subst = NULL;
  return ret;
}
#if 0
printf("\n --lmdev Switch for developing the linear model building. Implies -tf");
printf("\n         Builds a model of all literals in the parsed conjecture, then");
printf("\n         checks all literals in the parsed axioms against it.");
BOOL lModelDevel = FALSE;
 else if (0 == strcmp(currentParam, "--lmdev")) {
   lModelDevel = TRUE;
   tptpformula = TRUE;
 }
if (lModelDevel) {
  if (1) {
    LMODSTATE lmodstate;
    ARRAY groundLiterals, clauseLiterals;
    LMODEL model;
    lmodstate = lmodel_Init(state);
    if (array_GetSize(tfp->conjectures) != 1) {
      misc_StartUserErrorReport();
      misc_UserErrorReport("\n In %s:", __func__);
      misc_UserErrorReport("\n Ground literals for model building must be given in the single conjecture!");
      misc_FinishUserErrorReport();
    }
    groundLiterals = lmodlit_GrabLiterals(folstate,
                                          (TERM)array_GetElement(tfp->conjectures, 0),
                                          NULL);
    int cleanBehaviour;
    cleanBehaviour = lmodel_AllNegative();
    cleanBehaviour = lmodel_GreedyReject();
    cleanBehaviour = lmodel_GreedyComplete();
    cleanBehaviour = lmodel_AllPositive();
    model = lmodel_BuildFromLmodlits(lmodstate, groundLiterals, cleanBehaviour);
    lmodel_RepresentModel(lmodstate, model);
    lmodel_PrintModel(lmodstate, model);
    for (i=0; i<array_GetSize(tfp->otherterms); ++i) {
      TERM clauseTerm = (TERM)array_GetElement(tfp->otherterms, i);
      clauseLiterals = lmodlit_GrabLiterals(folstate,
                                             clauseTerm,
                                             NULL);
      printf("Checking clause ");
      term_PrintPrefix(termstate, clauseTerm);
      puts("");
      SUBST subst = lmodel_CheckLmodlitClause(lmodstate,
                                              model,
                                              clauseLiterals,
                                              (unsigned)term_MaxVar(termstate, clauseTerm)+1);
      if (subst == NULL) {
        printf("subst=(NULL) clause is true in model\n");
      }
      else {
        printf("clause false under subst ");
        subst_Print(termstate, symbstate, subst);
        puts("");
        subst_DeleteWithTerms(termstate, mem, subst);
      }
      for (j=0; j<array_GetSize(clauseLiterals); ++j) {
        lmodlit_Free(mem, (LMODLIT)array_GetElement(clauseLiterals, j));
      }
      array_Delete(mem, clauseLiterals);
    }
    lmodel_PrintModel(lmodstate, model);
    lmodel_Delete(lmodstate, model);
    lmodel_Free(lmodstate);
  }
  for (i=0; i<array_GetSize(tfp->conjectures);i++){
    term_Delete(termstate, (TERM) array_GetElement(tfp->conjectures, i));
  }
  array_Delete(mem, tfp->conjectures);
  for (i =0; i<array_GetSize(tfp->otherterms);i++){
    term_Delete(termstate, (TERM) array_GetElement(tfp->otherterms, i));
  }
  array_Delete(mem, tfp->otherterms);
  tptp_DeleteFofParsed(state->memory, state->termstate, tfp);
  tptp_Delete(tptp_parsestate);
  state_SetClauses(state, array_Create(state->memory, 2));
  state_Delete(state);
  sharing_Free(sharer);
  fol_Free(folstate);
  term_TermstateFree(termstate);
  symbol_Free(symbstate);
  subst_StateDelete(mem, subststate);
#ifdef SPASS_CHECK
  memory_Print(mem, 'c');
  memory_PrintLeaks(mem);
#endif
  memory_Delete(mem);
  exit(0);
 }
#endif
