#ifdef DOC_BUILD_INTERNAL
#endif
#include "hlmodgrow.h"
BOOL hlmdg_HeuristicCompare(POINTER Atom1, POINTER Atom2) {
  return (term_GetProfit(*(TERM*)Atom1) > term_GetProfit(*(TERM*)Atom2) ||
   (term_GetProfit(*(TERM*)Atom1) == term_GetProfit(*(TERM*)Atom2) && term_Size(*(TERM*)Atom1) < term_Size(*(TERM*)Atom2)));
}
BOOL hlmdg_HeuristicCompareNot(POINTER Atom1, POINTER Atom2) {
  return (term_GetProfit(*(TERM*)Atom1) < term_GetProfit(*(TERM*)Atom2) ||
    (term_GetProfit(*(TERM*)Atom1) == term_GetProfit(*(TERM*)Atom2) && term_Size(*(TERM*)Atom1) >= term_Size(*(TERM*)Atom2)));
}
BOOL hlmdg_ClauseCompare(POINTER Clause1, POINTER Clause2) {
  return (clause_GetFolLiterals(*(CLAUSE*)Clause1) > clause_GetFolLiterals(*(CLAUSE*)Clause2));
}
HLMDGSTATE hlmdg_Create(SCLSTATE State, TWFO Twfo)
{
  unsigned i, j, k, l, pindex, size, max;
  int inputlits;
  ARRAY clauses, candidates, active;
  TERM atom, newatom,otheratom,copyatom;
  SYMBOL iconst;
  SHARER sharer;
  DISTRN poslits;
  CLAUSE clause, pclause;
  MEMORY mem;
  TERMSTATE termstate;
  SYMBSTATE symbstate;
  SUBSTSTATE subststate;
  HLMDGSTATE result;
  clauses = state_GetClauses(State);
  mem = state_GetMemory(State);
  srtg_AMergeSortCompare(mem, clauses, clauses, clauses+(array_GetSize(clauses)-1), (BOOL (*)(POINTER,POINTER))hlmdg_ClauseCompare);
  result = memory_Malloc(mem, sizeof(HLMDG_NODE));
  result->twfo = Twfo;
  result->active = array_Create(mem, array_GetSize(clauses));
  result->inactive = array_Create(mem, array_GetSize(clauses));
  result->proplits = array_Create(mem, array_GetSize(clauses));
  result->extraproplits = array_Create(mem, 10);
  result->nonground = array_Create(mem, 10);
  result->trailhits = array_Create(mem, 200);
  result->inflits = array_Create(mem, 20);
  result->ireduce = FALSE;
  result->lmodstate = lmodel_Init(State);
  result->iconst = (SYMBOL)array_GetElement(state_GetConstants(State),0);
  result->heur = 2;
  result->backtrack = 0;
  result->forget = 0;
  result->extraprops = state_GetNumberInputLits(State);
  result->keep = state_GetNumberInputLits(State)/2;
  result->lastid = state_GetId(State);
  result->sattest = 10;
  result->infbonus = 0;
  sharer = state_GetSharer(State);
  iconst = result->iconst;
  max = 0;
  active = result->active;
  poslits = state_GetPoslits(State);
  inputlits = (int)state_GetNumberInputLits(State);
  candidates = array_Create(mem, inputlits/2);
  termstate = state_GetTermstate(State);
  symbstate = state_GetSymbstate(State);
  subststate = state_GetSubststate(State);
  for (i=0;i<array_GetSize(clauses) && inputlits > 0; i++) {
    clause = (CLAUSE)clauses[i];
    for (j=0; j<clause_GetPremiseLiterals(clause) && inputlits > 0; j++) {
      atom = clause_GetAtom(clause, j);
      array_Clean(candidates);
      candidates = distrn_SearchUnifiables(mem, poslits, termstate, atom, &candidates);
      for (k=0; k < array_GetSize(candidates) && inputlits > 0; k++) {
 pclause = (CLAUSE)array_PairFirst((ARRAY)candidates[k]);
 pindex = (unsigned)array_PairSecond((ARRAY)candidates[k]);
 otheratom = clause_GetAtom(pclause, pindex);
 subst_ContextStart(subststate, symbstate);
 if (subst_TermUnifyDisjointVarsNoTypes(subststate, termstate, symbstate, atom, otheratom, TRUE)) {
   subst_ContextStop(subststate);
   otheratom = term_RenameVariablesInTerm(termstate, otheratom, clause_GetVariables(clause));
   subst_ContextStart(subststate, symbstate);
   if (!subst_TermUnifyIdenticalVarsNoTypes(subststate, termstate, symbstate, atom, otheratom, FALSE)) {
     misc_StartUserErrorReport();
     misc_UserErrorReport("%s: Terms not unifiable.",__func__);
     misc_FinishUserErrorReport();
   }
   subst_ContextFlattenTerms(subststate, symbstate, clause_GetVariables(clause)+clause_GetVariables(pclause));
   for (l=0; l<clause_GetFolLiterals(clause); l++) {
     newatom = subst_ContextTermApplyToTerm(subststate, termstate, clause_GetAtom(clause, l));
     term_GroundTermConstant(state_GetTermstate(State), newatom, iconst);
     newatom = sharing_GetSharedTerm(sharer, newatom);
     if (clause_GetFolLiterals(clause) == 1)
       term_SetProfit(newatom,2);
     if (!term_IsActive(newatom)) {
       term_SetActive(newatom, TRUE);
       term_SetHasPhase(newatom, TRUE);
       if (clause_LiteralIsPositive(clause, l))
  term_SetPropertyPhaseNegative(newatom);
       else
  term_SetPropertyPhasePositive(newatom);
       inputlits--;
       active = array_Add(mem, active, (intptr_t)newatom);
       size = term_Size(newatom);
       if (size > max)
  max = size;
     }
   }
   for (l=0; l<clause_GetFolLiterals(pclause); l++) {
     copyatom = term_RenameVariablesInTerm(termstate, otheratom, clause_GetVariables(clause));
     newatom = subst_ContextTermApplyToTerm(subststate, termstate, copyatom);
     term_Delete(termstate, copyatom);
     term_GroundTermConstant(state_GetTermstate(State), newatom, iconst);
     newatom = sharing_GetSharedTerm(sharer, newatom);
     if (clause_GetFolLiterals(pclause) == 1)
       term_SetProfit(newatom,2);
     if (!term_IsActive(newatom)) {
       term_SetActive(newatom, TRUE);
       term_SetHasPhase(newatom, TRUE);
       if (clause_LiteralIsPositive(pclause, l))
  term_SetPropertyPhaseNegative(newatom);
       else
  term_SetPropertyPhasePositive(newatom);
       inputlits--;
       active = array_Add(mem, active, (intptr_t)newatom);
       size = term_Size(newatom);
       if (size > max)
  max = size;
     }
   }
   term_Delete(termstate, otheratom);
 }
 subst_ContextStop(subststate);
      }
    }
  }
  for (i=0;i<array_GetSize(active);i++) {
    if (term_GetProfit((TERM)active[i]) != 2)
      term_SetProfit((TERM)active[i],1);
    term_SetPersAtom((TERM)active[i], TRUE);
  }
  srtg_AMergeSortCompare(mem, active, active, active+(array_GetSize(active)-1), hlmdg_HeuristicCompare);
  result->active = active;
  result->max = max;
  array_Delete(mem, candidates);
  return result;
}
void hlmdg_Delete(MEMORY Mem, HLMDGSTATE Hlmdg)
{
  array_Delete(Mem, Hlmdg->active);
  array_Delete(Mem, Hlmdg->inactive);
  array_Delete(Mem, Hlmdg->proplits);
  array_Delete(Mem, Hlmdg->nonground);
  array_Delete(Mem, Hlmdg->extraproplits);
  array_Delete(Mem, Hlmdg->trailhits);
  array_Delete(Mem, Hlmdg->inflits);
  lmodel_Free(Hlmdg->lmodstate);
  memory_Free(Mem, Hlmdg, sizeof(HLMDG_NODE));
}
unsigned hlmdg_ActiveAtoms(HLMDGSTATE Hlmdg)
{
  return array_GetSize(Hlmdg->active);
}
ARRAY hlmdg_ActivateCompPropAtom(MEMORY Mem, ARRAY Active, TERM Atom, unsigned Index, PRLITS_ANNO_LIT Prlit)
{
  if (!term_IsActive(Atom) ) {
    term_SetActive(Atom,TRUE);
    term_SetProfit(Atom, 1);
    Active = array_Add(Mem, Active, (intptr_t)Atom);
  }
  if (!term_IsPropagatable(Atom)) {
    term_SetHasPhase(Atom, TRUE);
    term_SetPrLitIndex(Atom, Index);
    term_PropertySetPhase(Atom, prlits_GetAnnoLitValue(Prlit));
    term_SetPropagatable(Atom, TRUE);
  }
  return Active;
}
void hlmdg_UpdatePropLits(SCLSTATE State, HLMDGSTATE Hlmdg, TRAIL Trail, TWFO Twfo)
{
  ARRAY active,prlits,proplits,nonground;
  PRLITS_ANNO_LIT prlit,pprlit;
  TERM atom,patom;
  unsigned i,j,start;
  MEMORY mem;
  TERMSTATE termstate;
  SHARER sharer;
  BOOL conflict;
  mem = state_GetMemory(State);
  active = Hlmdg->active;
  proplits = Hlmdg->proplits;
  nonground = Hlmdg->nonground;
  prlits = prlits_GetStack((PRLITS)twfo_GetPrlit(Twfo));
  termstate = state_GetTermstate(State);
  sharer = state_GetSharer(State);
  conflict = FALSE;
  if (array_GetSize(prlits)>array_GetSize(proplits)) {
    start = array_GetSize(proplits);
    for (i=start;i<array_GetSize(prlits);i++) {
      prlit = (PRLITS_ANNO_LIT)prlits[i];
      atom = prlits_GetAnnoLitAtom(prlit);
      if (term_Size(atom) <= Hlmdg->max && (term_IsActive(atom) || term_IsPropagatable(atom) || Hlmdg->extraprops > 0)) {
 if (!term_IsPropagatable(atom)) {
   if (!term_IsGround(termstate,atom)) {
     term_SetHasPhase(atom, TRUE);
     term_PropertySetPhase(atom, prlits_GetAnnoLitValue(prlit));
     term_SetPropagatable(atom, TRUE);
     term_SetPrLitIndex(atom, i);
     nonground = array_Add(mem, nonground, (intptr_t)atom);
     atom = term_Copy(termstate, atom);
     term_GroundTermConstant(termstate, atom, Hlmdg->iconst);
     atom = sharing_GetSharedTerm(sharer, atom);
   }
#ifdef SPASS_CHECK
   if (!sharing_IsShared(atom)) {
     misc_StartUserErrorReport();
     misc_UserErrorReport("%s: Prlit ground atom not shared.",__func__);
     misc_FinishUserErrorReport();
   }
#endif
   if (!term_IsActive(atom) && Hlmdg->extraprops > 0) {
     Hlmdg->extraprops--;
     term_SetActive(atom,TRUE);
     term_SetProfit(atom, 1);
     active = array_Add(mem, active, (intptr_t)atom);
   }
   if (!term_IsPropagatable(atom)) {
     term_SetHasPhase(atom, TRUE);
     term_PropertySetPhase(atom, prlits_GetAnnoLitValue(prlit));
     term_SetPropagatable(atom, TRUE);
     term_SetPrLitIndex(atom, i);
   }
   else {
     if (term_PropertyPhasePositive(atom) != prlits_GetAnnoLitValue(prlit)) {
       term_SetProfit(atom, ++(Hlmdg->heur));
       conflict = TRUE;
     }
#ifdef SPASS_CHECK
     if (term_GetPrLitIndex(atom) == -1) {
       misc_StartUserErrorReport();
       misc_UserErrorReport("%s: Propagatable Literal at Index -1.",__func__);
       misc_FinishUserErrorReport();
     }
#endif
   }
 }
 else {
   if (term_HasPhase(atom) && term_PropertyPhasePositive(atom) != prlits_GetAnnoLitValue(prlit)) {
     if (term_IsGround(termstate, atom)) {
       if (!term_IsActive(atom)) {
  term_SetActive(atom,TRUE);
  active = array_Add(mem, active, (intptr_t)atom);
       }
       term_SetProfit(atom, ++(Hlmdg->heur));
       conflict = TRUE;
     }
   }
 }
      }
      else {
 if (term_IsPropagatable(atom) && prlits_GetAnnoLitValue(prlit) != prlits_GetAnnoLitValue((PRLITS_ANNO_LIT)prlits[term_GetPrLitIndex(atom)]) && term_IsGround(termstate, atom)) {
     active = hlmdg_ActivateCompPropAtom(mem, active, atom, i, prlit);
     term_SetProfit(atom, ++(Hlmdg->heur));
     conflict = TRUE;
   }
 else {
   if (!term_IsPropagatable(atom)) {
     term_SetPropagatable(atom, TRUE);
     term_SetPrLitIndex(atom, i);
     if (term_IsGround(termstate,atom)) {
       term_SetHasPhase(atom, TRUE);
       term_PropertySetPhase(atom, prlits_GetAnnoLitValue(prlit));
     }
   }
 }
 if (!term_IsGround(termstate,atom) && term_Size(atom) <= Hlmdg->max)
   nonground = array_Add(mem, nonground, (intptr_t)atom);
      }
      proplits = array_Push(mem, proplits, (intptr_t)atom);
      if (term_IsActive(atom) && Hlmdg->infbonus==0)
 term_SetPersAtom(atom, TRUE);
    }
    if (!conflict) {
      for (i=start;i<array_GetSize(prlits) && !conflict;i++) {
 prlit = (PRLITS_ANNO_LIT)prlits[i];
 atom = prlits_GetAnnoLitAtom(prlit);
 for (j=0;j<i&& !conflict;j++) {
   pprlit = (PRLITS_ANNO_LIT)prlits[j];
   patom = prlits_GetAnnoLitAtom(pprlit);
   if (prlits_GetAnnoLitValue(prlit) != prlits_GetAnnoLitValue(pprlit) && term_TopSymbol(atom) == term_TopSymbol(patom) && (!term_IsGround(termstate,atom) || !term_IsGround(termstate,patom))) {
     subst_ContextStart(state_GetSubststate(State), state_GetSymbstate(State));
     if (subst_TermUnifyDisjointVarsNoTypes(state_GetSubststate(State), termstate, state_GetSymbstate(State), patom, atom, TRUE)) {
       if (term_IsGround(termstate,atom)) {
  active = hlmdg_ActivateCompPropAtom(mem, active, atom, i, prlit);
  term_SetProfit(atom, ++(Hlmdg->heur));
  conflict = TRUE;
       }
       else {
  if (term_IsGround(termstate,patom)) {
    active = hlmdg_ActivateCompPropAtom(mem, active, patom, j, pprlit);
    term_SetProfit(patom, ++(Hlmdg->heur));
    conflict = TRUE;
  }
  else {
    subst_ContextStop(state_GetSubststate(State));
    atom = term_RenameVariablesInTerm(termstate, atom, clause_GetVariables(prlits_GetAnnoLitOriginClause(pprlit)));
    subst_ContextStart(state_GetSubststate(State), state_GetSymbstate(State));
    subst_TermUnifyIdenticalVarsNoTypes(state_GetSubststate(State), termstate, state_GetSymbstate(State), atom, patom, FALSE);
    patom = subst_ContextFlattenTermApplyToTerm(state_GetSubststate(State), termstate, atom);
    term_Delete(termstate, atom);
    term_GroundTermConstant(state_GetTermstate(State), patom, Hlmdg->iconst);
    patom = sharing_GetSharedTerm(sharer, patom);
    active = hlmdg_ActivateCompPropAtom(mem, active, patom, i, prlit);
    Hlmdg->extraproplits = array_Push(mem, Hlmdg->extraproplits, (intptr_t)patom);
    term_SetProfit(patom, ++(Hlmdg->heur));
    conflict = TRUE;
  }
       }
     }
     subst_ContextStop(state_GetSubststate(State));
   }
 }
      }
    }
    srtg_AMergeSortCompare(mem, active, active, active+(array_GetSize(active)-1), hlmdg_HeuristicCompare);
    Hlmdg->nonground = nonground;
    Hlmdg->active = active;
    Hlmdg->proplits = proplits;
  }
#ifdef SPASS_CHECK
  if (array_GetSize(proplits) != array_GetSize(prlits)) {
    twfo_PrintPropLiterals(Twfo);
    hlmdg_Print(State,Hlmdg);
    misc_StartErrorReport();
    misc_UserErrorReport("\n%s: Propagatable Literal mismatch Prlits ",__func__);
    misc_FinishErrorReport();
  }
  for (i=0;i<array_GetSize(proplits);i++) {
    if (term_GetPrLitIndex((TERM)proplits[i]) != -1) {
      if (term_IsGround(state_GetTermstate(State), prlits_GetAnnoLitAtom((PRLITS_ANNO_LIT)prlits[term_GetPrLitIndex((TERM)proplits[i])])) &&
   (!term_Equal(state_GetTermstate(State), (TERM)proplits[i], prlits_GetAnnoLitAtom((PRLITS_ANNO_LIT)prlits[term_GetPrLitIndex((TERM)proplits[i])])) ||
    !term_IsPropagatable(prlits_GetAnnoLitAtom((PRLITS_ANNO_LIT)prlits[term_GetPrLitIndex((TERM)proplits[i])]))))
 {
 misc_StartUserErrorReport();
 misc_UserErrorReport("\n%s: Propagatable Literal mismatch at Index %u ",__func__, i);
 printf("\n UAtom: "); term_PrintPrefix(state_GetTermstate(State), (TERM)proplits[i]); printf(":%d", term_GetPrLitIndex((TERM)proplits[i]));
 printf("\n\n   UPrlits:  %lu ", array_GetSize(prlits));
 for (i=0;i<array_GetSize(prlits);i++) {
   term_PrintPrefix(state_GetTermstate(State), prlits_GetAnnoLitAtom((PRLITS_ANNO_LIT)prlits[i]));
   printf(":%u ", i);
 }
 misc_FinishErrorReport();
      }
    }
    else {
 misc_StartUserErrorReport();
 misc_UserErrorReport("\n%s: Propagatable Literal without Index %u ",__func__, i);
 printf("\n UAtom: %lu ", array_GetSize(proplits)); term_PrintPrefix(state_GetTermstate(State), (TERM)proplits[i]);
 twfo_PrintPropLiterals(Twfo);
 misc_FinishUserErrorReport();
    }
  }
#endif
}
TERM hlmdg_NextInferenceLiteral(SCLSTATE State, HLMDGSTATE Hlmdg, TRAIL Trail, TWFO Twfo)
{
  ARRAY stuple,active,inflits,nonground;
  CLAUSE clause1, clause2;
  TERM atom, patom;
  unsigned lit1, lit2,maxvar,i,id1,id2;
  TERMSTATE termstate;
  SYMBSTATE symbstate;
  SUBSTSTATE sstate;
  SUBST subst;
  char cstring[8];
  MEMORY mem;
  SHARER sharer;
  mem = state_GetMemory(State);
  termstate = state_GetTermstate(State);
  symbstate = state_GetSymbstate(State);
  sstate = state_GetSubststate(State);
  active = Hlmdg->active;
  inflits = Hlmdg->inflits;
  nonground = Hlmdg->nonground;
  sharer = state_GetSharer(State);
  atom = (TERM)NULL;
  Hlmdg->extraprops = 0;
  while (atom == (TERM)NULL && array_GetSize(Hlmdg->inflits) == 0 && array_GetSize(state_GetInferences(State)) > 0) {
    while (array_GetSize(Hlmdg->inflits) == 0 && array_GetSize(state_GetInferences(State)) > 0) {
      stuple = (ARRAY)array_Pop(state_GetInferences(State));
      clause1 = (CLAUSE)array_STupleFirst(stuple);
      lit1 = (unsigned)array_STupleSecond(stuple);
      id1 = (unsigned)array_STupleFifth(stuple);
      clause2 = clause_Copy(termstate, (CLAUSE)array_STupleThird(stuple), TRUE);
      lit2 = (unsigned)array_STupleFourth(stuple);
      id2 = (unsigned)array_STupleSixth(stuple);
      array_STupleDelete(mem, stuple);
      if (clause_GetId(clause1) == id1 && clause_GetId(clause2) == id2) {
 clause_RenameVars(sstate, termstate, clause2, clause_GetVariables(clause1));
 subst_ContextStart(sstate, symbstate);
 if (!subst_TermUnifyIdenticalVarsNoTypes(sstate, termstate, symbstate, clause_GetAtom(clause1, lit1), clause_GetAtom(clause2,lit2), TRUE)) {
   misc_StartErrorReport();
   misc_ErrorReport("\n%s: Literals of set inferences should be unifiable!",__func__);
   misc_FinishErrorReport();
 }
 maxvar = clause_GetVariables(clause1)+clause_GetVariables(clause2);
 subst = subst_ContextFlattenExtractSubst(sstate, termstate, symbstate, maxvar);
 subst_ContextStop(sstate);
 if (array_GetSize(state_GetPConstants(State)) <= maxvar) {
   for (i=array_GetSize(state_GetPConstants(State)); i<=maxvar*2; i++) {
     sprintf(cstring, "pc%u", i);
     state_AddPConstant(State, symbol_CreateConstant(symbstate, fol_TypeTop(state_GetFolstate(State)), cstring));
   }
 }
 for(i=0;i<clause_GetFolLiterals(clause1);i++) {
   if (i != lit1) {
     atom = subst_SubstApplyTerm(termstate, term_Copy(termstate, clause_GetAtom(clause1,i)), subst, TRUE);
     term_GroundTermConstants(termstate, atom, state_GetPConstants(State));
     atom = sharing_GetSharedTerm(sharer, atom);
     term_SetHasPhase(atom, TRUE);
     if (clause_LiteralIsPositive(clause1, i))
       term_SetPropertyPhaseNegative(atom);
     else
       term_SetPropertyPhasePositive(atom);
     term_SetProfit(atom, Hlmdg->heur);
     inflits = array_Add(mem, inflits, (intptr_t)atom);
   }
   else {
     atom = subst_SubstApplyTerm(termstate, term_Copy(termstate, clause_GetAtom(clause1,i)), subst, TRUE);
     term_GroundTermConstants(termstate, atom, state_GetPConstants(State));
     atom = sharing_GetSharedTerm(sharer, atom);
     term_SetHasPhase(atom, TRUE);
     if (clause_LiteralIsPositive(clause1, i))
       term_SetPropertyPhasePositive(atom);
     else
       term_SetPropertyPhaseNegative(atom);
     term_SetProfit(atom, Hlmdg->heur);
     inflits = array_Add(mem, inflits, (intptr_t)atom);
     atom = (TERM)inflits[0];
     inflits[0] = inflits[array_GetSize(inflits)-1];
     inflits[array_GetSize(inflits)-1] = (intptr_t)atom;
   }
 }
 for(i=0;i<clause_GetFolLiterals(clause2);i++) {
   if (i != lit2) {
     atom = subst_SubstApplyTerm(termstate, term_Copy(termstate,clause_GetAtom(clause2,i)), subst, TRUE);
     term_GroundTermConstants(termstate, atom, state_GetPConstants(State));
     atom = sharing_GetSharedTerm(sharer, atom);
     term_SetHasPhase(atom, TRUE);
     if (clause_LiteralIsPositive(clause2, i))
       term_SetPropertyPhaseNegative(atom);
     else
       term_SetPropertyPhasePositive(atom);
     term_SetProfit(atom, Hlmdg->heur);
     inflits = array_Add(mem, inflits, (intptr_t)atom);
   }
 }
 subst_DeleteWithTerms(termstate, mem, subst);
 Hlmdg->inflits = inflits;
 Hlmdg->active = active;
      }
      clause_Delete(mem, termstate, clause2);
      atom = (TERM)NULL;
    }
  }
  if (array_GetSize(inflits) > 0) {
      atom = (TERM)array_Pop(inflits);
      for (i=0; i < array_GetSize(nonground); i++) {
 patom = (TERM)nonground[i];
 if (term_TopSymbol(patom) == term_TopSymbol(atom)) {
   subst_ContextStart(sstate, symbstate);
   if (subst_FolTermMatchTerms(sstate, symbstate, termstate, state_GetFolstate(State), patom, NULL, atom, NULL)) {
     i = array_GetSize(nonground);
     array_SetSize(inflits,0);
     atom = (TERM)NULL;
     Hlmdg->ireduce = TRUE;
   }
   subst_ContextStop(sstate);
 }
      }
    }
  if (array_GetSize(Hlmdg->inflits) == 0)
    Hlmdg->ireduce = TRUE;
  return atom;
}
TERM hlmdg_NextTrailLiteral(SCLSTATE State, HLMDGSTATE Hlmdg, TRAIL Trail, TWFO Twfo)
{
  TERM atom,patom;
  unsigned i;
  MEMORY mem;
  ARRAY nonground;
  mem = state_GetMemory(State);
  hlmdg_UpdatePropLits(State, Hlmdg, Trail, Twfo);
  if (array_GetSize(state_GetInferences(State)) > 0 || array_GetSize(Hlmdg->inflits) > 0) {
    if (Hlmdg->infbonus == 0)
      Hlmdg->infbonus = Hlmdg->heur++;
    atom = hlmdg_NextInferenceLiteral(State, Hlmdg, Trail, Twfo);
    if (atom != (TERM)NULL) {
      return atom;
    }
  }
  nonground = Hlmdg->nonground;
  if (array_GetSize(Hlmdg->active)>0) {
    atom = (TERM)array_Pop(Hlmdg->active);
    Hlmdg->inactive = array_Push(mem, Hlmdg->inactive, (intptr_t)atom);
    for (i=0; i < array_GetSize(nonground) && !term_IsPropagatable(atom); i++) {
      patom = (TERM)nonground[i];
      if (term_TopSymbol(patom) == term_TopSymbol(atom)) {
 subst_ContextStart(state_GetSubststate(State), state_GetSymbstate(State));
 if (subst_FolTermMatchTerms(state_GetSubststate(State), state_GetSymbstate(State), state_GetTermstate(State), state_GetFolstate(State), patom, NULL, atom, NULL)) {
   term_SetHasPhase(atom, TRUE);
   term_PropertySetPhase(atom, term_PropertyPhasePositive(patom));
   term_SetPropagatable(atom, TRUE);
   term_SetPrLitIndex(atom, term_GetPrLitIndex(patom));
   Hlmdg->extraproplits = array_Push(mem, Hlmdg->extraproplits, (intptr_t)atom);
 }
 subst_ContextStop(state_GetSubststate(State));
      }
    }
    return atom;
  }
  return (TERM)NULL;
}
void hlmdg_UpdateBacktrack(SCLSTATE State, HLMDGSTATE Hlmdg, TRAIL Trail, TWFO Twfo, unsigned Level)
{
  int i,j;
  unsigned sactive;
  ARRAY proplits,inactive, active,nonground,extraproplits;
  MEMORY mem;
  TERM atom;
  mem = state_GetMemory(State);
  inactive = Hlmdg->inactive;
  active = Hlmdg->active;
  nonground = Hlmdg->nonground;
  Hlmdg->backtrack++;
  for(i=array_GetSize(inactive); i > (int)trail_GetSize(Trail); i--) {
    atom = (TERM)array_Pop(inactive);
    if (term_Size(atom) > Hlmdg->max || (Hlmdg->infbonus > 0 && term_GetProfit(atom) > Hlmdg->infbonus && !term_IsPersAtom(atom))) {
      term_SetActive(atom, FALSE);
    }
    else
      active = array_Add(mem, active, (intptr_t)atom);
  }
  if (Hlmdg->infbonus>0) {
    j = array_GetSize(active)-1;
    i = 0;
    while (i<=j) {
      atom = (TERM)active[i];
      if (term_GetProfit(atom) > Hlmdg->infbonus && !term_IsPersAtom(atom)) {
 active[i] = active[j];
 term_SetActive(atom, FALSE);
 j--;
      }
      else
 i++;
    }
    array_SetSize(active, j+1);
  }
  Hlmdg->active = active;
  proplits = Hlmdg->proplits;
  extraproplits = Hlmdg->extraproplits;
  j = 0;
  i = array_GetSize(nonground) - 1;
  while (i >= 0) {
    if (term_GetPrLitIndex((TERM)nonground[i]) >= (int)Level)
      j++;
    else
      i = 0;
    i--;
  }
  for(i=array_GetSize(proplits); i > (int)Level; i--) {
    atom = (TERM)array_Pop(proplits);
    if (term_GetPrLitIndex(atom) >= (int)Level) {
      term_SetPropagatable(atom, FALSE);
      term_SetPrLitIndex(atom, -1);
    }
  }
  while (j >0) {
    atom = (TERM)array_Pop(nonground);
    term_SetPropagatable(atom, FALSE);
    term_SetPrLitIndex(atom, -1);
    j--;
  }
  i=0;
  while (i<array_GetSize(extraproplits)) {
    atom = (TERM)extraproplits[i];
    if (term_GetPrLitIndex(atom) >= (int)Level || term_GetPrLitIndex(atom) == -1) {
      term_SetPropagatable(atom, FALSE);
      term_SetPrLitIndex(atom, -1);
      array_RemoveAtIndex(extraproplits, i);
    }
    else
      i++;
  }
  if (FALSE && Level == 0 && Hlmdg->forget>0) {
    sactive = (unsigned)array_GetSize(active);
    if (sactive > state_GetNumberInputLits(State) && sactive > Hlmdg->keep) {
      Hlmdg->forget = (sactive < Hlmdg->keep ? 0 : misc_Min(Hlmdg->forget, sactive - Hlmdg->keep));
      if (Hlmdg->forget >0) {
 srtg_AMergeSortCompare(mem, active, active, active+(sactive-1), (BOOL (*)(POINTER,POINTER))hlmdg_HeuristicCompareNot);
#ifdef SPASS_CHECK
 if (Hlmdg->forget>array_GetSize(active)) {
   misc_StartErrorReport();
   misc_ErrorReport("%s: Too few literals in active to be all forgotten %u %u",__func__, Hlmdg->forget, array_GetSize(active));
   misc_FinishErrorReport();
 }
#endif
 printf("\n%% === Forgetting: %u out of %u and %u to be kept", Hlmdg->forget, (unsigned)array_GetSize(active), Hlmdg->keep);
 while (Hlmdg->forget>0) {
   Hlmdg->forget--;
   atom = (TERM)array_Pop(active);
   term_SetActive(atom, FALSE);
   term_SetPropagatable(atom, FALSE);
   term_SetPrLitIndex(atom, -1);
 }
      }
      Hlmdg->keep +=2;
      Hlmdg->forget = 0;
    }
  }
  hlmdg_UpdatePropLits(State, Hlmdg, Trail, Twfo);
  proplits = Hlmdg->proplits;
#ifdef SPASS_CHECK
  for (i=0;i<(int)array_GetSize(proplits);i++) {
    if (term_GetPrLitIndex((TERM)proplits[i]) != -1) {
      if (!term_Equal(state_GetTermstate(State), (TERM)proplits[i], prlits_GetAnnoLitAtom((PRLITS_ANNO_LIT)(prlits_GetStack((PRLITS)twfo_GetPrlit(Twfo)))[term_GetPrLitIndex((TERM)proplits[i])])) &&
   term_IsGround(state_GetTermstate(State), prlits_GetAnnoLitAtom((PRLITS_ANNO_LIT)(prlits_GetStack((PRLITS)twfo_GetPrlit(Twfo)))[term_GetPrLitIndex((TERM)proplits[i])]))) {
 misc_StartUserErrorReport();
 misc_UserErrorReport("%s: Propagatable Literal mismatch at Index %u",__func__, i);
 printf("\n BAtom: "); term_PrintPrefix(state_GetTermstate(State), (TERM)proplits[i]); printf(":%d", term_GetPrLitIndex((TERM)proplits[i]));
 printf("\n\n   UPrlits:  %lu ", array_GetSize((prlits_GetStack((PRLITS)twfo_GetPrlit(Twfo)))));
 for (i=0;i<array_GetSize((prlits_GetStack((PRLITS)twfo_GetPrlit(Twfo))));i++) {
   term_PrintPrefix(state_GetTermstate(State), prlits_GetAnnoLitAtom((PRLITS_ANNO_LIT)(prlits_GetStack((PRLITS)twfo_GetPrlit(Twfo)))[i]));
   printf(":%u ", i);
 }
 misc_FinishUserErrorReport();
      }
    }
  }
#endif
  if (array_GetSize(state_GetInferences(State)) > 0 && array_GetSize(Hlmdg->inflits) > 0 && Hlmdg->infbonus != 0 && Level == 0)
    Hlmdg->infbonus = 0;
}
void hlmdg_UpdateNewResolution(SCLSTATE State, HLMDGSTATE Hlmdg, TERM Atom, CLAUSE Resolvent, SUBST Grounding, ARRAY Parents)
{
  term_SetProfit(Atom, ++(Hlmdg->heur));
}
void hlmdg_UpdateRestart(SCLSTATE State, HLMDGSTATE Hlmdg, TRAIL Trail, TWFO Twfo)
{
  hlmdg_UpdateBacktrack(State, Hlmdg, Trail, Twfo, 0);
}
void hlmdg_UpdateReduction(SCLSTATE State, HLMDGSTATE Hlmdg, TRAIL Trail, TWFO Twfo)
{
  ARRAY proplits, extraproplits, nonground;
  unsigned i;
  TERM atom;
  proplits = Hlmdg->proplits;
  extraproplits = Hlmdg->extraproplits;
  nonground = Hlmdg->nonground;
  for(i=0; i< array_GetSize(proplits); i++) {
    atom = (TERM)proplits[i];
    term_SetPropagatable(atom, FALSE);
    term_SetPrLitIndex(atom, -1);
  }
  array_SetSize(proplits, 0);
  for(i=0; i< array_GetSize(nonground); i++) {
    atom = (TERM)nonground[i];
    term_SetPropagatable(atom, FALSE);
    term_SetPrLitIndex(atom, -1);
  }
  array_SetSize(nonground,0);
  for(i=0; i< array_GetSize(extraproplits); i++) {
    atom = (TERM)extraproplits[i];
    term_SetPropagatable(atom, FALSE);
    term_SetPrLitIndex(atom, -1);
    array_RemoveAtIndex(extraproplits, i);
  }
  array_SetSize(extraproplits,0);
  hlmdg_UpdatePropLits(State, Hlmdg, Trail, Twfo);
  Hlmdg->backtrack = 0;
}
BOOL hlmdg_PerformReduction(SCLSTATE State, HLMDGSTATE Hlmdg)
{
  if (array_GetSize(Hlmdg->inflits)>0)
    return FALSE;
  if (Hlmdg->ireduce) {
    Hlmdg->ireduce = FALSE;
    return TRUE;
  }
  if (Hlmdg->backtrack > 10) {
    Hlmdg->backtrack = 0;
    return TRUE;
  }
  return FALSE;
}
void hlmdg_UpdateLearnedClause(SCLSTATE State, HLMDGSTATE Hlmdg, TRAIL Trail, CLAUSE Clause, SUBST Subst)
{
  unsigned i;
  TERM atom;
  ++(Hlmdg->heur);
  for (i=0;i<clause_GetFolLiterals(Clause);i++) {
    atom = trail_AtomFromData(Trail, trail_AtomData(Trail, (TERM)Clause[i], Subst));
    term_SetProfit(atom, Hlmdg->heur);
  }
}
BOOL hlmdg_ExtendActiveLiterals(SCLSTATE State, HLMDGSTATE Hlmdg, TRAIL Trail, TWFO Twfo, BOOL *DetectSAT)
{
  unsigned i,j,k;
  LMODEL model;
  LMODSTATE lmodstate;
  CLAUSE clause;
  SUBST subst;
  TERM atom,patom;
  TERMSTATE termstate;
  ARRAY active;
  MEMORY mem;
  SHARER sharer;
  ARRAY inferences;
#ifdef SPASS_CHECK
  trail_IsConsistent(Trail);
#endif
  termstate = state_GetTermstate(State);
  sharer = state_GetSharer(State);
  mem = state_GetMemory(State);
  lmodstate = Hlmdg->lmodstate;
  active = Hlmdg->active;
  *DetectSAT = TRUE;
  model = lmodel_BuildFromTrail(lmodstate, Trail, lmodel_GreedyComplete());
  Hlmdg->heur++;
  for (i=0; i<array_GetSize(state_GetClauses(State));++i) {
    clause = (CLAUSE)array_GetElement(state_GetClauses(State), i);
    subst = lmodel_CheckSPASSClauseLowestDepth(lmodstate, model, clause);
    if (subst) {
      *DetectSAT = FALSE;
      for (j = 0; j < clause_GetFolLiterals(clause); j++) {
 atom = term_Copy(termstate, clause_GetAtom(clause, j));
 atom = subst_SubstApplyTerm(termstate, atom, subst, TRUE);
 if (!term_IsGround(termstate, atom)) {
   term_GroundTermConstant(termstate, atom, Hlmdg->iconst);
 }
 atom = sharing_GetSharedTerm(sharer, atom);
 ARRAY prlits;
 PRLITS_ANNO_LIT prlit;
 unsigned pindex;
 BOOL nohit;
 CLAUSE pclause;
 nohit = TRUE;
 prlits = prlits_GetStack((PRLITS)twfo_GetPrlit(Twfo));
 inferences = state_GetInferences(State);
 for (k=0;k<array_GetSize(prlits)&&nohit;k++) {
   prlit = (PRLITS_ANNO_LIT)prlits[k];
   patom = prlits_GetAnnoLitAtom(prlit);
   if (patom == atom && prlits_GetAnnoLitValue(prlit) != (j>=clause_GetPremiseLiterals(clause))) {
     nohit = FALSE;
     pclause = prlits_GetAnnoLitOriginClause(prlit);
     pindex = prlits_GetAnnoLitPosition(prlit);
     if (clause_GetId(pclause) > clause_GetId(clause))
       inferences = array_Add(mem, inferences, (intptr_t)array_STupleCreate(mem, (intptr_t)pclause, pindex, (intptr_t)clause, j, clause_GetId(pclause), clause_GetId(clause)));
     else
       inferences = array_Add(mem, inferences, (intptr_t)array_STupleCreate(mem, (intptr_t)clause, j, (intptr_t)pclause, pindex, clause_GetId(clause), clause_GetId(pclause)));
   }
   state_SetInferences(State,inferences);
 }
 if (!term_IsActive(atom)) {
   term_SetActive(atom,TRUE);
   term_SetHasPhase(atom, TRUE);
   term_SetPersAtom(atom, TRUE);
   active = array_Add(mem, active, (intptr_t)atom);
   if (term_Size(atom)>Hlmdg->max)
     Hlmdg->max = term_Size(atom);
 }
 term_SetProfit(atom, Hlmdg->heur);
 term_PropertySetPhase(atom, (j<clause_GetPremiseLiterals(clause)));
      }
      subst_DeleteWithTerms(termstate, mem, subst);
    }
  }
  inferences = state_GetInferences(State);
  lmodel_Delete(lmodstate, model);
  Hlmdg->active = active;
  if (*DetectSAT) {
    printf("\n\n%% Linear Model Building succeeded.");
    printf("\n%% SZS status %s\n", state_GetSZSSatStatus(State));
  }
  else {
    if (state_GetId(State) == Hlmdg->lastid)
      Hlmdg->forget = 0;
    else {
      Hlmdg->forget = array_GetSize(Hlmdg->inactive) * 0.3;
      Hlmdg->lastid = state_GetId(State);
    }
    Hlmdg->extraprops = 0;
  }
  return FALSE;
}
unsigned hlmdg_MissingPropLits(HLMDGSTATE Hlmdg, TWFO Twfo, TRAIL Trail)
{
  unsigned result,i;
  TERM atom;
  ARRAY prlits;
  TERMSTATE termstate;
  SHARER sharer;
  result = 0;
  prlits = prlits_GetStack(twfo_GetPrlit(Twfo));
  termstate = twfo_GetTermstate(Twfo);
  sharer = twfo_Sharer(Twfo);
  for (i=0;i<array_GetSize(prlits);i++) {
    atom = prlits_GetAnnoLitAtom((PRLITS_ANNO_LIT)prlits[i]);
    if (!term_IsGround(termstate, atom)) {
      atom = term_Copy(termstate, atom);
      term_GroundTermConstant(termstate, atom, Hlmdg->iconst);
      atom = sharing_GetSharedTerm(sharer, atom);
    }
    if (!trail_AtomData(Trail, atom, NULL))
      result++;
  }
  return result;
}
BOOL hlmdg_PerformSATTest(SCLSTATE State, HLMDGSTATE Hlmdg)
{
  if (Hlmdg->sattest == 0) {
    Hlmdg->sattest = 10;
    return TRUE;
  }
  Hlmdg->sattest--;
  return FALSE;
}
BOOL hlmdg_PerformSATAbstraction(SCLSTATE State, HLMDGSTATE Hlmdg)
{
  return TRUE;
}
void hlmdg_Print(SCLSTATE State, HLMDGSTATE Hlmdg)
{
  unsigned i;
  ARRAY proplits,inactive, active,nonground,extraproplits;
  extraproplits = Hlmdg->extraproplits;
  proplits = Hlmdg->proplits;
  inactive = Hlmdg->inactive;
  active = Hlmdg->active;
  nonground = Hlmdg->nonground;
  printf("\n\n%% ==LModGrow MaxSize: %u ExtraPropLits: %u MaxHeur: %u ", Hlmdg->max, Hlmdg->extraprops, Hlmdg->heur);
  printf("\n\n%% Proplits: %u ", (unsigned)array_GetSize(proplits));
  for (i=0;i<array_GetSize(proplits);i++) {
    if (!term_PropertyPhasePositive((TERM)proplits[i]))
      printf("~");
    term_PrintPrefix(state_GetTermstate(State), (TERM)proplits[i]);
    printf(":P%d:I%d ", term_IsPropagatable((TERM)proplits[i]), term_GetPrLitIndex((TERM)proplits[i]));
  }
  printf("\n\n%% ExtraProplits: %u ", (unsigned)array_GetSize(extraproplits));
  for (i=0;i<array_GetSize(extraproplits);i++) {
    if (!term_PropertyPhasePositive((TERM)extraproplits[i]))
      printf("~");
    term_PrintPrefix(state_GetTermstate(State), (TERM)extraproplits[i]);
    printf(":P%d:I%d ", term_IsPropagatable((TERM)extraproplits[i]), term_GetPrLitIndex((TERM)extraproplits[i]) );
  }
  printf("\n\n%% Nonground: %u ", (unsigned)array_GetSize(nonground));
  for (i=0;i<array_GetSize(nonground);i++) {
    if (!term_PropertyPhasePositive((TERM)nonground[i]))
      printf("~");
    term_PrintPrefix(state_GetTermstate(State), (TERM)nonground[i]);
    printf(":P%d:I%d ", term_IsPropagatable((TERM)nonground[i]), term_GetPrLitIndex((TERM)nonground[i]) );
  }
  printf("\n\n%% InActive: %u ", (unsigned)array_GetSize(inactive));
  for (i=0;i<array_GetSize(inactive);i++) {
    if (!term_PropertyPhasePositive((TERM)inactive[i]))
      printf("~");
    term_PrintPrefix(state_GetTermstate(State), (TERM)inactive[i]);
    printf(":P%d:I%d:H%d ", term_IsPropagatable((TERM)inactive[i]), term_GetPrLitIndex((TERM)inactive[i]), term_GetProfit((TERM)inactive[i]));
  }
  printf("\n\n%% Active: %u ", (unsigned)array_GetSize(active));
  for (i=0;i<array_GetSize(active);i++) {
    if (!term_PropertyPhasePositive((TERM)active[i]))
      printf("~");
    term_PrintPrefix(state_GetTermstate(State), (TERM)active[i]);
    printf(":P%d:I%d:H%d ", term_IsPropagatable((TERM)active[i]), term_GetPrLitIndex((TERM)active[i]), term_GetProfit((TERM)active[i]));
  }
}
void hlmdg_PrintStat(HLMDGSTATE Hlmdg)
{
  printf("\n%% LModGrow State MaxSize: %u ExtraPropLits: %u MaxHeur: %u Active: %u Inactive: %u ", Hlmdg->max, Hlmdg->extraprops, Hlmdg->heur, (unsigned)array_GetSize(Hlmdg->active), (unsigned)array_GetSize(Hlmdg->inactive));
}
