#ifdef DOC_BUILD_INTERNAL
#endif
#include "abstract.h"
const unsigned abstr_INITIALCAP = 32;
ABSTR abstr_Create(MEMORY Mem, TERMSTATE Termstate, FOLSTATE Folstate, SYMBSTATE Symbstate, SHARER Sharer, TRAIL Trail)
{
  ABSTR abstr;
  FLAGSTORE store;
  ARRAY stateflags;
  abstr = memory_Malloc(Mem, sizeof(ABSTR_NODE));
  abstr->mem = Mem;
  abstr->termstate = Termstate;
  abstr->folstate = Folstate;
  abstr->symbstate = Symbstate;
  abstr->sharer = Sharer;
  abstr->trail = Trail;
  abstr->emptyclause = (CLAUSE)NULL;
  abstr->mapping = array_Create(Mem, abstr_INITIALCAP);
  abstr->plits = array_Create(Mem, abstr_INITIALCAP);
  abstr->first = TRUE;
  abstr->unsat = FALSE;
  abstr->clauses = memory_Malloc(Mem, sizeof(ABSTR_CLAUSES_NODE));
  abstr->clauses->pclauses = array_Create(Mem, abstr_INITIALCAP);
  abstr->clauses->folclauses = array_Create(Mem, abstr_INITIALCAP);
  abstr->clauses->substs = array_Create(Mem, abstr_INITIALCAP);
  abstr->pstate = pstate_Create(Mem);
  pstate_Init(abstr->pstate, abstr_INITIALCAP, 0);
  pstate_SetInputClauses(abstr->pstate, array_Create(Mem, 0), NULL);
  store = pstate_CreateFlagstore(Mem, &stateflags);
  pstate_SetFlagstore(abstr->pstate, store, stateflags);
  flag_StoreSetFlagValue(store, pstate_FLAG_VERBOSE, 0);
  flag_StoreSetFlagValue(store, pstate_FLAG_TIMELIMIT, 0);
  abstr->reductions = array_Create(Mem, abstr_INITIALCAP);
  return abstr;
}
void abstr_Delete(ABSTR Abstr)
{
  MEMORY mem;
  PSTATE pstate;
  PCLAUSE pclause;
  CLAUSE folclause;
  TERMSTATE termstate;
  SUBST subst;
  ARRAY mapping, plits, pclauses, folclauses, substs, reductions;
  BOOL unsat;
  unsigned i;
  mem = abstr_GetMemory(Abstr);
  pstate = abstr_GetSATState(Abstr);
  mapping = abstr_GetMapping(Abstr);
  plits = abstr_GetPropLitsArray(Abstr);
  pclauses = abstr_GetPropClauses(Abstr);
  folclauses = abstr_GetFOLClauses(Abstr);
  substs = abstr_GetSubsts(Abstr);
  unsat = abstr_GetPropUNSAT(Abstr);
  termstate = abstr_GetTermState(Abstr);
  reductions = abstr_GetReductions(Abstr);
  flag_DeleteStore(mem, pstate_GetFlagstore(pstate));
  pstate_Delete(pstate);
  array_Delete(mem, mapping);
  array_Delete(mem, plits);
  if (!unsat) {
    for (i = 0; i < array_GetSize(pclauses); i++) {
      pclause = (PCLAUSE)array_GetElement(pclauses, i);
      pclause_Delete(mem, pclause);
    }
  }
  for (i = 0; i < array_GetSize(folclauses); i++) {
    folclause = (CLAUSE)array_GetElement(folclauses, i);
    clause_Delete(mem, termstate, folclause);
  }
  for (i = 0; i < array_GetSize(substs); i++) {
    subst = (SUBST)array_GetElement(substs, i);
    subst_DeleteWithTerms(termstate, mem, subst);
  }
  array_Delete(mem, pclauses);
  array_Delete(mem, folclauses);
  array_Delete(mem, substs);
  for (i = 0; i < array_GetSize(reductions); i++) {
    array_Delete(mem, (ARRAY)array_GetElement(reductions, i));
  }
  array_Delete(mem, reductions);
  memory_Free(mem, Abstr->clauses, sizeof(ABSTR_CLAUSES_NODE));
  memory_Free(mem, Abstr, sizeof(ABSTR_NODE));
}
MEMORY abstr_GetMemory(ABSTR Abstr)
{
  return Abstr->mem;
}
void abstr_SetMemory(ABSTR Abstr, MEMORY Mem)
{
  Abstr->mem = Mem;
}
CLAUSE abstr_GetEmptyClause(ABSTR Abstr)
{
  return Abstr->emptyclause;
}
void abstr_SetEmptyClause(ABSTR Abstr, CLAUSE Clause)
{
  Abstr->emptyclause = Clause;
}
TERMSTATE abstr_GetTermState(ABSTR Abstr)
{
  return Abstr->termstate;
}
void abstr_SetTermState(ABSTR Abstr, TERMSTATE Termstate)
{
  Abstr->termstate = Termstate;
}
FOLSTATE abstr_GetFOLState(ABSTR Abstr)
{
  return Abstr->folstate;
}
void abstr_SetFOLState(ABSTR Abstr, FOLSTATE Folstate)
{
  Abstr->folstate = Folstate;
}
SYMBSTATE abstr_GetSymbState(ABSTR Abstr)
{
  return Abstr->symbstate;
}
void abstr_SetSymbState(ABSTR Abstr, SYMBSTATE Symbstate)
{
  Abstr->symbstate = Symbstate;
}
SHARER abstr_GetSharer(ABSTR Abstr)
{
  return Abstr->sharer;
}
void abstr_SetSharer(ABSTR Abstr, SHARER Sharer)
{
  Abstr->sharer = Sharer;
}
TRAIL abstr_GetSCLTrail(ABSTR Abstr)
{
  return Abstr->trail;
}
void abstr_SetSCLTrail(ABSTR Abstr, TRAIL Trail)
{
  Abstr->trail = Trail;
}
PSTATE abstr_GetSATState(ABSTR Abstr)
{
  return Abstr->pstate;
}
void abstr_SetSATState(ABSTR Abstr, PSTATE PropState)
{
  Abstr->pstate = PropState;
}
ARRAY abstr_GetMapping(ABSTR Abstr)
{
  return Abstr->mapping;
}
void abstr_SetMapping(ABSTR Abstr, ARRAY Mapping)
{
  Abstr->mapping = Mapping;
}
ARRAY abstr_GetPropLitsArray(ABSTR Abstr)
{
  return Abstr->plits;
}
void abstr_SetPropLitsArray(ABSTR Abstr, ARRAY Plits)
{
  Abstr->plits = Plits;
}
BOOL abstr_GetFirst(ABSTR Abstr)
{
  return Abstr->first;
}
void abstr_SetFirst(ABSTR Abstr, BOOL First)
{
  Abstr->first = First;
}
BOOL abstr_GetPropUNSAT(ABSTR Abstr)
{
  return Abstr->unsat;
}
void abstr_SetPropUNSAT(ABSTR Abstr, BOOL UNSAT)
{
  Abstr->unsat = UNSAT;
}
ARRAY abstr_GetPropClauses(ABSTR Abstr)
{
  return Abstr->clauses->pclauses;
}
void abstr_SetPropClauses(ABSTR Abstr, ARRAY PropClauses)
{
  Abstr->clauses->pclauses = PropClauses;
}
ARRAY abstr_GetFOLClauses(ABSTR Abstr)
{
  return Abstr->clauses->folclauses;
}
void abstr_SetFOLClauses(ABSTR Abstr, ARRAY FOLClauses)
{
  Abstr->clauses->folclauses = FOLClauses;
}
ARRAY abstr_GetSubsts(ABSTR Abstr)
{
  return Abstr->clauses->substs;
}
void abstr_SetSubsts(ABSTR Abstr, ARRAY Substs)
{
  Abstr->clauses->substs = Substs;
}
ARRAY abstr_GetReductions(ABSTR Abstr)
{
  return Abstr->reductions;
}
void abstr_SetReductions(ABSTR Abstr, ARRAY Reductions)
{
  Abstr->reductions = Reductions;
}
void abstr_AddClauseAbstractionInfo(ABSTR Abstr, PCLAUSE PropClause, CLAUSE Clause, SUBST Subst)
{
  MEMORY mem;
  ARRAY pclauses, folclauses, substs;
  TERMSTATE termstate;
  mem = abstr_GetMemory(Abstr);
  termstate = abstr_GetTermState(Abstr);
  pclauses = abstr_GetPropClauses(Abstr);
  folclauses = abstr_GetFOLClauses(Abstr);
  substs = abstr_GetSubsts(Abstr);
  pclause_SetAbstrId(PropClause, array_GetSize(pclauses));
  PropClause = pclause_Copy(mem, PropClause);
  Clause = clause_Copy(termstate, Clause, TRUE);
  Subst = subst_CopyWitTerms(termstate, Subst, subst_NumberOfVariables(Subst));
  pclauses = array_Add(mem, pclauses, (intptr_t)PropClause);
  folclauses = array_Add(mem, folclauses, (intptr_t)Clause);
  substs = array_Add(mem, substs, (intptr_t)Subst);
  abstr_SetPropClauses(Abstr, pclauses);
  abstr_SetFOLClauses(Abstr, folclauses);
  abstr_SetSubsts(Abstr, substs);
}
PCLAUSE abstr_FOLClauseToPropClause(ABSTR Abstr, CLAUSE Clause, SUBST Subst)
{
  MEMORY mem;
  TERM atom;
  ARRAY plits;
  TERMSTATE termstate;
  SHARER sharer;
  unsigned i;
  PLIT plit;
  PCLAUSE pclause;
  int index;
  plits = abstr_GetPropLitsArray(Abstr);
  mem = abstr_GetMemory(Abstr);
  termstate = abstr_GetTermState(Abstr);
  sharer = abstr_GetSharer(Abstr);
  array_Clean(plits);
  for (i = 0; i < clause_GetPremiseLiterals(Clause); i++) {
    atom = clause_GetAtom(Clause, i);
    atom = term_Copy(termstate, atom);
    if (Subst) {
      atom = subst_SubstApplyTerm(termstate, atom, Subst, TRUE);
    }
    atom = sharing_GetSharedTerm(sharer, atom);
    plit = var_VarGetLiteralNo(term_GetPropVar(atom), FALSE);
    if (!array_ContainsElement(plits, (intptr_t)plit, &index)) {
      plits = array_Add(mem, plits, (intptr_t)(plit));
    }
  }
  for (; i < clause_GetFolLiterals(Clause); i++) {
    atom = clause_GetAtom(Clause, i);
    atom = term_Copy(termstate, atom);
    if (Subst) {
      atom = subst_SubstApplyTerm(termstate, atom, Subst, TRUE);
    }
    atom = sharing_GetSharedTerm(sharer, atom);
    plit = var_VarGetLiteralNo(term_GetPropVar(atom), TRUE);
    if (!array_ContainsElement(plits, (intptr_t)plit, &index)) {
      plits = array_Add(mem, plits, (intptr_t)(plit));
    }
  }
  abstr_SetPropLitsArray(Abstr, plits);
  pclause = pclause_CreateFromLiterals(mem, plits, pstate_GetFreshId(abstr_GetSATState(Abstr)), FALSE);
  abstr_AddClauseAbstractionInfo(Abstr, pclause, Clause, Subst);
  return pclause;
}
void abstr_MappingAdd(ABSTR Abstr, TERM Term)
{
  ARRAY mapping;
  if (!term_PropVarSet(Term)) {
    mapping = abstr_GetMapping(Abstr);
    term_SetPropVar(Term, array_GetSize(mapping));
    mapping = array_Add(abstr_GetMemory(Abstr), mapping, (intptr_t)Term);
    abstr_SetMapping(Abstr, mapping);
    pstate_AddVar(abstr_GetSATState(Abstr), FALSE);
  }
}
void abstr_MappingPrint(ABSTR Abstr)
{
  unsigned i;
  ARRAY mapping;
  TERMSTATE termstate;
  mapping = abstr_GetMapping(Abstr);
  termstate = abstr_GetTermState(Abstr);
  printf("%% Mappings between FOL ground atoms and propositional variables:\n");
  for (i = 0; i < array_GetSize(mapping); i++) {
    printf("%% Variable %d: ", i+1);
    term_PrettyPrint(termstate, (TERM)array_GetElement(mapping, i));
    printf("\n");
  }
  printf("\n");
}
void abstr_AddClause(ABSTR Abstr, PCLAUSE PropClause, BOOL Lazy)
{
  PSTATE pstate;
  PLIT plit;
  WLISTS wlists;
  WATCHERS_NODE *watchers;
  unsigned i;
  pstate = abstr_GetSATState(Abstr);
  if (abstr_GetFirst(Abstr) || Lazy) {
    pstate_AddToAllClauses(pstate, PropClause);
  }
  else {
    pstate_SetDl(pstate, 0);
    if (pstate_GetPrevious(pstate) != NULL) {
      psolver_AddClause(pstate, pstate_GetPrevious(pstate), TRUE, TRUE);
      pstate_SetPrevious(pstate, NULL);
    }
    psolver_MakeBacktrack(pstate);
    pstate_AddToAllClauses(pstate, PropClause);
    wlists = pstate_GetWlist(pstate);
    watchers = wlists->watchers;
    for (i = 0; i < wlist_GetSize(wlists); i++) {
      watchers[i].size = 0;
    }
    pindex_Reset(pstate_GetIndex(pstate));
    pindex_Reset(pstate_GetLIndex(pstate));
    pindex_Reset(pstate_GetTwoIndex(pstate));
    pindex_Reset(pstate_GetThreeIndex(pstate));
    for (i = 0; i < array_GetSize(pstate_GetUnits(pstate)); i++) {
      PropClause = (PCLAUSE)array_GetElement(pstate_GetUnits(pstate), i);
      plit = PropClause[0];
      var_Set(pstate_GetVar(pstate, var_LiteralGetVarNo(plit)),
              var_LiteralIsPositive(plit),
              pstate_GetDl(pstate),
              PropClause);
    }
  }
}
BOOL abstr_RunSATSolverAddClause(ABSTR Abstr, PCLAUSE PropClause)
{
  PSTATE pstate;
  FLAGSTORE store;
  BOOL sat;
  PLIT plit;
  WLISTS wlists;
  WATCHERS_NODE *watchers;
  unsigned timelimit, i;
  pstate = abstr_GetSATState(Abstr);
  store = pstate_GetFlagstore(pstate);
  timelimit = flag_StoreGetFlagValue(store, pstate->stateflags[pstate_FLAG_TIMELIMIT]);
  if (abstr_GetFirst(Abstr)) {
    pstate_AddToAllClauses(pstate, PropClause);
    preduce_Preprocess(pstate);
    sat = psolver_Solve(pstate, timelimit, TRUE);
    abstr_SetFirst(Abstr, FALSE);
  }
  else {
    pstate_SetDl(pstate, 0);
    if (pstate_GetPrevious(pstate) != NULL) {
      psolver_AddClause(pstate, pstate_GetPrevious(pstate), TRUE, TRUE);
      pstate_SetPrevious(pstate, NULL);
    }
    psolver_MakeBacktrack(pstate);
    pstate_AddToAllClauses(pstate, PropClause);
    wlists = pstate_GetWlist(pstate);
    watchers = wlists->watchers;
    for (i = 0; i < wlist_GetSize(wlists); i++) {
      watchers[i].size = 0;
    }
    pindex_Reset(pstate_GetIndex(pstate));
    pindex_Reset(pstate_GetLIndex(pstate));
    pindex_Reset(pstate_GetTwoIndex(pstate));
    pindex_Reset(pstate_GetThreeIndex(pstate));
    for (i = 0; i < array_GetSize(pstate_GetUnits(pstate)); i++) {
      PropClause = (PCLAUSE)array_GetElement(pstate_GetUnits(pstate), i);
      plit = PropClause[0];
      var_Set(pstate_GetVar(pstate, var_LiteralGetVarNo(plit)),
              var_LiteralIsPositive(plit),
              pstate_GetDl(pstate),
              PropClause);
    }
    preduce_Preprocess(pstate);
    sat = psolver_Solve(pstate, timelimit, FALSE);
  }
  if (!sat) {
    Abstr->unsat = TRUE;
    abstr_RefreshSolverState(Abstr);
    pstate = abstr_GetSATState(Abstr);
    store = pstate_GetFlagstore(pstate);
    timelimit = flag_StoreGetFlagValue(store, pstate->stateflags[pstate_FLAG_TIMELIMIT]);
    preduce_Preprocess(pstate);
    psolver_Solve(pstate, timelimit, TRUE);
    abstr_FindUNSATCore(Abstr);
  }
  return sat;
}
BOOL abstr_RunSATSolver(ABSTR Abstr)
{
  PSTATE pstate;
  FLAGSTORE store;
  BOOL sat;
  PLIT plit;
  WLISTS wlists;
  WATCHERS_NODE *watchers;
  unsigned timelimit, i;
  PCLAUSE propclause;
  pstate = abstr_GetSATState(Abstr);
  store = pstate_GetFlagstore(pstate);
  timelimit = flag_StoreGetFlagValue(store, pstate->stateflags[pstate_FLAG_TIMELIMIT]);
  pstate_SetDl(pstate, 0);
  if (pstate_GetPrevious(pstate) != NULL) {
    psolver_AddClause(pstate, pstate_GetPrevious(pstate), TRUE, TRUE);
    pstate_SetPrevious(pstate, NULL);
  }
  psolver_MakeBacktrack(pstate);
  wlists = pstate_GetWlist(pstate);
  watchers = wlists->watchers;
  for (i = 0; i < wlist_GetSize(wlists); i++) {
    watchers[i].size = 0;
  }
  pindex_Reset(pstate_GetIndex(pstate));
  pindex_Reset(pstate_GetLIndex(pstate));
  pindex_Reset(pstate_GetTwoIndex(pstate));
  pindex_Reset(pstate_GetThreeIndex(pstate));
  for (i = 0; i < array_GetSize(pstate_GetUnits(pstate)); i++) {
    propclause = (PCLAUSE)array_GetElement(pstate_GetUnits(pstate), i);
    plit = propclause[0];
    var_Set(pstate_GetVar(pstate, var_LiteralGetVarNo(plit)),
     var_LiteralIsPositive(plit),
     pstate_GetDl(pstate),
     propclause);
  }
  pstate_SetOrigVars(pstate, pstate_GetVarCount(pstate));
  preduce_Preprocess(pstate);
  sat = psolver_Solve(pstate, timelimit, FALSE);
  if (!sat) {
    Abstr->unsat = TRUE;
    abstr_RefreshSolverState(Abstr);
    pstate = abstr_GetSATState(Abstr);
    store = pstate_GetFlagstore(pstate);
    timelimit = flag_StoreGetFlagValue(store, pstate->stateflags[pstate_FLAG_TIMELIMIT]);
    preduce_Preprocess(pstate);
    psolver_Solve(pstate, timelimit, TRUE);
    abstr_FindUNSATCore(Abstr);
  }
  return sat;
}
BOOL abstr_RunSATSolverDecisionLiterals(ABSTR Abstr)
{
  PSTATE pstate;
  TRAIL scltrail;
  TRAILDATA traildata;
  TERM atom;
  PVAR pvar;
  PLIT plit;
  PCLAUSE pclause;
  BOOL phase, conflict;
  unsigned i;
  pstate = abstr_GetSATState(Abstr);
  scltrail = abstr_GetSCLTrail(Abstr);
  if (abstr_GetFirst(Abstr)) {
    preduce_Preprocess(pstate);
    abstr_SetFirst(Abstr, FALSE);
  }
  else {
    pstate_SetDl(pstate, 0);
    if (pstate_GetPrevious(pstate) != NULL) {
      psolver_AddClause(pstate, pstate_GetPrevious(pstate), TRUE, TRUE);
      pstate_SetPrevious(pstate, NULL);
    }
    psolver_MakeBacktrack(pstate);
    for (i = 0; i < pstate_GetVarCount(pstate); i++) {
      var_Unset(pstate_GetVar(pstate, i));
    }
    for (i = 0; i < array_GetSize(pstate_GetUnits(pstate)); i++) {
      pclause = (PCLAUSE)array_GetElement(pstate_GetUnits(pstate), i);
      plit = pclause[0];
      var_Set(pstate_GetVar(pstate, var_LiteralGetVarNo(plit)),
              var_LiteralIsPositive(plit),
              pstate_GetDl(pstate),
              pclause);
    }
  }
  conflict = FALSE;
  for (i = 0; i < trail_GetDl(scltrail); i++) {
    traildata = trail_GetDecisionAtDl(scltrail, i);
    atom = trail_AtomFromData(scltrail, traildata);
    pvar = term_GetPropVar(atom);
    phase = trail_IsPositiveFromData(scltrail, traildata);
    plit = var_VarGetLiteralNo(pvar, phase);
    pclause = var_GetReason(pstate_GetVar(pstate, pvar));
    if (pclause) {
      if (var_GetLastAssignment(pstate_GetVar(pstate, pvar)) == phase) {
        continue;
      }
      else {
        conflict = TRUE;
        break;
      }
    }
    pstate_IncreaseDecCount(pstate);
    pstate_NewDl(pstate);
    psolver_SetVar(pstate, plit, pclause_DECISION);
    while (pstate_HasPropLits(pstate)) {
      pstate_IncreasePropCount(pstate);
      if (psolver_PropagateNextLit(pstate, &plit)) {
        conflict = TRUE;
        break;
      }
    }
    if (conflict) {
      break;
    }
  }
  return conflict;
}
void abstr_AddAllGroundClauses(ABSTR Abstr, ARRAY Clauses)
{
  CLAUSE clause;
  PCLAUSE pclause;
  TERMSTATE termstate;
  TERM atom;
  unsigned numliterals, i, j;
  BOOL ispropclause;
  termstate = abstr_GetTermState(Abstr);
  for (i = 0; i < array_GetSize(Clauses); i++) {
    ispropclause = TRUE;
    clause = (CLAUSE)array_GetElement(Clauses, i);
    numliterals = clause_GetPremiseLiterals(clause) + clause_GetConclusionLiterals(clause);
    for (j = 0; j < numliterals; j++) {
      atom = clause_GetAtom(clause, j);
      if (!term_IsGround(termstate, atom)) {
        ispropclause = FALSE;
        break;
      }
    }
    if (!ispropclause) continue;
    for (j = 0; j < numliterals; j++) {
      atom = clause_GetAtom(clause, j);
      if (term_GetPropVar(atom) == var_NONE) {
        abstr_MappingAdd(Abstr, atom);
      }
    }
    pclause = abstr_FOLClauseToPropClause(Abstr, clause, NULL);
    pstate_AddToAllClauses(abstr_GetSATState(Abstr), pclause);
  }
}
void abstr_RefreshSolverState(ABSTR Abstr)
{
  PSTATE pstate;
  FLAGSTORE store;
  ARRAY stateflags, pclauses;
  MEMORY mem;
  PCLAUSE pclause;
  unsigned varcount, i;
  mem = abstr_GetMemory(Abstr);
  pstate = abstr_GetSATState(Abstr);
  pclauses = abstr_GetPropClauses(Abstr);
  varcount = pstate_GetVarCount(pstate);
  flag_DeleteStore(mem, pstate_GetFlagstore(pstate));
  pstate_Delete(pstate);
  pstate = pstate_Create(mem);
  pstate_Init(pstate, varcount, varcount);
  abstr_SetSATState(Abstr, pstate);
  store = pstate_CreateFlagstore(mem, &stateflags);
  pstate_SetFlagstore(Abstr->pstate, store, stateflags);
  flag_StoreSetFlagValue(store, pstate_FLAG_VERBOSE, 0);
  flag_StoreSetFlagValue(store, pstate_FLAG_TIMELIMIT, 0);
  for (i = 0; i < array_GetSize(pclauses); i++) {
    pclause = (PCLAUSE)array_GetElement(pclauses, i);
    pclause_SetId(pclause, i);
  }
  pstate_SetTrackUNSATCore(pstate, TRUE);
  pstate_SetInputClauses(pstate, array_Copy(abstr_GetMemory(Abstr), abstr_GetPropClauses(Abstr)), NULL);
  pstate_InitReasonsTable(pstate);
}
void abstr_FindUNSATCore(ABSTR Abstr)
{
  ARRAY core;
  ARRAY stack;
  ARRAY handled;
  MEMORY mem;
  PSTATE pstate;
  PCLAUSE pclause;
  ARRAY reasons;
  int pos;
  unsigned i, j, k, pclauseid, reasonclauseid, abstrid;
  ARRAY reductions, reduction;
  REASONS reasonsentry;
#ifdef SPASS_CHECK
  BOOL found;
#endif
  mem = abstr_GetMemory(Abstr);
  pstate = abstr_GetSATState(Abstr);
  core = array_Create(mem, abstr_INITIALCAP);
  stack = array_Create(mem, abstr_INITIALCAP);
  handled = array_Create(mem, abstr_INITIALCAP);
  pclause = NULL;
  for (i = 0; i < array_GetSize(pstate_GetAllClauses(pstate)); i++) {
    pclause = (PCLAUSE)array_GetElement(pstate_GetAllClauses(pstate), i);
    if (pclause_IsEmptyClause(pclause)) {
      stack = array_Push(mem, stack, (intptr_t)pclause_GetId(pclause));
      break;
    }
  }
#ifdef SPASS_CHECK
  if (array_IsEmpty(stack)) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: ", __func__);
    misc_ErrorReport("no empty clause found in the SAT solver state");
    misc_FinishErrorReport();
  }
#endif
  while (!array_IsEmpty(stack)) {
    pclauseid = (unsigned)array_Pop(stack);
    reasonsentry = (REASONS)array_GetElement(pstate->reasonstable, pclauseid);
    if (array_ContainsElement(handled, (intptr_t)reasonsentry, &pos))
      continue;
    reasons = reasonsentry->reasons;
    if (reasons) {
      for (i = 0; i < array_GetSize(reasons); i++) {
        reasonclauseid = (unsigned)array_GetElement(reasons, i);
        stack = array_Push(mem, stack, (intptr_t)reasonclauseid);
      }
    }
    core = array_Add(mem, core, (intptr_t)reasonsentry->origid);
    handled = array_Add(mem, handled, (intptr_t)reasonsentry);
  }
  for (i = 0; i < array_GetSize(core); i++) {
    pclauseid = (unsigned)array_GetElement(core, i);
    pclause = pstate_GetClauseById(pstate, pclauseid);
    pclause_ResetSize(pclause);
  }
  reductions = abstr_GetReductions(Abstr);
  for (i = 0; i < array_GetSize(core); i++) {
    pclauseid = (unsigned)array_GetElement(core, i);
    pclause = pstate_GetClauseById(pstate, pclauseid);
    abstrid = pclause_GetAbstrId(pclause);
    for (j = 0; j < array_GetSize(reductions); j++) {
      reduction = (ARRAY)array_GetElement(reductions, j);
      if (array_PairFirst(reduction) == abstrid) {
#ifdef SPASS_CHECK
        found = FALSE;
#endif
        for (k = 0; k < pclause_GetSize(pclause); k++) {
          if ((PLIT)array_PairSecond(reduction) == pclause_GetLiteral(pclause, k)) {
            pclause_RemoveLiteralSwap(pclause, pclause + k);
#ifdef SPASS_CHECK
            found = TRUE;
#endif
            break;
          }
        }
#ifdef SPASS_CHECK
        if (!found) {
          misc_StartErrorReport();
          misc_ErrorReport("\n In %s: ", __func__);
          misc_ErrorReport("the removed literal does not exist in the clause");
          misc_FinishErrorReport();
        }
#endif
      }
    }
  }
  abstr_PrintUNSATCore(Abstr, core, TRUE);
  array_Delete(mem, core);
  array_Delete(mem, stack);
  array_Delete(mem, handled);
}
void abstr_PrintUNSATCore(ABSTR Abstr, ARRAY Core, BOOL Fol)
{
  TERMSTATE termstate;
  ARRAY mapping;
  PSTATE pstate;
  PCLAUSE pclause;
  CLAUSE folclause, emptyclause;
  int len;
  unsigned i, j, pclauseid;
  PLIT plit;
  pstate = abstr_GetSATState(Abstr);
  termstate = abstr_GetTermState(Abstr);
  mapping = abstr_GetMapping(Abstr);
  emptyclause = clause_CreateGeneric(abstr_GetMemory(Abstr),0,0);
  if (!Fol) {
    printf("\n");
    printf("%% Unsatisfiable core in propositional terms (after reduction, with learned clauses):%n\n", &len);
    abstr_PrintDivisor(len);
    printf("%% p cnf %ld %ld\n", array_GetSize(abstr_GetMapping(Abstr)), array_GetSize(Core));
    for (i = 0; i < array_GetSize(Core); i++) {
      pclauseid = (unsigned)array_GetElement(Core, i);
      pclause = pstate_GetClauseById(pstate, pclauseid);
      printf("%% ");
      pclause_PrintDIMACS(pclause);
      printf("\n");
    }
    abstr_PrintDivisor(len);
    printf("\n");
    printf("%% Unsatisfiable core in FOL ground terms (after reduction, with learned clauses):%n\n", &len);
    abstr_PrintDivisor(len);
    for (i = 0; i < array_GetSize(Core); i++) {
      pclauseid = (unsigned)array_GetElement(Core, i);
      pclause = pstate_GetClauseById(pstate, pclauseid);
      printf("%% %s ", pclause_IsLearned(pclause) ? "(Learned)    " : "(Not learned)");
      for (j = 0; j < pclause_GetSize(pclause); j++) {
 plit = pclause_GetLiteral(pclause, j);
 if (!var_LiteralIsPositive(plit)) {
   term_PrettyPrint(termstate, (TERM)array_GetElement(mapping, var_LiteralGetVarNo(plit)));
   printf(" ");
 }
      }
      printf("-> ");
      for (j = 0; j < pclause_GetSize(pclause); j++) {
 plit = pclause_GetLiteral(pclause, j);
 if (var_LiteralIsPositive(plit)) {
   term_PrettyPrint(termstate, (TERM)array_GetElement(mapping, var_LiteralGetVarNo(plit)));
   printf(" ");
 }
      }
      printf("\n");
    }
    abstr_PrintDivisor(len);
  }
  for (i = 0; i < array_GetSize(Core); i++) {
    pclauseid = (unsigned)array_GetElement(Core, i);
    pclause = pstate_GetClauseById(pstate, pclauseid);
    if (pclause_IsLearned(pclause))
      continue;
    folclause = (CLAUSE)array_GetElement(abstr_GetFOLClauses(Abstr), pclauseid);
    clause_AddParent(abstr_GetMemory(Abstr), emptyclause, clause_GetId(folclause), 0);
  }
  abstr_SetEmptyClause(Abstr, emptyclause);
  abstr_PrintDivisor(len);
}
void abstr_PrintDivisor(int len)
{
  int i;
  printf("%% ");
  for (i = 0; i < len; i++) {
    putchar('=');
  }
  putchar('\n');
}
void abstr_HandleReduction(ABSTR Abstr, ARRAY Reductions)
{
  CLAUSE rclause;
  TERM rterm;
  unsigned clauseid, i;
  for (i = 0; i < array_GetSize(Reductions); i=i+2) {
    rclause = (CLAUSE)array_GetElement(Reductions, i);
    rterm = (TERM)array_GetElement(Reductions, i+1);
    clauseid = clause_GetId(rclause);
    abstr_HandleReductionIter(Abstr, abstr_GetPropClauses(Abstr), rterm, clauseid);
  }
}
void abstr_HandleReductionIter(ABSTR Abstr, ARRAY PropClauses,
                               TERM ReducedAtom, unsigned ClauseId)
{
  ARRAY folclauses, substs;
  BOOL foundlit;
  TERMSTATE termstate;
  TERM groundatom;
  SHARER sharer;
  SUBST subst;
  PVAR pvar;
  PLIT plit;
  PCLAUSE pclause;
  unsigned pclauseid, i, j;
  substs = abstr_GetSubsts(Abstr);
  folclauses = abstr_GetFOLClauses(Abstr);
  termstate = abstr_GetTermState(Abstr);
  sharer = abstr_GetSharer(Abstr);
  for (i = 0; i < array_GetSize(PropClauses); i++) {
    pclause = (PCLAUSE)array_GetElement(PropClauses, i);
    if (pclause_IsLearned(pclause))
      continue;
    pclauseid = pclause_GetAbstrId(pclause);
    if (ClauseId != clause_GetId((CLAUSE)array_GetElement(folclauses, pclauseid)))
      continue;
    subst = (SUBST)array_GetElement(substs, pclauseid);
    groundatom = term_Copy(termstate, ReducedAtom);
    groundatom = subst_SubstApplyTerm(termstate, groundatom, subst, TRUE);
    groundatom = sharing_GetSharedTerm(sharer, groundatom);
    pvar = term_GetPropVar(groundatom);
    foundlit = FALSE;
    for (j = 0; j < pclause_GetSize(pclause); j++) {
      plit = pclause_GetLiteral(pclause, j);
      if (pvar == var_LiteralGetVarNo(plit)) {
        foundlit = TRUE;
        break;
      }
    }
    if (foundlit) {
      abstr_AddReductionRecord(Abstr, pclause_GetAbstrId(pclause), pclause_GetLiteral(pclause, j));
      pclause_RemoveLiteralSwap(pclause, pclause + j);
    }
  }
}
void abstr_AddReductionRecord(ABSTR Abstr, unsigned ClauseAbstrID, PLIT Removed)
{
  MEMORY mem;
  ARRAY reductions;
  mem = abstr_GetMemory(Abstr);
  reductions = abstr_GetReductions(Abstr);
  reductions = array_Add(mem, reductions,
    (intptr_t)array_PairCreate(mem, (intptr_t)ClauseAbstrID, (intptr_t)Removed));
  abstr_SetReductions(Abstr, reductions);
}
unsigned abstr_TripleSize(ARRAY *Triple) {
  return term_Size((TERM)array_TripleFirst(*Triple));
}
BOOL abstr_TripleSizeCompare(POINTER Triple1, POINTER Triple2) {
  return (term_Size((TERM)array_TripleFirst(*(ARRAY *)Triple1)) < term_Size((TERM)array_TripleFirst(*(ARRAY *)Triple2)));
}
void abstr_EstablishAbstrTermSize(TERMSTATE Termstate, TERM Term, unsigned Constsize)
{
  if (term_IsVariable(Termstate,Term))
    term_SetSize(Term,1);
  else {
    if (term_IsConstant(Termstate,Term)) {
      term_SetSize(Term,Constsize);
    }
    else {
      unsigned i, sum;
      sum = 0;
      for (i=0;i<term_GetArity(Term);i++) {
 abstr_EstablishAbstrTermSize(Termstate, (TERM)Term[i], Constsize);
 sum += term_Size((TERM)Term[i]);
      }
      term_SetSize(Term,sum+1);
    }
  }
  return;
}
void abstr_SAT(SHARER Sharer, SCLSTATE State)
{
  ARRAY oclauses, aclauses, atoms, occs;
  TERMSTATE termstate;
  SYMBSTATE symbstate;
  SUBSTSTATE subststate;
  MEMORY mem;
  CLAUSE clause;
  TERM atom, newatom;
  SYMBOL pred;
  unsigned i, j, k, cnum, preds,varnum,index;
  termstate = state_GetTermstate(State);
  symbstate = state_GetSymbstate(State);
  subststate = state_GetSubststate(State);
  mem = state_GetMemory(State);
  oclauses = state_GetClauses(State);
  cnum = array_GetSize(oclauses);
  aclauses = array_Create(mem, cnum);
  atoms = array_Create(mem, 10);
  preds = 1;
  symbol_NewSigMark(symbstate, TRUE);
  for (i=0;i<cnum;i++) {
    clause = (CLAUSE)oclauses[i];
    clause = clause_Copy(termstate, clause, FALSE);
    aclauses = array_Add(mem, aclauses, (intptr_t)clause);
    for (j=0;j<clause_GetFolLiterals(clause); j++) {
      atom = (TERM)clause[j];
      abstr_EstablishAbstrTermSize(termstate, atom, 2);
      pred = term_TopSymbol(atom);
      if (symbol_GetSigMark(symbstate, pred) == 0) {
 symbol_SetSigMark(symbstate, pred, preds);
 atoms = array_AddAtIndex(mem, atoms, preds, (intptr_t)array_Create(mem,10));
 preds++;
      }
      atoms[symbol_GetSigMark(symbstate, pred)] = (intptr_t)array_Add(mem, (ARRAY)atoms[symbol_GetSigMark(symbstate, pred)], (intptr_t)array_TripleCreate(mem, (intptr_t)atom, (intptr_t)clause, j));
    }
  }
  varnum = 1;
  for (i=1;i<preds; i++) {
    occs = (ARRAY)atoms[i];
    srtg_AMergeSortCompare(mem, occs, occs, occs+(array_GetSize(occs)-1), (BOOL (*)(POINTER,POINTER))abstr_TripleSizeCompare);
    while (array_GetSize(occs) > 0) {
      atom = term_Copy(termstate, (TERM)array_TripleFirst((ARRAY)occs[0]));
      clause = (CLAUSE)array_TripleSecond((ARRAY)occs[0]);
      index = (unsigned)array_TripleThird((ARRAY)occs[0]);
      abstr_EstablishAbstrTermSize(termstate, (TERM)array_TripleFirst((ARRAY)occs[0]), 1);
      array_TripleDelete(mem, (ARRAY)occs[0]);
      occs[0] = (intptr_t)NULL;
      clause[index] = varnum;
      j = 1;
      while (j < array_GetSize(occs)) {
 subst_ContextStart(subststate, symbstate);
 if (subst_TermUnifyDisjointVarsNoTypes(subststate, termstate, symbstate, atom, (TERM)array_TripleFirst((ARRAY)occs[j]), TRUE)) {
   subst_ContextStop(subststate);
   clause = (CLAUSE)array_TripleSecond((ARRAY)occs[j]);
   index = (unsigned)array_TripleThird((ARRAY)occs[j]);
   symbol_SetStandardVarCounter(symbstate, misc_Max(clause_GetVariables(clause), (unsigned)term_MaxVar(termstate, atom)) + 1);
   subst_ContextStart(subststate, symbstate);
   term_StartStamp(termstate);
   subst_VarNormalize(subststate, termstate, symbstate, atom, NULL, (TYPE)((intptr_t)NULL));
   term_StopStamp(termstate);
   subst_ContextStop(subststate);
   subst_ContextStart(subststate, symbstate);
   subst_TermUnifyIdenticalVarsNoTypes(subststate, termstate, symbstate, atom, (TERM)array_TripleFirst((ARRAY)occs[j]), FALSE);
   newatom = subst_ContextFlattenTermApplyToTerm(subststate, termstate, atom);
   term_Delete(termstate,atom);
   atom = newatom;
   subst_ContextStop(subststate);
   symbol_ResetStandardVarCounter(symbstate);
   subst_ContextStart(subststate, symbstate);
   term_StartStamp(termstate);
   subst_VarNormalize(subststate, termstate, symbstate, atom, NULL, (TYPE)((intptr_t)NULL));
   term_StopStamp(termstate);
   abstr_EstablishAbstrTermSize(termstate, (TERM)array_TripleFirst((ARRAY)occs[j]), 1);
   array_TripleDelete(mem, (ARRAY)occs[j]);
   occs[j] = (intptr_t)NULL;
   clause[index] = varnum;
 }
 subst_ContextStop(subststate);
 j++;
      }
      j = 0;
      k = 1;
      varnum++;
      term_GroundTermConstant(termstate, atom, (SYMBOL)(state_GetConstants(State)[0]));
      atom = sharing_GetSharedTerm(Sharer, atom);
      state_AddGroundAtom(State, atom);
      while (k < array_GetSize(occs)) {
 if (occs[k] != (intptr_t)NULL) {
   occs[j] = occs[k];
   occs[k] = (intptr_t)NULL;
   while (occs[j] != (intptr_t)NULL)
     j++;
 }
 k++;
      }
      array_SetSize(occs, j);
    }
  }
  for (i=1;i<preds; i++) {
    occs = (ARRAY)atoms[i];
    array_Delete(mem, occs);
  }
  array_Delete(mem, atoms);
  for (j=0;j<array_GetSize(aclauses);j++) {
    clause = (CLAUSE)aclauses[j];
    clause_DeleteGeneric(mem,termstate,clause);
  }
  array_Delete(mem, aclauses);
  return;
}
BOOL abstr_DistrnAtomNew(TERMSTATE Termstate, DISTRN Distrn, TERM Atom)
{
  ARRAY result;
  BOOL value;
  result = distrn_ContainsTermCandidates(Distrn, Termstate, Atom);
  value = TRUE;
  if (result != NULL) {
    unsigned i;
    for (i=0; i<array_GetSize(result)&&value;i++) {
      if ((TERM)array_PairFirst((ARRAY)result[i]) == Atom)
 value = FALSE;
    }
    array_Delete(term_GetMemory(Termstate),result);
  }
  return value;
}
void abstr_DistrPrint(TERMSTATE Termstate, ARRAY Data)
{
  printf("Position: %ld ", array_PairSecond(Data));
  printf(" Atom: ");
  term_PrintPrefix(Termstate, (TERM)array_PairFirst(Data));
}
ARRAY abstr_ComputeGeneralAtoms(SHARER Sharer, SCLSTATE State)
{
  ARRAY oclauses, atoms, result, generals;
  TERMSTATE termstate;
  SYMBSTATE symbstate;
  SUBSTSTATE subststate;
  FOLSTATE folstate;
  MEMORY mem;
  CLAUSE clause;
  TERM atom, genatom;
  unsigned i, j, cnum;
  DISTRN distrn;
  termstate = state_GetTermstate(State);
  symbstate = state_GetSymbstate(State);
  subststate = state_GetSubststate(State);
  folstate = state_GetFolstate(State);
  mem = state_GetMemory(State);
  oclauses = state_GetClauses(State);
  cnum = array_GetSize(oclauses);
  atoms = array_Create(mem, 10);
  distrn = distrn_Create(mem);
  result = array_Create(mem, 10);
  generals = array_Create(mem, 10);
  for (i=0;i<cnum;i++) {
    clause = (CLAUSE)oclauses[i];
    for (j=0;j<clause_GetFolLiterals(clause); j++) {
      atom = (TERM)clause[j];
      if (abstr_DistrnAtomNew(termstate, distrn, atom)) {
 distrn_Insert(mem, distrn, termstate, atom, NULL, (intptr_t)array_PairCreate(mem, (intptr_t)atom, array_GetSize(atoms)));
 atoms = array_Add(mem, atoms, (intptr_t)atom);
      }
    }
  }
  for (i=0;i < array_GetSize(atoms);i++) {
    array_Clean(generals);
    atom = (TERM)atoms[i];
    generals = distrn_SearchGeneralizations(mem, distrn, termstate, atom, &generals);
    for (j=0; atom != (TERM)NULL && j<array_GetSize(generals);j++) {
      genatom = (TERM)array_PairFirst((ARRAY)generals[j]);
      if (genatom != atom) {
 subst_ContextStart(subststate, symbstate);
 if (subst_FolTermMatchTerms(subststate, symbstate, termstate, folstate, genatom, NULL, atom, NULL)) {
   subst_ContextStop(subststate);
   subst_ContextStart(subststate, symbstate);
   if (subst_FolTermMatchTerms(subststate, symbstate, termstate, folstate, atom, NULL, genatom, NULL)) {
     if ((unsigned)array_PairSecond((ARRAY)generals[j]) > i)
       atom = (TERM)NULL;
   }
   else
     atom = (TERM)NULL;
   subst_ContextStop(subststate);
 }
 else
   subst_ContextStop(subststate);
      }
    }
    if (atom != (TERM)NULL)
      result = array_Add(mem, result, (intptr_t)atom);
  }
  array_Delete(mem, generals);
  array_Delete(mem, atoms);
  distrn_DeleteWithEntriesIter(mem, distrn, array_PairDelete);
  return result;
}
