#ifdef DOC_BUILD_INTERNAL
#endif
#include "csolver.h"
CSTATE csolver_Create(MEMORY Mem, SUBSTSTATE Subststate, TERMSTATE Termstate, SYMBSTATE Symbstate, FOLSTATE Folstate, SHARER Sharer, SCLSTATE State)
{
  CSTATE cstate;
  cstate = (CSTATE)memory_Malloc(Mem, sizeof(CSTATE_NODE));
  cstate->trail = trail_Create(Mem, Symbstate, Termstate, Folstate, Subststate, Sharer);
  cstate->twfo = twfo_Create(Mem, Subststate, Termstate, Symbstate, Folstate, Sharer, state_GetClauses(State), cstate->trail);
  cstate->cons = array_Create(Mem, 1);
  cstate->prem = array_Create(Mem, 10);
  cstate->conc = array_Create(Mem, 10);
  cstate->parents = array_Create(Mem, 20);
  cstate->abstr = NULL;
  cstate->reductions = NULL;
#if (SPASS_CHECK && (SPASS_CHECK & SPASS_CHECK_NTWFO))
  State->ntwfo = ntwfo_Create(Mem, Subststate, Termstate, Symbstate, Sharer, state_GetClauses(State), state_GetPoslits(State), state_GetNeglits(State));
  csolver_IsNTWFOConsistent(State, cstate->trail, cstate->twfo, State->ntwfo);
#endif
  return cstate;
}
void csolver_UpdateAbstraction(MEMORY Mem, CSTATE Cstate, TERMSTATE Termstate, SYMBSTATE Symbstate, FOLSTATE Folstate, SHARER Sharer, BOOL EnableAbstr)
{
  if (EnableAbstr) {
    Cstate->abstr = abstr_Create(Mem, Termstate, Folstate, Symbstate, Sharer, Cstate->trail);
    Cstate->reductions = array_Create(Mem,30);
  }
}
void csolver_Delete(MEMORY Mem, CSTATE Cstate)
{
  trail_Delete(Cstate->trail);
  twfo_Delete(Cstate->twfo);
  array_Delete(Mem, Cstate->cons);
  array_Delete(Mem, Cstate->prem);
  array_Delete(Mem, Cstate->conc);
  array_Delete(Mem, Cstate->parents);
  if (Cstate->abstr) {
    abstr_Delete(Cstate->abstr);
    array_Delete(Mem, Cstate->reductions);
  }
  memory_Free(Mem, Cstate, sizeof(CSTATE_NODE));
}
TRAIL cstate_GetTrail(CSTATE Cstate)
{
  return Cstate->trail;
}
TWFO cstate_GetTwfo(CSTATE Cstate)
{
  return Cstate->twfo;
}
ARRAY cstate_GetCons(CSTATE Cstate)
{
  return Cstate->cons;
}
void cstate_SetCons(CSTATE Cstate, ARRAY Cons)
{
  Cstate->cons = Cons;
}
ARRAY cstate_GetPrem(CSTATE Cstate)
{
  return Cstate->prem;
}
void cstate_SetPrem(CSTATE Cstate, ARRAY Prem)
{
  Cstate->prem = Prem;
}
ARRAY cstate_GetConc(CSTATE Cstate)
{
  return Cstate->conc;
}
void cstate_SetConc(CSTATE Cstate, ARRAY Conc)
{
  Cstate->conc = Conc;
}
ARRAY cstate_GetParents(CSTATE Cstate)
{
  return Cstate->parents;
}
void cstate_SetParents(CSTATE Cstate, ARRAY Parents)
{
  Cstate->parents = Parents;
}
ARRAY cstate_GetReductions(CSTATE Cstate)
{
  return Cstate->reductions;
}
void cstate_SetReductions(CSTATE Cstate, ARRAY Reductions)
{
  Cstate->reductions = Reductions;
}
ABSTR cstate_GetAbstr(CSTATE Cstate)
{
  return Cstate->abstr;
}
void cstate_SetAbstr(CSTATE Cstate, ABSTR Abstr)
{
  Cstate->abstr = Abstr;
}
void csolver_GenerateTPTPLearnedClauseProblem(SCLSTATE State, CLAUSE Clause)
{
  FILE* output;
  char *filename, *outfile;
  TERMSTATE termstate;
  MEMORY mem;
  int i;
  unsigned j;
  ARRAY parents;
  CLAUSE parent;
  TERM atom;
  mem = state_GetMemory(State);
  termstate = state_GetTermstate(State);
  outfile = (char *)memory_Malloc(mem, 200);
  if (state_GetPConstants(State) == NULL)
    state_SetPConstants(State, array_Create(mem, clause_GetVariables(Clause)+2));
  j = array_GetSize(state_GetPConstants(State));
  if (j < clause_GetVariables(Clause)) {
    for (; j < clause_GetVariables(Clause); j++) {
      sprintf(outfile, "ap%u", j);
      state_AddPConstant(State, symbol_CreateConstant(term_GetSymbstate(termstate), fol_TypeTop(state_GetFolstate(State)), outfile));
    }
  }
  filename = state_GetFilename(State);
  i = string_SubStringChar(filename, '/', '.', outfile);
  parents = (ARRAY)clause_GetParents(Clause);
  if (i>0) {
    sprintf(outfile+i, "-%u.p", clause_GetId(Clause));
    output = fopen(outfile, "w");
    for(i=0;i<array_GetSize(parents);i=i+2) {
      parent = state_GetClauseById(State, (unsigned)parents[i]);
      fprintf(output, "\n");
      clause_FPrintTPTP(output, termstate, parent);
    }
    parent = clause_Copy(termstate, Clause, TRUE);
    for (j=0;j<clause_GetFolLiterals(Clause);j++){
      atom = clause_GetAtom(parent,j);
      term_ReplaceVarsWithConsts(termstate, atom, state_GetPConstants(State));
      fprintf(output, "\ncnf(clause_%u_%u, axiom, (", clause_GetId(Clause), j);
      if (j>=clause_GetPremiseLiterals(Clause))
        fprintf(output, "~");
      term_FPrintPrefix(output, termstate, atom, TRUE);
      fprintf(output, ")).");
    }
    clause_Delete(mem, termstate, parent);
    fclose(output);
    memory_Free(mem, outfile, 200);
  }
}
unsigned csolver_GetRandom(unsigned bound)
{
  unsigned result, chunksize, queryto;
  chunksize = ((unsigned)RAND_MAX + 1) / bound;
  queryto = chunksize * bound;
  while ((result = rand()) >= queryto);
  return result / chunksize;
}
BOOL csolver_CompareTerms(POINTER term1, POINTER term2)
{
  return term_Size(*(TERM*)term1) > term_Size(*(TERM*)term2);
}
BOOL csolver_CompareClauses(POINTER clause1, POINTER clause2)
{
  return clause_GetId(*(CLAUSE*)clause1) > clause_GetId(*(CLAUSE*)clause2);
}
BOOL csolver_FindMatcher(TERMSTATE termstate, TERM A, TERM B, SUBST subst)
{
  unsigned i;
  SYMBOL top_a, top_b;
  top_a = term_TopSymbol(A);
  top_b = term_TopSymbol(B);
  if (symbol_IsVariable(term_GetSymbstate(termstate), top_a)) {
    if (subst_VarDefined(subst, top_a)) {
      return term_Equal(termstate, subst_GetValue(subst, top_a), B);
    }
    subst_SetValue(subst, top_a, B);
    return TRUE;
  }
  if (top_a != top_b)
    return FALSE;
  for (i = 0; i < term_GetArity(A); i++) {
    if (!csolver_FindMatcher(termstate, (TERM)A[i], (TERM)B[i], subst))
      return FALSE;
  }
  return TRUE;
}
int csolver_MaxVar(TERMSTATE termstate, TERM term)
{
  int result, tmp;
  unsigned i;
  SYMBOL top;
  top = term_TopSymbol(term);
  if (symbol_IsVariable(term_GetSymbstate(termstate), top)) {
    return top;
  }
  result = -1;
  for (i = 0; i < term_GetArity(term); i++) {
    tmp = csolver_MaxVar(termstate, (TERM)term[i]);
    if (tmp > result) {
      result = tmp;
    }
  }
  return result;
}
BOOL csolver_IsInstance(MEMORY mem, TERMSTATE termstate, TERM instance, TERM general)
{
  SUBST subst;
  BOOL res;
  subst = subst_Create(mem, csolver_MaxVar(termstate, general)+1);
  res = csolver_FindMatcher(termstate, general, instance, subst);
  subst_Delete(mem, subst);
  return res;
}
SUBST csolver_CreateMatchingSubst(TERMSTATE Termstate, SUBSTSTATE SState, TERM Instance, TERM General, SUBST Remaining)
{
  SUBST subst;
  unsigned i, rvars, tvars, maxvar;
  rvars = subst_NumberOfVariables(Remaining);
  tvars = csolver_MaxVar(Termstate, General) + 1;
  maxvar = (rvars > tvars ? rvars : tvars);
  subst_ContextStart(SState, term_GetSymbstate(Termstate));
  if (!subst_FolTermMatchTermsSubsts(SState, term_GetSymbstate(Termstate), Termstate, NULL, General, NULL, Remaining, Instance, NULL, NULL)) {
    printf("\n General :"); term_PrintPrefix(Termstate, General);printf(" Instance :"); term_PrintPrefix(Termstate, Instance);
    misc_StartErrorReport();
    misc_ErrorReport("In %s: Matcher does not exist.\n", __func__);
    misc_FinishErrorReport();
  }
  for (i=0; i<rvars; i++)
    if (subst_VarDefined(Remaining, i))
      subst_ContextSetValue(SState, i, (intptr_t)subst_GetValue(Remaining, i));
  subst = subst_ContextFlattenExtractSubst(SState, Termstate, term_GetSymbstate(Termstate), maxvar);
  subst_ContextStop(SState);
  return subst;
}
BOOL csolver_EqualWithSubst(TERMSTATE termstate, TERM A, TERM B, SUBST subst)
{
  unsigned i;
  SYMBOL top_a, top_b;
  top_a = term_TopSymbol(A);
  top_b = term_TopSymbol(B);
  if (symbol_IsVariable(term_GetSymbstate(termstate), top_b)) {
    return term_Equal(termstate, A, subst_GetValue(subst, top_b));
  }
  if (top_a != top_b)
    return FALSE;
  for (i = 0; i < term_GetArity(A); i++) {
    if (!csolver_EqualWithSubst(termstate, (TERM)A[i], (TERM)B[i], subst))
      return FALSE;
  }
  return TRUE;
}
BOOL csolver_ClauseIsFalse(TRAIL Trail, CLAUSE Clause, SUBST Subst)
{
  unsigned i;
  for (i=0; i<clause_GetPremiseLiterals(Clause); i++)
    if (trail_LitStatusFromAtom(Trail, (TERM)Clause[i], Subst, FALSE) != SET_FALSE)
      return FALSE;
  for (; i<clause_GetFolLiterals(Clause); i++)
    if (trail_LitStatusFromAtom(Trail, (TERM)Clause[i], Subst, TRUE) != SET_FALSE)
      return FALSE;
  return TRUE;
}
BOOL csolver_CanSkip(TRAIL trail, TRAILDATA literal, CLAUSE clause, SUBST subst)
{
  unsigned i;
  if (trail_IsPositiveFromData(trail, literal)) {
    for (i = 0; i < clause_GetPremiseLiterals(clause); i++) {
      if (csolver_EqualWithSubst(trail_GetTermstate(trail), trail_AtomFromData(trail, literal), clause_GetAtom(clause, i), subst)) {
        return FALSE;
      }
    }
  } else {
    for (i = 0; i < clause_GetConclusionLiterals(clause); i++) {
      if (csolver_EqualWithSubst(trail_GetTermstate(trail), trail_AtomFromData(trail, literal), clause_GetAtom(clause, clause_GetPremiseLiterals(clause) + i), subst)) {
        return FALSE;
      }
    }
  }
  return TRUE;
}
TERM csolver_RenameVariablesInTerm(TERMSTATE termstate, TERM term, unsigned offset)
{
  unsigned i;
  SYMBOL top;
  ARRAY args;
  TERM result;
  top = term_TopSymbol(term);
  if (symbol_IsVariable(term_GetSymbstate(termstate), top)) {
    return term_Create(termstate, top+offset, NULL);
  }
  args = array_Create(term_GetMemory(termstate), 1);
  for (i = 0; i < term_GetArity(term); i++) {
    args = array_Add(term_GetMemory(termstate), args, (intptr_t)csolver_RenameVariablesInTerm(termstate, (TERM)term[i], offset));
  }
  result = term_Create(termstate, top, args);
  array_Delete(term_GetMemory(termstate), args);
  return result;
}
void csolver_Resolve(TERMSTATE termstate, SUBSTSTATE subststate, SYMBSTATE symbstate, FOLSTATE folstate, TERM literal, CLAUSE conflictclause, SUBST conflictsubst, CLAUSE trailclause, SUBST trailsubst, BOOL trailpositive, CLAUSE *outclause, SUBST *outsubst, ARRAY *cons, ARRAY *prem, ARRAY *conc, ARRAY *parents, CLAUSE markresolved)
{
  TERM unifywith, tmp;
  BOOL addedtoparents;
  TYPING typing;
  unsigned i;
  typing = symbol_CreateVarTyping(term_GetMemory(termstate), clause_GetVariables(conflictclause) + clause_GetVariables(trailclause));
  for (i = 0; i < clause_GetVariables(conflictclause); i++) {
    symbol_SetVarTyping(typing, i, clause_GetVarType(conflictclause, i));
  }
  for (i = 0; i < clause_GetVariables(trailclause); i++) {
    symbol_SetVarTyping(typing, i + clause_GetVariables(conflictclause), clause_GetVarType(trailclause, i));
  }
  unifywith = NULL;
  subst_ContextStart(subststate, symbstate);
  for (i = 0; i < clause_GetPremiseLiterals(conflictclause); i++) {
    if (trailpositive) {
      if (csolver_EqualWithSubst(termstate, literal, clause_GetAtom(conflictclause, i), conflictsubst)) {
        if (markresolved) {
          clause_IncrementResolutions(term_GetMemory(termstate), markresolved, i);
        }
        if (unifywith == NULL) {
          unifywith = clause_GetAtom(conflictclause, i);
          if (array_GetSize(*parents) == 1) {
            *parents = array_Add(term_GetMemory(termstate), *parents, i);
          }
        } else {
          subst_FolTermUnifyIdenticalVars(subststate, folstate, termstate, symbstate, typing, unifywith, clause_GetAtom(conflictclause, i), FALSE);
          *cons = array_Add(term_GetMemory(termstate), *cons, (intptr_t)clause_GetAtom(conflictclause, i));
        }
      } else {
        *prem = array_Add(term_GetMemory(termstate), *prem, (intptr_t)clause_GetAtom(conflictclause, i));
      }
    } else {
      *prem = array_Add(term_GetMemory(termstate), *prem, (intptr_t)clause_GetAtom(conflictclause, i));
    }
  }
  for (i = clause_GetPremiseLiterals(conflictclause); i < clause_GetPremiseLiterals(conflictclause) + clause_GetConclusionLiterals(conflictclause); i++) {
    if (trailpositive) {
      *conc = array_Add(term_GetMemory(termstate), *conc, (intptr_t)clause_GetAtom(conflictclause, i));
    } else {
      if (csolver_EqualWithSubst(termstate, literal, clause_GetAtom(conflictclause, i), conflictsubst)) {
        if (markresolved) {
          clause_IncrementResolutions(term_GetMemory(termstate), markresolved, i);
        }
        if (unifywith == NULL) {
          unifywith = clause_GetAtom(conflictclause, i);
          if (array_GetSize(*parents) == 1) {
            *parents = array_Add(term_GetMemory(termstate), *parents, i);
          }
        } else {
          subst_FolTermUnifyIdenticalVars(subststate, folstate, termstate, symbstate, typing, unifywith, clause_GetAtom(conflictclause, i), FALSE);
          *cons = array_Add(term_GetMemory(termstate), *cons, (intptr_t)clause_GetAtom(conflictclause, i));
        }
      } else {
        *conc = array_Add(term_GetMemory(termstate), *conc, (intptr_t)clause_GetAtom(conflictclause, i));
      }
    }
  }
  *parents = array_Add(term_GetMemory(termstate), *parents, clause_GetId(trailclause));
  addedtoparents = FALSE;
  for (i = 0; i < clause_GetPremiseLiterals(trailclause); i++) {
    if (trailpositive) {
      *prem = array_Add(term_GetMemory(termstate), *prem, (intptr_t)csolver_RenameVariablesInTerm(termstate, clause_GetAtom(trailclause, i), clause_GetVariables(conflictclause)));
    } else {
      if (csolver_EqualWithSubst(termstate, literal, clause_GetAtom(trailclause, i), trailsubst)) {
        clause_IncrementResolutions(term_GetMemory(termstate), trailclause, i);
        if (addedtoparents == FALSE) {
          *parents = array_Add(term_GetMemory(termstate), *parents, i);
          addedtoparents = TRUE;
        }
        tmp = csolver_RenameVariablesInTerm(termstate, clause_GetAtom(trailclause, i), clause_GetVariables(conflictclause));
        subst_FolTermUnifyIdenticalVars(subststate, folstate, termstate, symbstate, typing, unifywith, tmp, FALSE);
        *cons = array_Add(term_GetMemory(termstate), *cons, (intptr_t)tmp);
      } else {
        *prem = array_Add(term_GetMemory(termstate), *prem, (intptr_t)csolver_RenameVariablesInTerm(termstate, clause_GetAtom(trailclause, i), clause_GetVariables(conflictclause)));
      }
    }
  }
  for (i = clause_GetPremiseLiterals(trailclause); i < clause_GetPremiseLiterals(trailclause) + clause_GetConclusionLiterals(trailclause); i++) {
    if (trailpositive) {
      if (csolver_EqualWithSubst(termstate, literal, clause_GetAtom(trailclause, i), trailsubst)) {
        clause_IncrementResolutions(term_GetMemory(termstate), trailclause, i);
        if (addedtoparents == FALSE) {
          *parents = array_Add(term_GetMemory(termstate), *parents, i);
          addedtoparents = TRUE;
        }
        tmp = csolver_RenameVariablesInTerm(termstate, clause_GetAtom(trailclause, i), clause_GetVariables(conflictclause));
        subst_FolTermUnifyIdenticalVars(subststate, folstate, termstate, symbstate, typing, unifywith, tmp, FALSE);
        *cons = array_Add(term_GetMemory(termstate), *cons, (intptr_t)tmp);
      } else {
        *conc = array_Add(term_GetMemory(termstate), *conc, (intptr_t)csolver_RenameVariablesInTerm(termstate, clause_GetAtom(trailclause, i), clause_GetVariables(conflictclause)));
      }
    } else {
      *conc = array_Add(term_GetMemory(termstate), *conc, (intptr_t)csolver_RenameVariablesInTerm(termstate, clause_GetAtom(trailclause, i), clause_GetVariables(conflictclause)));
    }
  }
  for (i = 0; i < array_GetSize(*prem); i++) {
    tmp = subst_ContextFlattenTermApplyToTerm(subststate, termstate, (TERM)array_GetElement(*prem, i));
    term_Delete(termstate, (TERM)array_GetElement(*prem, i));
    array_SetElement(*prem, i, (intptr_t)tmp);
  }
  for (i = 0; i < array_GetSize(*conc); i++) {
    tmp = subst_ContextFlattenTermApplyToTerm(subststate, termstate, (TERM)array_GetElement(*conc, i));
    term_Delete(termstate, (TERM)array_GetElement(*conc, i));
    array_SetElement(*conc, i, (intptr_t)tmp);
  }
  subst_ContextStop(subststate);
  term_Delete(termstate, unifywith);
  for (i = 0; i < array_GetSize(*cons); i++) {
    term_Delete(termstate, (TERM)array_GetElement(*cons, i));
  }
  array_Clean(*cons);
  *outclause = clause_CreateFromLiterals(term_GetMemory(termstate), *cons, *conc, *prem, FALSE, 1337);
  array_Clean(*prem);
  array_Clean(*conc);
  clause_SetVariables(*outclause, clause_GetVariables(conflictclause) + clause_GetVariables(trailclause));
  clause_SetTypes(*outclause, typing);
  *outsubst = subst_Create(term_GetMemory(termstate), clause_GetVariables(*outclause));
  for (i = 0; i < clause_GetVariables(conflictclause); i++) {
    subst_SetValue(*outsubst, i, subst_GetValue(conflictsubst, i));
  }
  for (i = 0; i < clause_GetVariables(trailclause); i++) {
    if (subst_GetValue(trailsubst, i)) {
      subst_SetValue(*outsubst, i + clause_GetVariables(conflictclause), term_Copy(termstate, subst_GetValue(trailsubst, i)));
    }
  }
  for (i = 0; i < clause_GetVariables(conflictclause); i++) {
    subst_SetValue(*outsubst, i, subst_GetValue(conflictsubst, i));
  }
  clause_SharedDelete(term_GetMemory(termstate), termstate, conflictclause);
  subst_Delete(term_GetMemory(termstate), conflictsubst);
  clause_NormalizeVarsAndSubst(subststate, termstate, *outclause, outsubst);
}
ARRAY csolver_EMatching(SHARER sharer, SUBSTSTATE subststate, TERMSTATE termstate, CLAUSE clause, TERM atom)
{
  unsigned i, j, k;
  SYMBOL maxvar;
  BOOL flag;
  ARRAY result, tmpvars;
  SUBST subst;
  TERM copied;
  result = array_Create(term_GetMemory(termstate), 2);
  for (i = 0; i < clause_GetFolLiterals(clause); i++) {
    if (term_IsGround(termstate, clause_GetAtom(clause, i))) {
      continue;
    }
    subst_ContextStart(subststate, term_GetSymbstate(termstate));
    if (subst_TermUnifyIdenticalVarsNoTypes(subststate, termstate, term_GetSymbstate(termstate), clause_GetAtom(clause, i), atom, FALSE)) {
      maxvar = term_MaxVar(termstate, clause_GetAtom(clause, i));
      subst = subst_ContextExtractSubstShallow(subststate, termstate, term_GetSymbstate(termstate), maxvar);
      for (j = 0; j < clause_GetFolLiterals(clause); j++) {
        if (i == j) {
          continue;
        }
        tmpvars = term_ArrayOfVariables(termstate, clause_GetAtom(clause, j));
        if (array_IsEmpty(tmpvars)) {
          array_Delete(term_GetMemory(termstate), tmpvars);
          continue;
        }
        flag = TRUE;
        for (k = 0; flag && k < array_GetSize(tmpvars); k++) {
          if ((SYMBOL)array_GetElement(tmpvars, k) > maxvar) {
            flag = FALSE;
          } else if (term_IsVariable(termstate, subst_GetValue(subst, (SYMBOL)array_GetElement(tmpvars, k)))) {
            flag = FALSE;
          }
        }
        if (flag) {
          copied = term_Copy(termstate, clause_GetAtom(clause, j));
          result = array_Add(term_GetMemory(termstate), result, (intptr_t)sharing_GetSharedTerm(sharer, subst_SubstApplyTerm(termstate, copied, subst, FALSE)));
        }
        array_Delete(term_GetMemory(termstate), tmpvars);
      }
      subst_Delete(term_GetMemory(termstate), subst);
    }
    subst_ContextStop(subststate);
  }
  return result;
}
ARRAY csolver_AddActive(MEMORY mem, ARRAY active, TERM atom, unsigned initial_profit)
{
  term_SetPropagatable(atom, FALSE);
  term_SetActive(atom, TRUE);
  term_SetProfit(atom, initial_profit);
  return array_Add(mem, active, (intptr_t)atom);
}
int csolver_CompareMaxLiterals(POINTER left, POINTER right, POINTER state)
{
  unsigned left_clause_id, left_literal_id, right_clause_id, right_literal_id;
  CLAUSE left_clause, right_clause;
  left_clause_id = *(intptr_t*)left >> 32;
  left_literal_id = *(intptr_t*)left & ((1ll<<32)-1);
  right_clause_id = *(intptr_t*)right >> 32;
  right_literal_id = *(intptr_t*)right & ((1ll<<32)-1);
  left_clause = (CLAUSE)array_GetElement(state_GetClauses((SCLSTATE)state), left_clause_id);
  right_clause = (CLAUSE)array_GetElement(state_GetClauses((SCLSTATE)state), right_clause_id);
  if (clause_GetResolutions(left_clause, left_literal_id) != clause_GetResolutions(right_clause, right_literal_id)) {
    return clause_GetResolutions(left_clause, left_literal_id) > clause_GetResolutions(right_clause, right_literal_id);
  }
  if (clause_GetFolLiterals(left_clause) != clause_GetFolLiterals(right_clause)) {
    return clause_GetFolLiterals(left_clause) > clause_GetFolLiterals(right_clause);
  }
  return clause_GetId(left_clause) > clause_GetId(right_clause);
}
TERM csolver_ApplyContextMakeGround(SUBSTSTATE subststate, SYMBSTATE symbstate, TERMSTATE termstate, TERM term, SYMBOL minconst, unsigned offset)
{
  unsigned i;
  SYMBOL top;
  ARRAY args;
  TERM result;
  top = term_TopSymbol(term);
  if (symbol_IsVariable(symbstate, top)) {
    if (!subst_ContextValueIsMarked(subststate, top + offset) || term_TopSymbol((TERM)subst_ContextGetValue(subststate, top + offset)) == top + offset) {
      return term_Create(termstate, minconst, NULL);
    }
    return csolver_ApplyContextMakeGround(subststate, symbstate, termstate, (TERM)subst_ContextGetValue(subststate, top + offset), minconst, 0);
  }
  if (term_GetArity(term) == 0) {
    return term_Copy(termstate, term);
  }
  args = array_Create(term_GetMemory(termstate), term_GetArity(term));
  for (i = 0; i < term_GetArity(term); i++) {
    args = array_Add(term_GetMemory(termstate), args, (intptr_t)csolver_ApplyContextMakeGround(subststate, symbstate, termstate, term_GetArgument(term, i), minconst, offset));
  }
  result = term_Create(termstate, top, args);
  array_Delete(term_GetMemory(termstate), args);
  return result;
}
void csolver_SetPhasesForInstance(TERMSTATE termstate, CLAUSE clause, TERM baseground, ARRAY instances, ARRAY *active, unsigned *active_pointer)
{
  unsigned i, j;
  TERM tmp;
  for (i = 0; i < clause_GetFolLiterals(clause); i++) {
    tmp = (TERM)array_GetElement(instances, i);
    if (tmp == baseground) {
      continue;
    }
    if (!term_IsActive(tmp)) {
      *active = csolver_AddActive(term_GetMemory(termstate), *active, tmp, 0);
    }
    if (!term_HasPhase(tmp)) {
      term_SetHasPhase(tmp, TRUE);
      if (i < clause_GetPremiseLiterals(clause)) {
        term_SetPropertyPhasePositive(tmp);
      } else {
        term_SetPropertyPhaseNegative(tmp);
      }
      for (j = *active_pointer; j < array_GetSize(*active); j++) {
        if ((TERM)array_GetElement(*active, j) == tmp) {
          array_SetElement(*active, j, (intptr_t)array_GetElement(*active, *active_pointer));
          array_SetElement(*active, *active_pointer, (intptr_t)tmp);
          (*active_pointer)++;
          break;
        }
      }
    }
  }
}
ARRAY csolver_GenerateGroundInstanceIfMaximal(SUBSTSTATE subststate, SYMBSTATE symbstate, TERMSTATE termstate, KBOSTATE kbostate, SHARER sharer, CLAUSE clause, TERM baseground, SYMBOL minconst, unsigned offset, BOOL check_maximal)
{
  unsigned i;
  TERM tmp;
  ARRAY res;
  res = array_Create(term_GetMemory(termstate), clause_GetFolLiterals(clause));
  for (i = 0; i < clause_GetFolLiterals(clause); i++) {
    tmp = sharing_GetSharedTerm(sharer, csolver_ApplyContextMakeGround(subststate, symbstate, termstate, clause_GetAtom(clause, i), minconst, offset));
    res = array_Add(term_GetMemory(termstate), res, (intptr_t)tmp);
    if (tmp == baseground) {
      continue;
    }
    if (check_maximal && kbo_Compare(kbostate, baseground, tmp) == kbo_SMALLER_THAN) {
      array_Delete(term_GetMemory(termstate), res);
      return NULL;
    }
  }
  return res;
}
BOOL csolver_PrepareInstancesForResolution(SCLSTATE state, KBOSTATE kbostate, SHARER sharer, ARRAY *active, ARRAY maxliterals, ARRAY *usedmaxliterals)
{
  unsigned cur, i, j, offset, base_id, test_id, active_pointer;
  ARRAY matched, termstodelete, groundinstances, groundclauses, tmpground;
  CLAUSE base, test;
  SUBST renamesubst;
  TERM renamed_test, baseground;
  srtg_AMergeSortWithState(state_GetMemory(state), maxliterals, maxliterals, maxliterals + array_GetSize(maxliterals) - 1, csolver_CompareMaxLiterals, (POINTER)state);
  for (cur = 0; cur + 1 < array_GetSize(maxliterals); cur++) {
    base = (CLAUSE)array_GetElement(state_GetClauses(state), array_GetElement(maxliterals, cur) >> 32);
    for (i = 0; i < array_GetSize(*usedmaxliterals); i++) {
      if (array_GetElement(*usedmaxliterals, i) == array_GetElement(maxliterals, cur)) {
        base = NULL;
        break;
      }
    }
    if (!base) {
      continue;
    }
    *usedmaxliterals = array_Add(state_GetMemory(state), *usedmaxliterals, array_GetElement(maxliterals, cur));
    base_id = array_GetElement(maxliterals, cur) & ((1ll<<32) - 1);
    offset = clause_GetVariables(base);
    matched = array_Create(state_GetMemory(state), 2);
    termstodelete = array_Create(state_GetMemory(state), 2);
    for (i = cur + 1; i < array_GetSize(maxliterals); i++) {
      test = (CLAUSE)array_GetElement(state_GetClauses(state), array_GetElement(maxliterals, i) >> 32);
      test_id = array_GetElement(maxliterals, i) & ((1ll<<32) - 1);
      if (clause_GetId(base) == clause_GetId(test) || term_TopSymbol(clause_GetAtom(base, base_id)) != term_TopSymbol(clause_GetAtom(test, test_id))) {
        continue;
      }
      if ((base_id < clause_GetPremiseLiterals(base)) == (test_id < clause_GetPremiseLiterals(test))) {
        continue;
      }
      for (j = 0; test && j < array_GetSize(matched); j++) {
        if (array_GetElement(matched, j) == (array_GetElement(maxliterals, i) >> 32)) {
          test = NULL;
        }
      }
      if (!test) {
        continue;
      }
      subst_HotStateUpdate(state_GetMemory(state), state_GetSymbstate(state), state_GetSubststate(state), offset + clause_GetVariables(test));
      renamesubst = subst_Create(state_GetMemory(state), clause_GetVariables(test));
      for (j = 0; j < clause_GetVariables(test); j++) {
        subst_SetValue(renamesubst, (SYMBOL)j, term_Create(state_GetTermstate(state), (SYMBOL)(j + offset), NULL));
      }
      renamed_test = subst_SubstApplyTerm(state_GetTermstate(state), term_Copy(state_GetTermstate(state), clause_GetAtom(test, test_id)), renamesubst, TRUE);
      termstodelete = array_Add(state_GetMemory(state), termstodelete, (intptr_t)renamed_test);
      if (array_IsEmpty(matched)) {
        subst_ContextStart(state_GetSubststate(state), state_GetSymbstate(state));
      } else {
        subst_ContextStackPush(state_GetSubststate(state));
      }
      if ((array_IsEmpty(matched) && subst_TermUnifyIdenticalVarsNoTypes(state_GetSubststate(state), state_GetTermstate(state), state_GetSymbstate(state), clause_GetAtom(base, base_id), renamed_test, TRUE))
          || (!array_IsEmpty(matched) && subst_TermUnifyIdenticalVarsNoTypesStack(state_GetSubststate(state), state_GetTermstate(state), state_GetSymbstate(state), clause_GetAtom(base, base_id), renamed_test, TRUE))) {
        offset += clause_GetVariables(test);
        if (array_IsEmpty(matched)) {
          subst_ContextStackStart(state_GetSubststate(state));
        }
        matched = array_Add(state_GetMemory(state), matched, array_GetElement(maxliterals, i) >> 32);
      } else {
        if (array_IsEmpty(matched)) {
          subst_ContextStop(state_GetSubststate(state));
        } else {
          subst_ContextStackPop(state_GetSubststate(state));
        }
      }
      subst_DeleteWithTerms(state_GetTermstate(state), state_GetMemory(state), renamesubst);
    }
    if (!array_IsEmpty(matched)) {
      subst_ContextFlattenTerms(state_GetSubststate(state), state_GetSymbstate(state), offset);
      baseground = sharing_GetSharedTerm(sharer, csolver_ApplyContextMakeGround(state_GetSubststate(state), state_GetSymbstate(state), state_GetTermstate(state), clause_GetAtom(base, base_id), (SYMBOL)state_GetConstants(state)[0], 0));
      tmpground = csolver_GenerateGroundInstanceIfMaximal(state_GetSubststate(state), state_GetSymbstate(state), state_GetTermstate(state), kbostate, sharer, base, baseground, (SYMBOL)state_GetConstants(state)[0], 0, TRUE);
      if (tmpground) {
        groundinstances = array_Create(state_GetMemory(state), array_GetSize(matched) + 1);
        groundclauses = array_Create(state_GetMemory(state), array_GetSize(matched) + 1);
        groundinstances = array_Add(state_GetMemory(state), groundinstances, (intptr_t)tmpground);
        groundclauses = array_Add(state_GetMemory(state), groundclauses, (intptr_t)base);
        offset = clause_GetVariables(base);
        for (i = 0; i < array_GetSize(matched); i++) {
          test = (CLAUSE)array_GetElement(state_GetClauses(state), array_GetElement(matched, i));
          tmpground = csolver_GenerateGroundInstanceIfMaximal(state_GetSubststate(state), state_GetSymbstate(state), state_GetTermstate(state), kbostate, sharer, test, baseground, (SYMBOL)state_GetConstants(state)[0], offset, FALSE);
          if (tmpground) {
            groundinstances = array_Add(state_GetMemory(state), groundinstances, (intptr_t)tmpground);
            groundclauses = array_Add(state_GetMemory(state), groundclauses, (intptr_t)test);
          }
          offset += clause_GetVariables(test);
        }
        subst_ContextStackStop(state_GetSubststate(state));
        subst_ContextStop(state_GetSubststate(state));
        if (array_GetSize(groundinstances) >= 2) {
          active_pointer = 0;
          for (i = 0; i < array_GetSize(*active); i++) {
            term_SetHasPhase((TERM)array_GetElement(*active, i), FALSE);
          }
          if (!term_IsActive(baseground)) {
            *active = csolver_AddActive(state_GetMemory(state), *active, baseground, 0);
          }
          for (i = 0; i < array_GetSize(groundinstances); i++) {
            csolver_SetPhasesForInstance(state_GetTermstate(state), (CLAUSE)array_GetElement(groundclauses, i), baseground, (ARRAY)array_GetElement(groundinstances, i), active, &active_pointer);
          }
          for (i = active_pointer; i < array_GetSize(*active); i++) {
            if ((TERM)array_GetElement(*active, i) == baseground) {
              array_SetElement(*active, i, array_GetElement(*active, active_pointer));
              array_SetElement(*active, active_pointer, (intptr_t)baseground);
              break;
            }
          }
          for (i = 0; i < array_GetSize(groundinstances); i++) {
            array_Delete(state_GetMemory(state), (ARRAY)array_GetElement(groundinstances, i));
          }
          array_Delete(state_GetMemory(state), groundinstances);
          array_Delete(state_GetMemory(state), groundclauses);
          array_Delete(state_GetMemory(state), matched);
          for (i = 0; i < array_GetSize(termstodelete); i++) {
            term_Delete(state_GetTermstate(state), (TERM)array_GetElement(termstodelete, i));
          }
          array_Delete(state_GetMemory(state), termstodelete);
          return TRUE;
        } else {
          for (i = 0; i < array_GetSize(groundinstances); i++) {
            array_Delete(state_GetMemory(state), (ARRAY)array_GetElement(groundinstances, i));
          }
          array_Delete(state_GetMemory(state), groundinstances);
          array_Delete(state_GetMemory(state), groundclauses);
        }
      } else {
        subst_ContextStackStop(state_GetSubststate(state));
        subst_ContextStop(state_GetSubststate(state));
      }
    }
    array_Delete(state_GetMemory(state), matched);
    for (i = 0; i < array_GetSize(termstodelete); i++) {
      term_Delete(state_GetTermstate(state), (TERM)array_GetElement(termstodelete, i));
    }
    array_Delete(state_GetMemory(state), termstodelete);
  }
  return FALSE;
}
int csolver_CompareByKBO(POINTER term1, POINTER term2, POINTER kbostate)
{
  return kbo_Compare((KBOSTATE)kbostate, *(TERM*)term1, *(TERM*)term2) == kbo_GREATER_THAN;
}
void csolver_SubstituteMinConstantForAllVariables(TERMSTATE termstate, TERM term, SYMBOL minconst)
{
  unsigned i;
  if (symbol_IsVariable(term_GetSymbstate(termstate), term_TopSymbol(term))) {
    term_RplacTop(term, minconst);
    return;
  }
  for (i = 0; i < term_GetArity(term); i++) {
    csolver_SubstituteMinConstantForAllVariables(termstate, term_GetArgument(term, i), minconst);
  }
}
void csolver_UnifyLiteralsGenerateResolutionInstance(SCLSTATE state, SHARER sharer, KBOSTATE kbostate, ARRAY *active, CLAUSE left, CLAUSE right, unsigned left_lit, unsigned right_lit)
{
  unsigned offset, i;
  BOOL good;
  SUBSTSTATE subststate;
  ARRAY rightatoms, rightground, leftground;
  SUBST renamesubst;
  SYMBOL minconst;
  TERM rightrenamed, tmp;
  subststate = state_GetSubststate(state);
  if (term_TopSymbol(clause_GetAtom(left, left_lit)) != term_TopSymbol(clause_GetAtom(right, right_lit))) {
    return;
  }
  subst_StateUpdate(state_GetMemory(state), state_GetSymbstate(state), subststate, clause_GetVariables(left) + clause_GetVariables(right));
  kbo_AdjustMaxVars(kbostate, clause_GetVariables(left) + clause_GetVariables(right));
  offset = clause_GetVariables(left);
  renamesubst = subst_Create(state_GetMemory(state), clause_GetVariables(right));
  for (i = 0; i < clause_GetVariables(right); i++) {
    subst_SetValue(renamesubst, (SYMBOL)i, term_Create(state_GetTermstate(state), (SYMBOL)(i + offset), NULL));
  }
  rightrenamed = subst_SubstApplyTerm(state_GetTermstate(state), term_Copy(state_GetTermstate(state), clause_GetAtom(right, right_lit)), renamesubst, TRUE);
  subst_ContextStart(subststate, state_GetSymbstate(state));
  if (subst_TermUnifyIdenticalVarsNoTypes(state_GetSubststate(state), state_GetTermstate(state), state_GetSymbstate(state), clause_GetAtom(left, left_lit), rightrenamed, TRUE)) {
    rightatoms = array_Create(state_GetMemory(state), clause_GetFolLiterals(right));
    for (i = 0; i < clause_GetFolLiterals(right); i++) {
      if (i != right_lit) {
        rightatoms = array_Add(state_GetMemory(state), rightatoms, (intptr_t)subst_SubstApplyTerm(state_GetTermstate(state), term_Copy(state_GetTermstate(state), clause_GetAtom(right, i)), renamesubst, TRUE));
      } else {
        rightatoms = array_Add(state_GetMemory(state), rightatoms, (intptr_t)rightrenamed);
      }
    }
    minconst = kbo_GetMinConstant(kbostate);
    leftground = array_Create(state_GetMemory(state), clause_GetFolLiterals(left));
    for (i = 0; i < clause_GetFolLiterals(left); i++) {
      leftground = array_Add(state_GetMemory(state), leftground, (intptr_t)subst_ContextFlattenTermApplyToTerm(state_GetSubststate(state), state_GetTermstate(state), clause_GetAtom(left, i)));
      csolver_SubstituteMinConstantForAllVariables(state_GetTermstate(state), (TERM)array_GetElement(leftground, i), minconst);
    }
    rightground = array_Create(state_GetMemory(state), clause_GetFolLiterals(right));
    for (i = 0; i < clause_GetFolLiterals(right); i++) {
      rightground = array_Add(state_GetMemory(state), rightground, (intptr_t)subst_ContextFlattenTermApplyToTerm(state_GetSubststate(state), state_GetTermstate(state), (TERM)array_GetElement(rightatoms, i)));
      csolver_SubstituteMinConstantForAllVariables(state_GetTermstate(state), (TERM)array_GetElement(rightground, i), minconst);
    }
    subst_ContextStop(state_GetSubststate(state));
    good = TRUE;
    for (i = 0; good && i < clause_GetFolLiterals(left); i++) {
      if (i != left_lit && kbo_Compare(kbostate, (TERM)array_GetElement(leftground, i), (TERM)array_GetElement(leftground, left_lit)) == kbo_GREATER_THAN) {
        good = FALSE;
      }
    }
    for (i = 0; good && i < clause_GetFolLiterals(right); i++) {
      if (i != right_lit && kbo_Compare(kbostate, (TERM)array_GetElement(rightground, i), (TERM)array_GetElement(rightground, right_lit)) == kbo_GREATER_THAN) {
        good = FALSE;
      }
    }
    if (good) {
      for (i = 0; i < clause_GetPremiseLiterals(left); i++) {
        tmp = (TERM)array_GetElement(leftground, i);
        tmp = sharing_GetSharedTerm(sharer, tmp);
        if (!term_IsActive(tmp)) {
          *active = csolver_AddActive(state_GetMemory(state), *active, tmp, 0);
          term_SetHasPhase(tmp, TRUE);
          term_SetPropertyPhasePositive(tmp);
        }
      }
      for (i = clause_GetPremiseLiterals(left); i < clause_GetFolLiterals(left); i++) {
        tmp = (TERM)array_GetElement(leftground, i);
        tmp = sharing_GetSharedTerm(sharer, tmp);
        if (!term_IsActive(tmp)) {
          *active = csolver_AddActive(state_GetMemory(state), *active, tmp, 0);
          term_SetHasPhase(tmp, TRUE);
          term_SetPropertyPhaseNegative(tmp);
        }
      }
      for (i = 0; i < clause_GetPremiseLiterals(right); i++) {
        tmp = (TERM)array_GetElement(rightground, i);
        tmp = sharing_GetSharedTerm(sharer, tmp);
        if (!term_IsActive(tmp)) {
          *active = csolver_AddActive(state_GetMemory(state), *active, tmp, 0);
          term_SetHasPhase(tmp, TRUE);
          term_SetPropertyPhasePositive(tmp);
        }
      }
      for (i = clause_GetPremiseLiterals(right); i < clause_GetFolLiterals(right); i++) {
        tmp = (TERM)array_GetElement(rightground, i);
        tmp = sharing_GetSharedTerm(sharer, tmp);
        if (!term_IsActive(tmp)) {
          *active = csolver_AddActive(state_GetMemory(state), *active, tmp, 0);
          term_SetHasPhase(tmp, TRUE);
          term_SetPropertyPhaseNegative(tmp);
        }
      }
    } else {
      for (i = 0; i < array_GetSize(leftground); i++) {
        term_Delete(state_GetTermstate(state), (TERM)array_GetElement(leftground, i));
      }
      for (i = 0; i < array_GetSize(rightground); i++) {
        term_Delete(state_GetTermstate(state), (TERM)array_GetElement(rightground, i));
      }
    }
    array_Delete(state_GetMemory(state), leftground);
    array_Delete(state_GetMemory(state), rightground);
    for (i = 0; i < array_GetSize(rightatoms); i++) {
      term_Delete(state_GetTermstate(state), (TERM)array_GetElement(rightatoms, i));
    }
    array_Delete(state_GetMemory(state), rightatoms);
  } else {
    subst_ContextStop(state_GetSubststate(state));
    term_Delete(state_GetTermstate(state), rightrenamed);
  }
  subst_DeleteWithTerms(state_GetTermstate(state), state_GetMemory(state), renamesubst);
}
BOOL csolver_CompareAtomStreamsByProfit(POINTER atomstream1, POINTER atomstream2)
{
  return groundgen_AtomStreamGetProfit(*(ATOMSTREAM*)atomstream1) < groundgen_AtomStreamGetProfit(*(ATOMSTREAM*)atomstream2);
}
void csolver_FindMaximalLiterals(MEMORY memory, KBOSTATE kbostate, ARRAY *maxliterals, CLAUSE clause, unsigned clauseindex)
{
  unsigned i, j;
  TERM lit, comp;
  BOOL maximal;
  kbo_AdjustMaxVars(kbostate, clause_GetVariables(clause));
  for (i = 0; i < clause_GetFolLiterals(clause); i++) {
    lit = clause_GetAtom(clause, i);
    maximal = TRUE;
    for (j = 0; j < clause_GetFolLiterals(clause); j++) {
      if (i != j) {
        comp = clause_GetAtom(clause, j);
        if (kbo_Compare(kbostate, lit, comp) == kbo_SMALLER_THAN) {
          maximal = FALSE;
          break;
        }
      }
    }
    if (maximal) {
      *maxliterals = array_Add(memory, *maxliterals, (((unsigned long long)clauseindex) << 32) + i);
    }
  }
}
void csolver_Restart(SCLSTATE State, CSTATE Cstate, METASTATE Meta)
{
  while (trail_GetSize(Cstate->trail) > 0) {
    trail_Pop(Cstate->trail);
  }
  trail_SetDl(Cstate->trail, 0);
  trail_CStackAdjustSize(Cstate->trail);
  twfo_Backtrack(Cstate->twfo, Cstate->trail);
  meta_Print(Meta);
#if (SPASS_CHECK && (SPASS_CHECK & SPASS_CHECK_NTWFO))
  ntwfo_Backtrack(State->ntwfo, Cstate->trail);
#endif
}
void csolver_HeuristicsAddClause(SCLSTATE state, GROUNDGEN groundgen, ARRAY *openstreams, ARRAY *active, CLAUSE clause)
{
  unsigned i, j;
  TERM atom;
  ATOMSTREAM atomstream;
  BOOL flag;
  for (i = 0; i < clause_GetFolLiterals(clause); i++) {
    atom = clause_GetAtom(clause, i);
    atomstream = groundgen_CreateAtomStream(groundgen, atom);
    flag = TRUE;
    for (j = 0; flag && j < array_GetSize(*openstreams); j++) {
      if (groundgen_AtomStreamGetAtom((ATOMSTREAM)array_GetElement(*openstreams, j)) == groundgen_AtomStreamGetAtom(atomstream)) {
        flag = FALSE;
      }
    }
    if (flag) {
      *openstreams = array_Add(state_GetMemory(state), *openstreams, (intptr_t)atomstream);
      atom = groundgen_AtomStreamGetNext(groundgen, atomstream);
      if (!term_IsActive(atom)) {
        *active = csolver_AddActive(state_GetMemory(state), *active, atom, 0);
      }
    } else {
      groundgen_DeleteAtomStream(groundgen, atomstream);
    }
  }
}
BOOL csolver_IsTheoryConflict(SCLSTATE State, INST Conflict)
{
  return (Conflict == state_GetInstance(State));
}
BOOL csolver_Timeout(SCLSTATE State)
{
  return (state_GetSeconds(State) != -1 && (float)state_GetSeconds(State) <= clock_GetSeconds(state_GetClockOverall(State), clock_OVERALL));
}
BOOL csolver_HandleTheoryConflict(SCLSTATE State, METASTATE Meta, CSTATE Cstate, INST Conflict)
{
  CLAUSE newclause;
  CCBS_STATE congrstate;
  TRAIL trail;
  TWFO twfo;
  TERMSTATE termstate;
  newclause = inst_GetOrigin(Conflict);
  congrstate = state_GetCongrstate(State);
  trail = cstate_GetTrail(Cstate);
  twfo = cstate_GetTwfo(Cstate);
  termstate = state_GetTermstate(State);
  switch (inst_GetFirstWatched(Conflict)) {
  case THEORY_CONFLICT_PROP_UNSAT:
    return TRUE;
  case THEORY_CONFLICT_LEARN_CLAUSE:
    congrbs_Backtrack(congrstate, trail_GetSize(trail));
    state_AddClause(State, newclause);
    if (clause_GetFolLiterals(newclause) == 0) {
      state_SetEmptyClause(State, newclause);
      return TRUE;
    }
    array_Clean(twfo_GetProps(twfo));
    twfo_LearnNewClause(twfo, trail, newclause, TRUE, 0);
    break;
  default:
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s:", __func__);
    misc_ErrorReport("\n Theory number %u unknown.", inst_GetFirstWatched(Conflict));
    misc_FinishErrorReport();
  }
  meta_UpdateLearnedClause(State, Meta, trail, newclause, (SUBST)NULL);
  csolver_Restart(State, Cstate, Meta);
  return FALSE;
}
BOOL csolver_HandleFOLConflict(SCLSTATE State, METASTATE Meta, CSTATE Cstate, INST Conflict)
{
  CLAUSE clause,newclause,learntclause;
  SUBST subst,newsubst;
  TERMSTATE termstate;
  SYMBSTATE symbstate;
  SUBSTSTATE subststate;
  FOLSTATE folstate;
  SHARER sharer;
  MEMORY mem;
  TRAIL trail;
  TWFO twfo;
  ARRAY parents,conc,prem,cons;
  BOOL emptyclause, backtracked;
  TRAILDATA literal;
  unsigned oldtrailsize;
  TERM newterm;
  unsigned i, level;
  CCBS_STATE congrstate;
  ABSTR abstr;
  PCLAUSE pclause;
  emptyclause = FALSE;
  backtracked = FALSE;
  termstate = state_GetTermstate(State);
  symbstate = state_GetSymbstate(State);
  subststate = state_GetSubststate(State);
  congrstate = state_GetCongrstate(State);
  folstate = state_GetFolstate(State);
  sharer = state_GetSharer(State);
  mem = state_GetMemory(State);
  clause = clause_Copy(termstate, inst_GetOrigin(Conflict), TRUE);
  subst = subst_CopyWitTerms(termstate, inst_GetSubst(Conflict), subst_NumberOfVariables(inst_GetSubst(Conflict)));
  trail = cstate_GetTrail(Cstate);
  twfo = cstate_GetTwfo(Cstate);
  parents = cstate_GetParents(Cstate);
  conc = cstate_GetConc(Cstate);
  prem = cstate_GetPrem(Cstate);
  cons = cstate_GetCons(Cstate);
  abstr = cstate_GetAbstr(Cstate);
  if (abstr) {
    pclause = abstr_FOLClauseToPropClause(abstr, clause, subst);
    abstr_AddClause(abstr, pclause, TRUE);
  }
  parents = array_Add(mem, parents, clause_GetId(clause));
  while (!backtracked && !emptyclause && clause_GetFolLiterals(clause) > 0) {
    literal = trail_GetDataFromTrailPos(trail, trail_GetSize(trail)-1);
    if (csolver_CanSkip(trail, literal, clause, subst)) {
      if (trail_LitIsDecision(trail, trail_Pop(trail))) {
 trail_SetDl(trail, trail_GetDl(trail) - 1);
 trail_CStackAdjustSize(trail);
      }
    }
    else {
      if (trail_LitIsDecision(trail, literal)) {
 oldtrailsize = trail_GetSize(trail);
 state_IncLearnedClauses(State);
 meta_UpdateLearnedClause(State, Meta, trail, clause, subst);
 subst_DeleteWithTerms(termstate, mem, subst);
 clause_NormalizeVars(subststate, termstate, clause);
 learntclause = clause;
 clause = NULL;
 clause_RemoveDuplicateLiterals(termstate, learntclause, FALSE);
 if (condense_Condense(State, learntclause)) {
   state_IncCondensations(State);
 }
 clause_SetId(learntclause, state_GetNextIncrementId(State));
 for (i = 0; i < array_GetSize(parents); i += 2) {
   clause_AddParent(mem, learntclause, array_GetElement(parents, i), array_GetElement(parents, i+1) + 1);
 }
 array_Clean(parents);
 fred_ExhaustiveForwardSubRes(State, learntclause, FALSE);
 fred_InsertClauseToIndex(State, learntclause);
 for (i = 0; i < clause_GetFolLiterals(learntclause); i++) {
   newterm = sharing_GetSharedTerm(sharer, clause_GetAtom(learntclause, i));
   learntclause[i] = (uintptr_t) newterm;
 }
 if (clause_GetFolLiterals(learntclause) == 0) {
   emptyclause = TRUE;
   state_SetEmptyClause(State, learntclause);
   state_AddClause(State, learntclause);
 }
 else {
#if (SPASS_CHECK && (SPASS_CHECK & SPASS_CHECK_NTWFO))
          unsigned int backtracked_trail_size = ntwfo_ComputeBacktrackLevelLearnNewClause(State->ntwfo, trail, learntclause);
#endif
   level = twfo_ComputeBacktrackLevelLearnNewClause(twfo, trail, learntclause);
#if (SPASS_CHECK && (SPASS_CHECK & SPASS_CHECK_NTWFO))
          if (backtracked_trail_size != trail_GetSize(trail)) {
            misc_StartErrorReport();
            misc_ErrorReport("In %s: TWFO and NTWFO computed different backtracking points. Trail sizes after BT: TWFO: %u, NTWFO: %u.\n", __func__, trail_GetSize(trail), backtracked_trail_size);
            misc_FinishErrorReport();
          }
#endif
   state_AddClause(State, learntclause);
   state_AddLearnedClause(State, learntclause);
   backtracked = TRUE;
   meta_UpdateBacktrack(State, Meta, trail, twfo, level);
   if (state_IsBSREqProblem(State))
     congrbs_Backtrack(congrstate, oldtrailsize - trail_GetSize(trail));
 }
      }
      else {
 state_IncResolutions(State);
 if ((clause_GetVariables(clause) + clause_GetVariables(trail_LitReasonFromData(trail, literal)))*2 > (unsigned)symbol_GetMaxVars(symbstate)) {
   subst_StateUpdate(mem, symbstate, subststate, (clause_GetVariables(clause) + clause_GetVariables(trail_LitReasonFromData(trail, literal)))*2);
 }
 csolver_Resolve(termstate, subststate, symbstate, folstate, trail_AtomFromData(trail, literal), clause, subst, trail_LitReasonFromData(trail, literal), trail_LitSubstFromData(trail, literal), trail_IsPositiveFromData(trail, literal), &newclause, &newsubst, &cons, &prem, &conc, &parents, (array_GetSize(parents) == 1? inst_GetOrigin(Conflict) : NULL));
 clause = newclause;
 subst = newsubst;
 meta_UpdateNewResolution(State, Meta, trail_AtomFromData(trail, literal), clause, subst, parents);
#ifdef SPASS_CHECK
 if (!csolver_ClauseIsFalse(trail, clause, subst)) {
   misc_StartErrorReport();
   misc_ErrorReport("In %s: Clause not false with respect to trail: ", __func__);
   clause_Print(termstate, clause); printf(" "); subst_Print(termstate, symbstate,subst);
   misc_ErrorReport("\n");
   trail_Print(trail);
   misc_ErrorReport("\n");
   misc_FinishErrorReport();
 }
#endif
      }
    }
  }
  if (!backtracked && !emptyclause) {
    subst_DeleteWithTerms(termstate, mem, subst);
    learntclause = clause_CreateGeneric(mem, 0, 0);
    clause_SetId(learntclause, state_GetNextIncrementId(State));
    for (i = 0; i < array_GetSize(parents); i += 2) {
      clause_AddParent(mem, learntclause, array_GetElement(parents, i), array_GetElement(parents, i+1) + 1);
    }
    state_AddClause(State, learntclause);
    clause_Delete(mem, termstate, clause);
    state_SetEmptyClause(State, learntclause);
    emptyclause = TRUE;
  }
  cstate_SetParents(Cstate, parents);
  cstate_SetConc(Cstate, conc);
  cstate_SetPrem(Cstate, prem);
  cstate_SetCons(Cstate, cons);
  return emptyclause;
}
INST csolver_ExtendTrail(SCLSTATE State, METASTATE Meta, CSTATE Cstate, TERM Atom)
{
  INST conflict;
  CLAUSE newclause;
  PRLITS_ANNO_LIT prlit;
  CCBS_STATE congrstate;
  FOLSTATE folstate;
  SUBST subst;
  PCLAUSE pclause;
  ABSTR abstr;
  conflict = (INST)NULL;
  congrstate = state_GetCongrstate(State);
  folstate = state_GetFolstate(State);
  subst = (SUBST)NULL;
  abstr = cstate_GetAbstr(Cstate);
  if (abstr)
    abstr_MappingAdd(abstr, Atom);
  if (term_IsPropagatable(Atom)) {
    state_IncPropagations(State);
    prlit = (PRLITS_ANNO_LIT)prlits_GetStack((PRLITS)twfo_GetPrlit(Cstate->twfo))[term_GetPrLitIndex(Atom)];
    subst = csolver_CreateMatchingSubst(state_GetTermstate(State), state_GetSubststate(State), Atom, clause_GetAtom(prlits_GetAnnoLitOriginClause(prlit), prlits_GetAnnoLitPosition(prlit)), prlits_GetAnnoLitSubst(prlit));
    trail_Add(Cstate->trail, Atom, prlits_GetAnnoLitOriginClause(prlit), subst, prlits_GetAnnoLitPosition(prlit), prlits_GetAnnoLitValue(prlit), TRUE);
    if (abstr) {
      pclause = abstr_FOLClauseToPropClause(abstr, prlits_GetAnnoLitOriginClause(prlit), subst);
      abstr_AddClause(abstr, pclause, TRUE);
    }
    conflict = twfo_NewLiteralOnTrail(Cstate->twfo, Cstate->trail);
  }
  else {
    state_IncDecisions(State);
    if (!term_HasPhase(Atom)) {
      term_SetPropertyPhasePositive(Atom);
      term_SetHasPhase(Atom, TRUE);
    }
    trail_NewDl(Cstate->trail);
    if (term_PropertyPhasePositive(Atom)) {
      trail_Add(Cstate->trail, Atom, NULL, NULL, 0, TRUE, FALSE);
    } else {
      trail_Add(Cstate->trail, Atom, NULL, NULL, 0, FALSE, FALSE);
    }
    conflict = twfo_NewLiteralOnTrail(Cstate->twfo, Cstate->trail);
    if (conflict) {
#ifdef SPASS_CHECK
      trail_Print(Cstate->trail);
      twfo_PrintPropLiterals(Cstate->twfo);
      meta_Print(Meta);
      printf("\n Instance:" ); inst_Print(state_GetTermstate(State), conflict);
      printf("\n Atom:" ); term_PrintPrefix(state_GetTermstate(State), Atom); printf("\n");
#endif
      misc_StartErrorReport();
      misc_ErrorReport("In %s: Decide should not enable the direct application of Conflict\n", __func__);
      misc_FinishErrorReport();
    }
  }
#if (SPASS_CHECK && (SPASS_CHECK & SPASS_CHECK_NTWFO))
  BOOL ntwfo_conflict = ntwfo_NewLiteralOnTrail(State->ntwfo, Cstate->trail);
  if ((conflict != NULL) != ntwfo_conflict) {
    misc_StartErrorReport();
    misc_ErrorReport("In %s: TWFO and NTWFO conflict information differs after decision. TWFO says %s, NTWFO says %s.\n", __func__, conflict != NULL ? "TRUE" : "FALSE", ntwfo_conflict ? "TRUE" : "FALSE");
    misc_FinishErrorReport();
  }
  if (FALSE && !conflict) {
    csolver_IsNTWFOConsistent(State, Cstate->trail, Cstate->twfo, State->ntwfo);
  }
#endif
  if (!conflict) {
    if (state_IsBSREqProblem(State)) {
      congrbs_BacktrackPush(congrstate);
      if (!congrbs_AssertLiteral(congrstate, Atom, folstate, term_PropertyPhasePositive(Atom))) {
 newclause = congrbs_CreateClauseFromConflict(congrstate, state_GetNextIncrementId(State));
 clause_MarkTautology(newclause, TRUE);
 fred_ExhaustiveForwardSubRes(State, newclause, TRUE);
 fred_InsertClauseToIndex(State, newclause);
 state_AddClause(State, newclause);
 conflict = state_GetInstance(State);
 inst_SetOrigin(conflict, newclause);
 inst_SetFirstWatched(conflict, 1);
      }
    }
  }
  return conflict;
}
BOOL csolver_CheckSAT(SCLSTATE State, METASTATE Meta, CSTATE Cstate)
{
  return FALSE;
}
void csolver_HandleRestart(SCLSTATE State, METASTATE Meta, CSTATE Cstate)
{
  TRAIL Trail;
  TWFO Twfo;
  Trail = Cstate->trail;
  Twfo = Cstate->twfo;
  while (trail_GetSize(Trail) > 0) {
    trail_Pop(Trail);
  }
  trail_SetDl(Trail, 0);
  trail_CStackAdjustSize(Trail);
  twfo_Backtrack(Twfo, Trail);
#if (SPASS_CHECK && (SPASS_CHECK & SPASS_CHECK_NTWFO))
  ntwfo_Backtrack(State->ntwfo, Trail);
#endif
  twfo_RefreshInstances(Twfo);
  twfo_FactorizeRefreshedInstances(Twfo, Trail);
  meta_UpdateRestart(State, Meta, Trail, Twfo);
  return;
}
void csolver_HandleReduction(SCLSTATE State, METASTATE Meta, CSTATE Cstate, ARRAY Reductions)
{
  ABSTR abstr;
  abstr = cstate_GetAbstr(Cstate);
  meta_UpdateReduction(State, Meta, Cstate->trail, Cstate->twfo);
  if (abstr && array_GetSize(Reductions) > 0) {
    abstr_HandleReduction(abstr, Reductions);
  }
  return;
}
void csolver_Solve(SCLSTATE State, KBOSTATE KBOState, BOOL *Finish, METAHEUR Mode)
{
  MEMORY mem;
  SYMBSTATE symbstate;
  TERMSTATE termstate;
  SHARER sharer;
  FOLSTATE folstate;
  SUBSTSTATE subststate;
  TRAIL trail;
  TWFO twfo;
  TERM atom;
  INST conflict;
  BOOL learned_empty_clause, detected_SAT, give_UP, saturated;
  METASTATE meta;
  CSTATE cstate;
  ARRAY reductions;
  ABSTR abstr;
  mem = state_GetMemory(State);
  symbstate = state_GetSymbstate(State);
  termstate = state_GetTermstate(State);
  folstate = state_GetFolstate(State);
  subststate = state_GetSubststate(State);
  sharer = state_GetSharer(State);
  cstate = csolver_Create(mem, subststate, termstate, symbstate, folstate, sharer, State);
  trail = cstate_GetTrail(cstate);
  twfo = cstate_GetTwfo(cstate);
  meta = meta_Create(State, twfo, Mode);
  state_SetAbstraction(State, meta_PerformSATAbstraction(State,meta));
  csolver_UpdateAbstraction(mem, cstate, termstate, symbstate, folstate, sharer, state_GetAbstraction(State));
  abstr = cstate_GetAbstr(cstate);
  printf("\n\n%% === Starting SPASS-SCL-FOL A Little Less Naive, considering %u atoms initially. Used heuristic: %s ===\n\n", meta_GetNumberActiveAtoms(meta),
         Mode == META_LCL ? "lcl" : Mode == META_LMODEL_GROW ? "lmodel_grow" : "unknown_heuristic");
  learned_empty_clause = FALSE;
  detected_SAT = FALSE;
  give_UP = FALSE;
  saturated = FALSE;
  conflict = (INST)NULL;
  if (abstr)
    abstr_AddAllGroundClauses(abstr, state_GetClauses(State));
  while (!csolver_Timeout(State) && !learned_empty_clause && !detected_SAT && !give_UP) {
    if (conflict) {
      if (csolver_IsTheoryConflict(State,conflict)) {
 learned_empty_clause = csolver_HandleTheoryConflict(State,meta,cstate,conflict);
      }
      else {
 learned_empty_clause = csolver_HandleFOLConflict(State,meta,cstate,conflict);
      }
      conflict = (INST)NULL;
    }
    else {
      if (meta_PerformReduction(State,meta)) {
        reductions = cstate_GetReductions(cstate);
 csolver_HandleRestart(State,meta,cstate);
 learned_empty_clause = fred_BackReduction(State,trail,twfo,&reductions);
 csolver_HandleReduction(State,meta,cstate,reductions);
 cstate_SetReductions(cstate, reductions);
#if (SPASS_CHECK && (SPASS_CHECK & SPASS_CHECK_NTWFO))
        csolver_IsNTWFOConsistent(State, trail, twfo, State->ntwfo);
#endif
      }
      if (!learned_empty_clause) {
 atom = meta_SelectNextTrailLiteral(State,meta,trail,twfo);
 if (atom) {
   conflict = csolver_ExtendTrail(State,meta,cstate,atom);
 }
 else {
   saturated = TRUE;
 }
 if (saturated) {
   give_UP = meta_ExtendActiveLiterals(State,meta,trail,twfo,&detected_SAT);
   if (!give_UP && !detected_SAT) {
     reductions = cstate_GetReductions(cstate);
     csolver_HandleRestart(State,meta,cstate);
     learned_empty_clause = fred_BackReduction(State,trail,twfo,&reductions);
     csolver_HandleReduction(State,meta,cstate,reductions);
     cstate_SetReductions(cstate, reductions);
   }
   saturated = FALSE;
 }
 if (!detected_SAT && !learned_empty_clause && meta_PerformSATTest(State,meta)) {
   if (abstr && !abstr_RunSATSolver(abstr)) {
     conflict = state_GetInstance(State);
     clause_SetId(abstr_GetEmptyClause(abstr), state_GetNextIncrementId(State));
            clause_MarkPropAbstrTautology(abstr_GetEmptyClause(abstr), TRUE);
     state_SetEmptyClause(State, abstr_GetEmptyClause(abstr));
     state_AddClause(State, abstr_GetEmptyClause(abstr));
     printf("\n%% === SAT Conflict found: ");
     clause_Print(termstate, abstr_GetEmptyClause(abstr));
     inst_SetFirstWatchedTheoryConflict(conflict, THEORY_CONFLICT_PROP_UNSAT);
   }
 }
      }
    }
  }
  if (learned_empty_clause) {
    printf("\n\n%% SZS status %s\n", state_GetSZSUnsatStatus(State));
  }
  else {
    if (detected_SAT)
      printf("\n\n%% SZS status %s\n", state_GetSZSSatStatus(State));
    else {
      if (give_UP)
 printf("\n\n%% SZS status GaveUp\n");
      else
 printf("\n\n%% SZS status Timeout\n");
    }
  }
  state_PrintStatistics(State);
#if (SPASS_CHECK && (SPASS_CHECK & SPASS_CHECK_NTWFO))
  ntwfo_Delete(State->ntwfo);
#endif
  meta_Delete(meta);
  csolver_Delete(mem, cstate);
}
#if (SPASS_CHECK && (SPASS_CHECK & SPASS_CHECK_NTWFO))
void csolver_IsNTWFOConsistent(SCLSTATE state, TRAIL trail, TWFO twfo, NTWFO ntwfo)
{
  unsigned i, j;
  BOOL flag1, flag2;
  TERM lit;
  PRLITS prlits, nprlits;
  prlits = (PRLITS)twfo_GetPrlit(twfo);
  nprlits = ntwfo_GetPrlits(ntwfo);
  ARRAY twfo_lits = array_Create(state_GetMemory(state), 10);
  ARRAY ntwfo_lits = array_Create(state_GetMemory(state), 10);
  for(i = 0; i < array_GetSize(prlits_GetStack(prlits)); i++) {
    lit = prlits_GetAnnoLitAtom((PRLITS_ANNO_LIT)prlits_GetStack(prlits)[i]);
    twfo_lits = array_Add(state_GetMemory(state), twfo_lits, (intptr_t)lit);
  }
  for(i = 0; i < array_GetSize(prlits_GetStack(nprlits)); i++) {
    lit = prlits_GetAnnoLitAtom((PRLITS_ANNO_LIT)prlits_GetStack(nprlits)[i]);
    ntwfo_lits = array_Add(state_GetMemory(state), ntwfo_lits, (intptr_t)lit);
  }
  for(i = 0; i < array_GetSize(twfo_lits); i++) {
    lit = (TERM)array_GetElement(twfo_lits, i);
    flag1 = FALSE;
    for(j = 0; j < array_GetSize(ntwfo_lits); j++) {
      if (term_Equal(state_GetTermstate(state), lit, (TERM)array_GetElement(ntwfo_lits, j))) {
        flag1 = TRUE;
        break;
      }
      subst_ContextStart(state_GetSubststate(state), state_GetSymbstate(state));
      if(subst_FolTermMatchTerms(state_GetSubststate(state), state_GetSymbstate(state), state_GetTermstate(state), state_GetFolstate(state), (TERM) array_GetElement(ntwfo_lits, j), NULL, lit, NULL)) {
        subst_ContextStop(state_GetSubststate(state));
        flag1 = TRUE;
        break;
      }
      subst_ContextStop(state_GetSubststate(state));
    }
    if (!flag1) {
      misc_StartErrorReport();
      misc_ErrorReport("In %s: Literal in TWFO not found in NTWFO.\n", __func__);
      trail_Print(trail);
      printf("\nThe missing literal is: ");
      term_PrettyPrint(state_GetTermstate(state), lit);
      printf("\n");
      printf("NTWFO literals:\n");
      for(i = 0; i < array_GetSize(ntwfo_lits); i++) {
        lit = (TERM)array_GetElement(ntwfo_lits, i);
        term_PrettyPrint(state_GetTermstate(state), lit);
        printf("\n");
      }
      printf("\n");
      printf("TWFO literals:\n");
      for(i = 0; i < array_GetSize(twfo_lits); i++) {
        lit = (TERM)array_GetElement(twfo_lits, i);
        term_PrettyPrint(state_GetTermstate(state), lit);
        printf("\n");
      }
      misc_FinishErrorReport();
    }
  }
  for(i = 0; i < array_GetSize(ntwfo_lits); i++) {
    lit = (TERM)array_GetElement(ntwfo_lits, i);
    flag2 = FALSE;
    for(j = 0; j < array_GetSize(twfo_lits); j++) {
      if (term_Equal(state_GetTermstate(state), lit, (TERM)array_GetElement(twfo_lits, j))) {
        flag2 = TRUE;
        break;
      }
    }
    if (!flag2) {
      prlits_Print(prlits, state_GetTermstate(state), TRUE);
      misc_StartErrorReport();
      misc_ErrorReport("In %s: Literal in NTWFO not found in TWFO.\n", __func__);
      term_PrettyPrint(state_GetTermstate(state), lit);
      misc_FinishErrorReport();
    }
  }
  array_Delete(state_GetMemory(state), twfo_lits);
  array_Delete(state_GetMemory(state), ntwfo_lits);
}
#endif
