#ifdef DOC_BUILD_INTERNAL
#endif
#include "instset.h"
const uint32_t insts_INITIALINSTCAPACITY = 16;
const uint32_t insts_CHECKGENINSTINITIALCAPACITY = 16;
INSTSET instset_Create(MEMORY Mem, ARRAY Clauses, TERMSTATE Termstate, TRAIL Trail, ARRAY * Insts)
{
  INSTSET new;
  int it, number;
  CLAUSE clause;
  INST inst;
  new = memory_Malloc(Mem, sizeof(struct INSTSET_HELP));
  number = array_GetSize(Clauses);
  new->insts = ohash_Create(Mem, number, instset_ClauseHash, instset_ClauseEqual);
  new->positive = distrn_Create(Mem);
  new->negative = distrn_Create(Mem);
  new->originClauses = array_Create(Mem, number);
  new->substmaps = array_Create(Mem, number);
  new->filter = instset_FilterCreate(Mem, NULL, TRUE);
  new->instances = 0;
  *Insts = array_Clean(*Insts);
  for (it = 0; it < number; it++) {
    clause = (CLAUSE)array_GetElement(Clauses, it);
    inst = instset_NewOriginClause(Mem, new, clause, Termstate, Trail, trail_GetSize(Trail));
    *Insts = array_Add(Mem, *Insts, (intptr_t)inst);
  }
  return new;
}
void instset_Delete(MEMORY Mem, INSTSET Instset, SYMBSTATE Symbstate)
{
  ARRAY substmaps;
  int it;
  OHASH cur;
  substmaps = instset_GetSubstmaps(Instset);
  substmaps = ohash_CreateDataArr(Mem, instset_GetInsts(Instset), &substmaps);
  for (it = 0; it < array_GetSize(substmaps); it++) {
    cur = (OHASH)array_GetElement(substmaps, it);
    ohash_Delete(cur, NULL, instset_HashDeleteInst);
  }
  ohash_Delete(instset_GetInsts(Instset), NULL, NULL);
  array_Delete(Mem, instset_GetOriginClauses(Instset));
  array_Delete(Mem, substmaps);
  instset_FilterDelete(Mem, instset_GetFilter(Instset));
  distrn_DeleteIter(Mem, instset_GetNegativeDistr(Instset));
  distrn_DeleteIter(Mem, instset_GetPositiveDistr(Instset));
  memory_Free(Mem, Instset, sizeof(struct INSTSET_HELP));
}
unsigned instset_GetInstances(INSTSET Instset)
{
  return Instset->instances;
}
void instset_SetInstances(INSTSET Instset, unsigned Value)
{
  Instset->instances = Value;
}
void instset_IncrementInstances(INSTSET Instset)
{
  Instset->instances++;
}
void instset_DecrementInstances(INSTSET Instset)
{
  Instset->instances--;
}
uint32_t instset_HashQuery(const OHASH_KEY_TYPE Data)
{
  return (clause_GetId(inst_GetOrigin(inst_GetQueryInst((INST_QUERY)Data))) * 387780157) % 1378999961;
}
OHASH instset_GetInsts(INSTSET Instset)
{
  return Instset->insts;
}
void instset_SetInsts(INSTSET Instset, OHASH InstsMap)
{
  Instset->insts = InstsMap;
}
DISTRN instset_GetPositiveDistr(INSTSET Instset)
{
  return Instset->positive;
}
DISTRN instset_GetNegativeDistr(INSTSET Instset)
{
  return Instset->negative;
}
ARRAY instset_GetOriginClauses(INSTSET Instset)
{
  return Instset->originClauses;
}
void instset_SetOriginClauses(INSTSET Instset, ARRAY OriginClauses)
{
  Instset->originClauses = OriginClauses;
}
ARRAY instset_GetSubstmaps(INSTSET Instset)
{
  return Instset->substmaps;
}
void instset_SetSubstmaps(INSTSET Instset, ARRAY Substmaps)
{
  Instset->substmaps = Substmaps;
}
INSTSET_FILTER instset_GetFilter(INSTSET Instset)
{
  return Instset->filter;
}
void instset_SetFilter(INSTSET Instset, INSTSET_FILTER Filter)
{
  Instset->filter = Filter;
}
INSTSET_FILTER instset_FilterCreate(MEMORY Mem, ARRAY Origins, BOOL DeleteInstances)
{
  INSTSET_FILTER new;
  new = memory_Malloc(Mem, sizeof(struct INSTSET_FILTER_HELP));
  new->origins = Origins;
  new->deleteInstances = DeleteInstances;
  return new;
}
void instset_FilterDelete(MEMORY Mem, INSTSET_FILTER Filter)
{
  memory_Free(Mem, Filter, sizeof(struct INSTSET_FILTER_HELP));
}
ARRAY instset_GetFilterOrigins(INSTSET_FILTER Filter)
{
  return Filter->origins;
}
void instset_SetFilterOrigins(INSTSET_FILTER Filter, ARRAY Origins)
{
  Filter->origins = Origins;
}
BOOL instset_GetFilterDeleteInstances(INSTSET_FILTER Filter)
{
  return Filter->deleteInstances;
}
void instset_SetFilterDeleteInstances(INSTSET_FILTER Filter, BOOL DeleteInstances)
{
  Filter->deleteInstances = DeleteInstances;
}
INST instset_NewOriginClause(MEMORY Mem, INSTSET Instset, CLAUSE Clause, TERMSTATE Termstate, TRAIL Trail, unsigned Pos)
{
  INST inst;
  OHASH inst_map;
#ifdef SPASS_CHECK
  if (!instset_CheckIfOriginNotMember(Instset, Clause)) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: Given new origin clause\n ", __func__);
    clause_Print(Termstate, Clause);
    printf("\n");
    misc_ErrorReport(" is already in set of instances.");
    misc_FinishErrorReport();
  }
#endif
  inst = inst_Create(Mem, Clause, 0, 0, NULL, TRUE);
  instset_IncrementInstances(Instset);
  inst_InitiallyPickWatched(inst, Termstate, Trail, Pos);
#ifdef SPASS_CHECK
  if (inst_GetFirstWatched(inst) >= clause_GetFolLiterals(inst_GetOrigin(inst)) || inst_GetSecondWatched(inst) >= clause_GetFolLiterals(inst_GetOrigin(inst))) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: A watched literal is not in the clause in the instance", __func__);
    inst_Print(Termstate, inst);
    misc_FinishErrorReport();
  }
  inst_CheckForDifferentWatched(inst, Termstate);
#endif
  inst_map = ohash_Create(Mem, insts_INITIALINSTCAPACITY, instset_SubstHash, instset_SubstEqual);
  inst_map = ohash_Insert(inst_map, (OHASH_KEY_TYPE)inst_GetSubst(inst), (OHASH_DATA_TYPE)inst, NULL, NULL);
  instset_SetInsts(Instset, ohash_Insert(instset_GetInsts(Instset), (OHASH_KEY_TYPE)Clause, (OHASH_DATA_TYPE)inst_map, NULL, NULL));
  instset_AddWatchedToIndex(Mem, Instset, inst, Termstate, TRUE);
  instset_AddWatchedToIndex(Mem, Instset, inst, Termstate, FALSE);
  return inst;
}
BOOL instset_IsInClauseSubst(INSTSET Instset, CLAUSE Clause, SUBST Subst)
{
  OHASH instances;
  OHASH_DATA_TYPE search_result;
#ifdef SPASS_CHECK
  unsigned it;
  if (Clause == NULL) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: Clause is NULL.", __func__);
    misc_FinishErrorReport();
  }
  for (it = 0; it < subst_NumberOfVariables(Subst); it++) {
    if (subst_GetValue(Subst, (SYMBOL)it) != NULL && !sharing_IsShared(subst_GetValue(Subst, (SYMBOL)it))) {
      misc_StartErrorReport();
      misc_ErrorReport("\n In %s: A valueterm in Subst is not shared.", __func__);
      misc_FinishErrorReport();
    }
  }
#endif
  instances = (OHASH)ohash_Search(instset_GetInsts(Instset), (OHASH_KEY_TYPE)Clause);
  search_result = ohash_Search(instances, (OHASH_KEY_TYPE)Subst);
  return search_result != (OHASH_DATA_TYPE)NULL;
}
BOOL instset_IsInInst(INSTSET Instset, INST Inst)
{
  return instset_IsInClauseSubst(Instset, inst_GetOrigin(Inst), inst_GetSubst(Inst));
}
void instset_AddNewInstance(MEMORY Mem, INSTSET Instset, INST Inst, TERMSTATE Termstate)
{
  OHASH instances;
  instances = (OHASH)ohash_Search(instset_GetInsts(Instset), (OHASH_KEY_TYPE)inst_GetOrigin(Inst));
  instances = ohash_Insert(instances, (OHASH_KEY_TYPE)inst_GetSubst(Inst), (OHASH_DATA_TYPE)Inst, NULL, NULL);
  instset_SetInsts(Instset, ohash_Insert(instset_GetInsts(Instset), (OHASH_KEY_TYPE)inst_GetOrigin(Inst), (OHASH_DATA_TYPE)instances, NULL, NULL));
  instset_AddWatchedToIndex(Mem, Instset, Inst, Termstate, TRUE);
  instset_AddWatchedToIndex(Mem, Instset, Inst, Termstate, FALSE);
}
BOOL instset_IfNotInAddInstance(MEMORY Mem, SHARER Sharer, TERMSTATE Termstate, INSTSET Instset, INST Inst, unsigned FalseWatched, TRAIL Trail, unsigned Pos)
{
  if (instset_IsInInst(Instset, Inst)) {
    return FALSE;
  }
  inst_NewCreatedPickNewWatched(Inst, Termstate, FalseWatched, Trail, Pos);
  inst_CheckPotentialFalseLiteralsOfNewInst(Inst, Termstate, Trail, Pos);
#ifdef SPASS_CHECK
  inst_CheckWatchedCorrect(Inst, Termstate, Trail, Pos);
#endif
  instset_AddNewInstance(Mem, Instset, Inst, Termstate);
#ifdef SPASS_CHECK
  inst_CheckSubstShared(Inst, Termstate);
  if (inst_GetFirstWatched(Inst) >= clause_GetFolLiterals(inst_GetOrigin(Inst)) || inst_GetSecondWatched(Inst) >= clause_GetFolLiterals(inst_GetOrigin(Inst))) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: A watched literal is not in the clause in the instance\n ", __func__);
    inst_Print(Termstate, Inst);
    printf("\n");
    misc_FinishErrorReport();
  }
  inst_CheckForDifferentWatched(Inst, Termstate);
#endif
  return TRUE;
}
INST instset_IfNotInAddNewInstanceFromSubst(MEMORY Mem, SHARER Sharer, TERMSTATE Termstate, INSTSET Instset, INST Inst, SUBST Subst, unsigned FalseWatched, TRAIL Trail)
{
  INST new;
#ifdef SPASS_CHECK
  if (Subst == NULL) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: Substitution is NULL.", __func__);
    misc_FinishErrorReport();
  }
  if (FalseWatched > 2) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: FalseWatched is not 0, 1 or 2.", __func__);
    misc_FinishErrorReport();
  }
#endif
  new = inst_CreateFromInstAndSubst(Mem, Sharer, Termstate, Inst, Subst, trail_GetSize(Trail) == 0);
  instset_IncrementInstances(Instset);
  if (instset_IfNotInAddInstance(Mem, Sharer, Termstate, Instset, new, FalseWatched, Trail, trail_GetSize(Trail)))
    return new;
  inst_Delete(Mem, new);
  return NULL;
}
INST instset_IfNotInAddNewInstanceFromContext(MEMORY Mem, SHARER Sharer, TERMSTATE Termstate, INSTSET Instset, INST Inst, SUBSTSTATE Subststate, unsigned FalseWatched, TRAIL Trail, BOOL Matching, unsigned Pos)
{
  INST new;
  unsigned i;
  SUBST subst;
#ifdef SPASS_CHECK
  if (FalseWatched > 2) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: FalseWatched is not 0, 1 or 2.", __func__);
    misc_FinishErrorReport();
  }
#endif
  if (inst_GetSubst(Inst) == NULL) {
    if (Matching)
      subst = subst_ContextExtractSubstShallow(Subststate, Termstate, term_GetSymbstate(Termstate), (SYMBOL)clause_GetVariables(inst_GetOrigin(Inst)));
    else
      subst = subst_ContextFlattenExtractSubst(Subststate, Termstate, term_GetSymbstate(Termstate), (SYMBOL)clause_GetVariables(inst_GetOrigin(Inst)));
  }
  else
    subst = subst_ContextFlattenApplyToSubst(Subststate, Termstate, inst_GetSubst(Inst), TRUE);
  for (i = 0; i < subst_NumberOfVariables(subst); i++)
    if (subst_VarDefined(subst, (SYMBOL)i) && !sharing_IsShared(subst_GetValue(subst, (SYMBOL)i)))
      subst_SetValue(subst, (SYMBOL)i, sharing_GetSharedTerm(Sharer, subst_GetValue(subst, (SYMBOL)i)));
  if (instset_IsInClauseSubst(Instset, inst_GetOrigin(Inst), subst)) {
    subst_Delete(Mem, subst);
    return (INST)NULL;
  }
  new = inst_Create(Mem, inst_GetOrigin(Inst), inst_GetFirstWatched(Inst), inst_GetSecondWatched(Inst), subst, trail_GetSize(Trail) == 0);
  instset_IncrementInstances(Instset);
  inst_NewCreatedPickNewWatched(new, Termstate, FalseWatched, Trail, Pos);
  inst_CheckPotentialFalseLiteralsOfNewInst(new, Termstate, Trail, Pos);
#ifdef SPASS_CHECK
  inst_CheckWatchedCorrect(new, Termstate, Trail, Pos);
#endif
  instset_AddNewInstance(Mem, Instset, new, Termstate);
  return new;
}
void instset_AddWatchedToIndex(MEMORY Mem, INSTSET Instset, INST Inst, TERMSTATE Termstate, BOOL FirstWatched)
{
  unsigned literal;
  CLAUSE clause;
  SUBST subst;
  INST_QUERY query;
  clause = inst_GetOrigin(Inst);
  subst = inst_GetSubst(Inst);
  if (FirstWatched) {
    literal = inst_GetFirstWatched(Inst);
    query = inst_GetFirstQuery(Inst);
  } else {
    literal = inst_GetSecondWatched(Inst);
    query = inst_GetSecondQuery(Inst);
  }
  if (clause_LiteralIsPositive(clause, literal)) {
    distrn_InsertDataHash(Mem, instset_GetPositiveDistr(Instset), Termstate, clause_GetAtom(clause, literal), subst,
     (intptr_t)query, instset_HashQuery);
  }
  else {
    distrn_InsertDataHash(Mem, instset_GetNegativeDistr(Instset), Termstate, clause_GetAtom(clause, literal), subst,
    (intptr_t)query, instset_HashQuery);
  }
}
void instset_RemoveWatchedFromIndex(INSTSET Instset, INST Inst, TERMSTATE Termstate, unsigned OldWatched, BOOL FirstWatched)
{
  CLAUSE clause;
  SUBST subst;
  INST_QUERY query;
  clause = inst_GetOrigin(Inst);
  subst = inst_GetSubst(Inst);
  if (FirstWatched)
    query = inst_GetFirstQuery(Inst);
  else
    query = inst_GetSecondQuery(Inst);
  if (clause_LiteralIsPositive(clause, OldWatched))
    distrn_Remove(instset_GetPositiveDistr(Instset), Termstate, clause_GetAtom(clause, OldWatched), subst, (intptr_t)query);
  else
    distrn_Remove(instset_GetNegativeDistr(Instset), Termstate, clause_GetAtom(clause, OldWatched), subst, (intptr_t)query);
}
ARRAY instset_SearchNewlyFalseWatched(MEMORY Mem, INSTSET Instset, TERMSTATE Termstate, TERM Atom, BOOL Value, ARRAY * Result, unsigned Size)
{
  if (Value) {
    return distrn_SearchGeneralizations(Mem, instset_GetNegativeDistr(Instset), Termstate, Atom, Result);
  }
  else {
    return distrn_SearchGeneralizations(Mem, instset_GetPositiveDistr(Instset), Termstate, Atom, Result);
  }
}
BOOL instset_TryUpdateWatched(MEMORY Mem, INSTSET Instset, TERMSTATE Termstate, INST Inst, BOOL FirstFalse, TRAIL Trail)
{
  BOOL found_new;
  unsigned old_watched;
  if (FirstFalse)
    old_watched = inst_GetFirstWatched(Inst);
  else
    old_watched = inst_GetSecondWatched(Inst);
  found_new = inst_PickNewWatchedPos(Inst, Termstate, FirstFalse, Trail, trail_GetSize(Trail));
#ifdef SPASS_CHECK
  if (inst_GetFirstWatched(Inst) >= clause_GetFolLiterals(inst_GetOrigin(Inst)) || inst_GetSecondWatched(Inst) >= clause_GetFolLiterals(inst_GetOrigin(Inst))) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: A watched literal is not in the clause in the instance\n ", __func__);
    inst_Print(Termstate, Inst);
    printf("\n");
    misc_FinishErrorReport();
  }
  inst_CheckForDifferentWatched(Inst, Termstate);
#endif
  if (!found_new)
    return FALSE;
  instset_RemoveWatchedFromIndex(Instset, Inst, Termstate, old_watched, FirstFalse);
  instset_AddWatchedToIndex(Mem, Instset, Inst, Termstate, FirstFalse);
  return TRUE;
}
BOOL instset_TryUpdateWatchedPos(MEMORY Mem, INSTSET Instset, TERMSTATE Termstate, INST Inst, BOOL FirstFalse, TRAIL Trail, unsigned Pos)
{
  BOOL found_new;
  unsigned old_watched ;
#ifdef SPASS_CHECK
  CLAUSE clause;
#endif
  if (FirstFalse) {
    old_watched = inst_GetFirstWatched(Inst);
  }
  else {
    old_watched = inst_GetSecondWatched(Inst);
  }
  found_new = inst_PickNewWatchedPos(Inst, Termstate, FirstFalse, Trail, Pos);
#ifdef SPASS_CHECK
  clause = inst_GetOrigin(Inst);
  if (inst_GetFirstWatched(Inst) >= clause_GetFolLiterals(clause) || inst_GetSecondWatched(Inst) >= clause_GetFolLiterals(clause)) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: A watched literal is not in the clause in the instance\n ", __func__);
    inst_Print(Termstate, Inst);
    printf("\n");
    misc_FinishErrorReport();
  }
  inst_CheckForDifferentWatched(Inst, Termstate);
#endif
  if (!found_new)
    return FALSE;
  instset_RemoveWatchedFromIndex(Instset, Inst, Termstate, old_watched, FirstFalse);
  instset_AddWatchedToIndex(Mem, Instset, Inst, Termstate, FirstFalse);
  return TRUE;
}
void instset_DeleteClause(MEMORY Mem, TERMSTATE Termstate, INSTSET Instset, CLAUSE Clause)
{
  OHASH instances;
  unsigned k, cap;
  INST inst;
  instances = (OHASH)ohash_Search(instset_GetInsts(Instset), (OHASH_KEY_TYPE)Clause);
  cap = ohash_GetCapacity(instances);
  for (k = 0; k < cap; k++) {
    if (ohash_GetOccupancyAtIndex(instances, k) == ohash_ENTRY_OCCUPIED) {
      inst = (INST)ohash_GetDataAtIndex(instances, k);
      instset_DeleteInst(Mem, Termstate, Instset, inst, TRUE);
    }
  }
  instset_SetInsts(Instset, ohash_Remove(instset_GetInsts(Instset), (OHASH_KEY_TYPE)Clause, (OHASH_DELETE_KEY_FCT)NULL, (OHASH_DELETE_DATA_FCT)NULL));
  ohash_Delete(instances, NULL, NULL);
}
void instset_RefreshInstances(MEMORY Mem, TERMSTATE Termstate, INSTSET Instset)
{
  OHASH cinstances, instances;
  unsigned k, i, ccap, cap;
  INST inst;
  cinstances = instset_GetInsts(Instset);
  ccap = ohash_GetCapacity(cinstances);
  for (i = 0; i < ccap; i++) {
    if (ohash_GetOccupancyAtIndex(cinstances, i) == ohash_ENTRY_OCCUPIED) {
      instances = (OHASH)ohash_GetDataAtIndex(cinstances, i);
      cap = ohash_GetCapacity(instances);
      for (k = 0; k < cap; k++) {
 if (ohash_GetOccupancyAtIndex(instances, k) == ohash_ENTRY_OCCUPIED) {
   inst = (INST)ohash_GetDataAtIndex(instances, k);
   if (inst_GetSubst(inst) != (SUBST)NULL) {
     instset_DeleteInst(Mem, Termstate, Instset, inst, TRUE);
     instset_DecrementInstances(Instset);
     ohash_RemoveEntryAtIndex(instances, k);
   }
 }
      }
      ohash_SetDataAtIndex(cinstances,i, (OHASH_DATA_TYPE)ohash_Cleanup(instances));
    }
  }
}
unsigned instset_ComputeNumberOfDuplicates(TERMSTATE Termstate, INSTSET Instset)
{
  OHASH cinstances, instances;
  unsigned k, i, j, ccap, cap, sum;
  INST inst1,inst2;
  cinstances = instset_GetInsts(Instset);
  ccap = ohash_GetCapacity(cinstances);
  sum = 0;
  for (i = 0; i < ccap; i++) {
    if (ohash_GetOccupancyAtIndex(cinstances, i) == ohash_ENTRY_OCCUPIED) {
      instances = (OHASH)ohash_GetDataAtIndex(cinstances, i);
      cap = ohash_GetCapacity(instances);
      for (k = 0; k < cap; k++) {
 if (ohash_GetOccupancyAtIndex(instances, k) == ohash_ENTRY_OCCUPIED) {
   inst1 = (INST)ohash_GetDataAtIndex(instances, k);
   for (j = k+1; j < cap; j++) {
     if (ohash_GetOccupancyAtIndex(instances, j) == ohash_ENTRY_OCCUPIED) {
       inst2 = (INST)ohash_GetDataAtIndex(instances, j);
       if (inst_Equal(term_GetSymbstate(Termstate), inst1, inst2)) {
  sum++;
       }
     }
   }
 }
      }
    }
  }
  return sum;
}
void instset_DeleteMarkedInstances(MEMORY Mem, TERMSTATE Termstate, INSTSET Instset)
{
  OHASH cinstances, instances;
  unsigned k, i, ccap, cap;
  INST inst;
  CLAUSE clause;
  cinstances = instset_GetInsts(Instset);
  ccap = ohash_GetCapacity(cinstances);
  for (i = 0; i < ccap; i++) {
    if (ohash_GetOccupancyAtIndex(cinstances, i) == ohash_ENTRY_OCCUPIED) {
      instances = (OHASH)ohash_GetDataAtIndex(cinstances, i);
      clause = (CLAUSE)ohash_GetKeyAtIndex(cinstances, i);
      if (clause_IsMarkedDelete(clause) || clause_IsMarkedNullAtoms(clause)) {
 cap = ohash_GetCapacity(instances);
 for (k = 0; k < cap; k++) {
   if (ohash_GetOccupancyAtIndex(instances, k) == ohash_ENTRY_OCCUPIED) {
     inst = (INST)ohash_GetDataAtIndex(instances, k);
     instset_DeleteInst(Mem, Termstate, Instset, inst, TRUE);
   }
 }
 ohash_Delete(instances, NULL, NULL);
 ohash_RemoveEntryAtIndex(cinstances, i);
      }
    }
  }
  instset_SetInsts(Instset, ohash_Cleanup(cinstances));
}
void instset_DeleteInst(MEMORY Mem, TERMSTATE Termstate, INSTSET Instset, INST Inst, BOOL Lazy)
{
  CLAUSE clause;
  SUBST subst;
  INST_QUERY query;
  unsigned watched;
  OHASH instances;
  clause = inst_GetOrigin(Inst);
  subst = inst_GetSubst(Inst);
  query = inst_GetFirstQuery(Inst);
  watched = inst_GetFirstWatched(Inst);
  if (clause_LiteralIsPositive(clause, watched))
    distrn_Remove(instset_GetPositiveDistr(Instset), Termstate, clause_GetAtom(clause, watched), subst, (intptr_t)query);
  else
    distrn_Remove(instset_GetNegativeDistr(Instset), Termstate, clause_GetAtom(clause, watched), subst, (intptr_t)query);
  query = inst_GetSecondQuery(Inst);
  watched = inst_GetSecondWatched(Inst);
  if (clause_LiteralIsPositive(clause, watched))
    distrn_Remove(instset_GetPositiveDistr(Instset), Termstate, clause_GetAtom(clause, watched), subst, (intptr_t)query);
  else
    distrn_Remove(instset_GetNegativeDistr(Instset), Termstate, clause_GetAtom(clause, watched), subst, (intptr_t)query);
  if (!Lazy) {
    instances = (OHASH)ohash_Search(instset_GetInsts(Instset), (OHASH_KEY_TYPE)clause);
    instset_SetInsts(Instset, ohash_Insert(instset_GetInsts(Instset), (OHASH_KEY_TYPE)clause,
        (OHASH_DATA_TYPE)ohash_Remove(instances, (OHASH_KEY_TYPE)subst, (OHASH_DELETE_KEY_FCT)NULL, (OHASH_DELETE_DATA_FCT)NULL), NULL, NULL));
  }
  inst_Delete(Mem, Inst);
}
void instset_RestartAndForget(MEMORY Mem, SYMBSTATE Symbstate, INSTSET Instset, ARRAY Origins, BOOL DeleteInstances)
{
  int it;
  CLAUSE origin;
  OHASH substmap, clausemap;
  ARRAY clauses;
  ARRAY substmaps;
  INSTSET_FILTER filter;
  filter = instset_GetFilter(Instset);
  instset_SetFilterOrigins(filter, Origins);
  instset_SetFilterDeleteInstances(filter, DeleteInstances);
  distrn_RemoveIfTrue(Mem, instset_GetPositiveDistr(Instset), Symbstate, instset_DistrFilterEmptyTrailAndForget, (intptr_t)filter, NULL);
  distrn_RemoveIfTrue(Mem, instset_GetNegativeDistr(Instset), Symbstate, instset_DistrFilterEmptyTrailAndForget, (intptr_t)filter, NULL);
  clausemap = instset_GetInsts(Instset);
  if (Origins != NULL)
    for (it = 0; it < array_GetSize(Origins); it++) {
      origin = (CLAUSE)array_GetElement(Origins, it);
      substmap = (OHASH)ohash_Search(clausemap, (OHASH_KEY_TYPE)origin);
      if (substmap != NULL) {
        ohash_Delete(substmap, NULL, instset_HashDeleteInst);
        clausemap = ohash_Remove(clausemap, (OHASH_KEY_TYPE)origin, NULL, NULL);
      }
    }
  if (!DeleteInstances) {
    clauses = array_Clean(instset_GetOriginClauses(Instset));
    substmaps = array_Clean(instset_GetSubstmaps(Instset));
    ohash_CreateKeyAndDataArr(Mem, instset_GetInsts(Instset), &clauses, &substmaps);
    for (it = 0; it < array_GetSize(substmaps); it++) {
      origin = (CLAUSE)array_GetElement(clauses, it);
      substmap = (OHASH)array_GetElement(substmaps, it);
      substmap = ohash_RemoveIfTrue(substmap, instset_HashFilterEmptyTrail, (intptr_t)NULL, NULL, instset_HashDeleteInst);
      clausemap = ohash_Insert(clausemap, (OHASH_KEY_TYPE)origin, (OHASH_DATA_TYPE)substmap, NULL, NULL);
    }
    instset_SetOriginClauses(Instset, clauses);
    instset_SetSubstmaps(Instset, substmaps);
  }
  instset_SetInsts(Instset, clausemap);
}
ARRAY instset_GetAllInstances(MEMORY Mem, INSTSET Instset, ARRAY * Result)
{
  ARRAY substmaps;
  OHASH clausemap;
  int it;
  clausemap = instset_GetInsts(Instset);
  substmaps = instset_GetSubstmaps(Instset);
  *Result = array_Clean(*Result);
  substmaps = ohash_CreateDataArr(Mem, clausemap, &substmaps);
  for (it = 0; it < array_GetSize(substmaps); it++) {
    *Result = ohash_AppendDataToArr(Mem, (OHASH)array_GetElement(substmaps, it), Result);
  }
  instset_SetSubstmaps(Instset, substmaps);
  return *Result;
}
uint32_t instset_ClauseHash(const OHASH_KEY_TYPE Clause)
{
  CLAUSE cl;
  cl = (CLAUSE)Clause;
  return (clause_GetId(cl) * 387780157) % 1378999961;
}
BOOL instset_ClauseEqual(const OHASH_KEY_TYPE Clause1, const OHASH_KEY_TYPE Clause2)
{
  CLAUSE cl1, cl2;
  cl1 = (CLAUSE)Clause1;
  cl2 = (CLAUSE)Clause2;
  return clause_GetId(cl1) == clause_GetId(cl2);
}
uint32_t instset_SubstHash(const OHASH_KEY_TYPE Subst)
{
  SUBST sub;
  unsigned it;
  uint32_t res;
  intptr_t value;
  sub = (SUBST)Subst;
  if (sub == NULL)
    return 0;
  res = 12345;
  for (it = 0; it < subst_NumberOfVariables(sub); it++) {
    value = (intptr_t)subst_GetValue(sub, (SYMBOL)it);
    if (value != 0){
      value = (intptr_t)term_Index((TERM)value);
      res += (uint32_t)((intptr_t)value) ^ ((intptr_t)value >> 5) ^ ((intptr_t)value >> 9);
    }
    else
      res += 3457235782;
    res *= 2015264737;
  }
  return res % 1378999961;
}
BOOL instset_SubstEqual(const OHASH_KEY_TYPE Subst1, const OHASH_KEY_TYPE Subst2)
{
  unsigned it, vars1, vars2;
  SUBST sub1, sub2;
  if (Subst1 == (OHASH_KEY_TYPE)NULL && Subst2 == (OHASH_KEY_TYPE)NULL)
    return TRUE;
  if (Subst1 == (OHASH_KEY_TYPE)NULL || Subst2 == (OHASH_KEY_TYPE)NULL)
    return FALSE;
  sub1 = (SUBST)Subst1;
  sub2 = (SUBST)Subst2;
  vars1 = subst_NumberOfVariables(sub1);
  vars2 = subst_NumberOfVariables(sub2);
  if (vars1 != vars2)
    return FALSE;
  for (it = 0; it < vars1; it++)
    if (subst_GetValue(sub1, (SYMBOL)it) != subst_GetValue(sub2, (SYMBOL)it))
      return FALSE;
  return TRUE;
}
void instset_HashDeleteInst(MEMORY Mem, OHASH_DATA_TYPE Inst)
{
  inst_Delete(Mem, (INST)Inst);
}
BOOL instset_HashFilterEmptyTrail(intptr_t State, OHASH_KEY_TYPE Key, OHASH_DATA_TYPE Data)
{
  INST inst;
  inst = (INST)Data;
  return !inst_GetEmptyTrail(inst);
}
BOOL instset_DistrFilterEmptyTrailAndForget(intptr_t Filter, intptr_t Entry)
{
  INST_QUERY query;
  INST inst;
  ARRAY clauses;
  INSTSET_FILTER filter;
  query = (INST_QUERY)Entry;
  inst = inst_GetQueryInst(query);
  filter = (INSTSET_FILTER)Filter;
  clauses = instset_GetFilterOrigins(filter);
  if (instset_GetFilterDeleteInstances(filter) && !inst_GetEmptyTrail(inst))
    return TRUE;
  if (clauses != NULL && array_HasElement(clauses, (intptr_t)inst_GetOrigin(inst)))
    return TRUE;
  return FALSE;
}
void instset_CheckOriginForCorrectWatched(MEMORY Mem, INSTSET Instset, TERMSTATE Termstate, CLAUSE Origin, TRAIL Trail, BOOL ExhaustiveAppl)
{
  unsigned it;
  ARRAY insts;
  OHASH clausemap, substmap;
  INST cur;
  clausemap = instset_GetInsts(Instset);
  substmap = (OHASH)ohash_Search(clausemap, (OHASH_KEY_TYPE)Origin);
  if (substmap == NULL) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: Given origin clause\n ", __func__);
    clause_Print(Termstate, Origin);
    printf("\n");
    misc_ErrorReport(" is not in the set of instances.");
    misc_FinishErrorReport();
  }
  insts = array_Create(Mem, ohash_GetNumberElems(substmap));
  insts = ohash_CreateDataArr(Mem, substmap, &insts);
  for (it = 0; it < array_GetSize(insts); it++) {
    cur = (INST)array_GetElement(insts, it);
    if (clause_GetId(inst_GetOrigin(cur)) != clause_GetId(Origin)) {
      misc_StartErrorReport();
      misc_ErrorReport("\n In %s: The instance\n ", __func__);
      inst_Print(Termstate, cur);
      printf("\n");
      misc_ErrorReport(" is in the map of instances of the origin clause\n ");
      clause_Print(Termstate, Origin);
      printf("\n");
      misc_FinishErrorReport();
    }
    inst_CheckForDifferentWatched(cur, Termstate);
    if (ExhaustiveAppl)
      inst_CheckWatchedCorrectAfterExhaustiveApplication(cur, Termstate, Trail);
    else
      inst_CheckWatchedCorrect(cur, Termstate, Trail, trail_GetSize(Trail)-1);
  }
  array_Delete(Mem, insts);
}
void instset_CheckAllInstancesForWatched(MEMORY Mem, INSTSET Instset, TERMSTATE Termstate, TRAIL Trail, BOOL ExhaustiveAppl)
{
  unsigned it;
  OHASH clausemap;
  ARRAY origins, substmaps;
  CLAUSE cur;
  clausemap = instset_GetInsts(Instset);
  origins = array_Create(Mem, ohash_GetNumberElems(clausemap));
  substmaps = array_Create(Mem, ohash_GetNumberElems(clausemap));
  ohash_CreateKeyAndDataArr(Mem, clausemap, &origins, &substmaps);
  for (it = 0; it < array_GetSize(origins); it++) {
    cur = (CLAUSE)array_GetElement(origins, it);
    instset_CheckOriginForCorrectWatched(Mem, Instset, Termstate, cur, Trail, ExhaustiveAppl);
  }
  array_Delete(Mem, substmaps);
  array_Delete(Mem, origins);
}
BOOL instset_CheckIfOriginNotMember(INSTSET Instset, CLAUSE Origin)
{
  OHASH clausemap;
  clausemap = instset_GetInsts(Instset);
  return (ohash_Search(clausemap, (OHASH_KEY_TYPE)Origin) == (OHASH_DATA_TYPE)NULL);
}
void instset_CheckIfInstancesAreGeneratedForClauseInternal(MEMORY Mem, INSTSET Instset, TERMSTATE Termstate, SUBSTSTATE Subststate, FOLSTATE Folstate,
                                                           KBOSTATE Kbostate, SHARER Sharer, CLAUSE Clause, TRAIL Trail, TERM Beta,
                                                           ARRAY * substs, ARRAY * first_not_false, ARRAY * second_not_false,
                                                           ARRAY * next_substs, ARRAY * next_first_not_false, ARRAY * next_second_not_false)
{
  SYMBSTATE symbstate;
  OHASH substmap;
  ARRAY h_array, instances;
  TERM atom;
  SUBST cur_subst, new_subst;
  unsigned it, i, vars, w1, w2;
  int cur_first_not_false, cur_second_not_false;
  BOOL is_pos;
  TYPING typing;
  INST inst;
  symbstate = term_GetSymbstate(Termstate);
  substmap = (OHASH)ohash_Search(instset_GetInsts(Instset), (OHASH_KEY_TYPE)Clause);
  if (substmap == (OHASH)NULL) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: Given clause is not in set of instances as origin clause.", __func__);
    misc_FinishErrorReport();
  }
  array_Clean(*substs);
  array_Clean(*first_not_false);
  array_Clean(*second_not_false);
  array_Clean(*next_substs);
  array_Clean(*next_first_not_false);
  array_Clean(*next_second_not_false);
  typing = clause_GetTypes(Clause);
  vars = clause_GetVariables(Clause);
  cur_subst = subst_Create(Mem, vars);
  *substs = array_Push(Mem, *substs, (intptr_t)cur_subst);
  *first_not_false = array_Push(Mem, *first_not_false, -1);
  *second_not_false = array_Push(Mem, *second_not_false, -1);
  for (it = 0; it < clause_GetFolLiterals(Clause); it++) {
    atom = clause_GetAtom(Clause, it);
    is_pos = clause_LiteralIsPositive(Clause, it);
    while (!array_IsEmpty(*substs)) {
      cur_subst = (SUBST)array_Pop(*substs);
      cur_first_not_false = array_Pop(*first_not_false);
      cur_second_not_false = array_Pop(*second_not_false);
      if (subst_TermIsGrounded(Termstate, atom, cur_subst)) {
        if (trail_LitStatusFromAtom(Trail, atom, cur_subst, is_pos) == SET_FALSE) {
          *next_substs = array_Push(Mem, *next_substs, (intptr_t)cur_subst);
          *next_first_not_false = array_Push(Mem, *next_first_not_false, cur_first_not_false);
          *next_second_not_false = array_Push(Mem, *next_second_not_false, cur_second_not_false);
          continue;
        }
      } else {
        if (trail_StartFalseInstancesIterator(Trail, atom, cur_subst, is_pos, typing)) {
          while (trail_NextFalseInstanceFromIterator(Trail, atom, cur_subst, is_pos, typing)) {
            new_subst = subst_ContextFlattenApplyToSubst(Subststate, Termstate, cur_subst, TRUE);
            if ((cur_first_not_false == -1 ||
                 trail_LitStatusFromAtom(Trail, clause_GetAtom(Clause, cur_first_not_false), new_subst, clause_LiteralIsPositive(Clause, cur_first_not_false)) != SET_FALSE) &&
                (cur_second_not_false == -1 ||
                 trail_LitStatusFromAtom(Trail, clause_GetAtom(Clause, cur_second_not_false), new_subst, clause_LiteralIsPositive(Clause, cur_second_not_false)) != SET_FALSE)) {
              *next_substs = array_Push(Mem, *next_substs, (intptr_t)new_subst);
              *next_first_not_false = array_Push(Mem, *next_first_not_false, cur_first_not_false);
              *next_second_not_false = array_Push(Mem, *next_second_not_false, cur_second_not_false);
            } else {
              subst_DeleteWithTerms(Termstate, Mem, new_subst);
            }
            subst_ContextStop(Subststate);
          }
        }
        trail_StopInstancesIterator(Trail);
      }
      if (cur_first_not_false != -1) {
        subst_ContextStart(Subststate, symbstate);
        if (subst_FolTermUnifyIdenticalVarsSubst(Subststate, Folstate, Termstate, symbstate, clause_GetTypes(Clause), cur_subst,
                                              clause_GetAtom(Clause, it), clause_GetAtom(Clause, cur_first_not_false), TRUE)) {
          new_subst = subst_ContextFlattenApplyToSubst(Subststate, Termstate, cur_subst, TRUE);
          if ((trail_LitStatusFromAtom(Trail, clause_GetAtom(Clause, cur_first_not_false), new_subst, clause_LiteralIsPositive(Clause, cur_first_not_false)) != SET_FALSE) &&
              (cur_second_not_false == -1 ||
               trail_LitStatusFromAtom(Trail, clause_GetAtom(Clause, cur_second_not_false), new_subst, clause_LiteralIsPositive(Clause, cur_second_not_false)) != SET_FALSE)) {
            *next_substs = array_Push(Mem, *next_substs, (intptr_t)new_subst);
            *next_first_not_false = array_Push(Mem, *next_first_not_false, cur_first_not_false);
            *next_second_not_false = array_Push(Mem, *next_second_not_false, cur_second_not_false);
          } else {
            subst_DeleteWithTerms(Termstate, Mem, new_subst);
          }
        }
        subst_ContextStop(Subststate);
        if (cur_second_not_false != -1) {
          subst_ContextStart(Subststate, symbstate);
          if (subst_FolTermUnifyIdenticalVarsSubst(Subststate, Folstate, Termstate, symbstate, clause_GetTypes(Clause), cur_subst,
                                                clause_GetAtom(Clause, it), clause_GetAtom(Clause, cur_second_not_false), TRUE)) {
            new_subst = subst_ContextFlattenApplyToSubst(Subststate, Termstate, cur_subst, TRUE);
            if (trail_LitStatusFromAtom(Trail, clause_GetAtom(Clause, cur_first_not_false), new_subst, clause_LiteralIsPositive(Clause, cur_first_not_false)) != SET_FALSE &&
                trail_LitStatusFromAtom(Trail, clause_GetAtom(Clause, cur_second_not_false), new_subst, clause_LiteralIsPositive(Clause, cur_second_not_false)) != SET_FALSE) {
              *next_substs = array_Push(Mem, *next_substs, (intptr_t)new_subst);
              *next_first_not_false = array_Push(Mem, *next_first_not_false, cur_first_not_false);
              *next_second_not_false = array_Push(Mem, *next_second_not_false, cur_second_not_false);
            } else {
              subst_DeleteWithTerms(Termstate, Mem, new_subst);
            }
          }
          subst_ContextStop(Subststate);
        }
      }
      if ((cur_second_not_false != -1) || (cur_first_not_false != -1 && clause_LiteralIsPositive(Clause, cur_first_not_false) == clause_LiteralIsPositive(Clause, it) &&
                                           subst_TermEqualModuloSubsts(symbstate, clause_GetAtom(Clause, cur_first_not_false), cur_subst, atom, cur_subst))) {
        subst_DeleteWithTerms(Termstate, Mem, cur_subst);
        continue;
      }
      *next_substs = array_Push(Mem, *next_substs, (intptr_t)cur_subst);
      if (cur_first_not_false == -1) {
        *next_first_not_false = array_Push(Mem, *next_first_not_false, it);
        *next_second_not_false = array_Push(Mem, *next_second_not_false, -1);
      } else {
        *next_first_not_false = array_Push(Mem, *next_first_not_false, cur_first_not_false);
        *next_second_not_false = array_Push(Mem, *next_second_not_false, it);
      }
    }
    h_array = *next_substs;
    *next_substs = *substs;
    *substs = h_array;
    h_array = *next_first_not_false;
    *next_first_not_false = *first_not_false;
    *first_not_false = h_array;
    h_array = *next_second_not_false;
    *next_second_not_false = *second_not_false;
    *second_not_false = h_array;
  }
  instances = *next_substs;
  ohash_CreateDataArr(Mem, substmap, &instances);
  while (!array_IsEmpty(*substs)) {
    cur_subst = (SUBST)array_Pop(*substs);
    for (it = 0; it < clause_GetFolLiterals(Clause); it++)
      if (!order_SmallerEqualSubst(Termstate, symbstate, Subststate, cur_subst, clause_GetAtom(Clause, it), Beta))
        break;
    if (it < clause_GetFolLiterals(Clause)) {
      subst_DeleteWithTerms(Termstate, Mem, cur_subst);
      continue;
    }
    for (it = 0; it < subst_NumberOfVariables(cur_subst); it++)
      if (subst_VarDefined(cur_subst, (SYMBOL)it) && !sharing_IsShared(subst_GetValue(cur_subst, (SYMBOL)it)))
        subst_SetValue(cur_subst, (SYMBOL)it, sharing_GetSharedTerm(Sharer, subst_GetValue(cur_subst, (SYMBOL)it)));
    cur_first_not_false = array_Pop(*first_not_false);
    cur_second_not_false = array_Pop(*second_not_false);
    if (cur_first_not_false == -1) {
      for (it = 0; it < array_GetSize(instances); it++) {
        inst = (INST)array_GetElement(instances, it);
        if (inst_GetSubst(inst) == NULL) {
          for (i = 0; i < subst_NumberOfVariables(cur_subst); i++) {
            if (subst_VarDefined(cur_subst, (SYMBOL)i))
              break;
          }
        } else {
          for (i = 0; i < subst_NumberOfVariables(cur_subst); i++) {
            if (subst_GetValue(cur_subst, (SYMBOL)i) != subst_GetValue(inst_GetSubst(inst), (SYMBOL)i))
              break;
          }
        }
        if (i >= subst_NumberOfVariables(cur_subst)) {
          inst_CheckWatchedCorrectAfterExhaustiveApplication(inst, Termstate, Trail);
          break;
        }
      }
      if (it >= array_GetSize(instances)) {
        misc_StartErrorReport();
        misc_ErrorReport("\n In %s: The conflicting instance from clause\n ", __func__);
        clause_Print(Termstate, Clause);
        printf("\n");
        misc_ErrorReport(" with substitution\n ");
        subst_Print(Termstate, symbstate, cur_subst);
        printf("\n");
        misc_ErrorReport(" is not in the set of instances.");
        misc_FinishErrorReport();
      }
      subst_Delete(Mem, cur_subst);
      continue;
    }
    if (cur_second_not_false == -1) {
      for (it = 0; it < array_GetSize(instances); it++) {
        inst = (INST)array_GetElement(instances, it);
        w1 = inst_GetFirstWatched(inst);
        w2 = inst_GetSecondWatched(inst);
        if ((int)w1 == cur_first_not_false || (int)w2 == cur_first_not_false ||
            subst_TermEqualModuloSubsts(symbstate, clause_GetAtom(Clause, w1), inst_GetSubst(inst), clause_GetAtom(Clause, cur_first_not_false), inst_GetSubst(inst)) ||
            subst_TermEqualModuloSubsts(symbstate, clause_GetAtom(Clause, w2), inst_GetSubst(inst), clause_GetAtom(Clause, cur_first_not_false), inst_GetSubst(inst))) {
          if (subst_IsInstance(Subststate, symbstate, Termstate, inst_GetSubst(inst), cur_subst)) {
            for (i = 0; i < clause_GetFolLiterals(Clause); i++) {
              if (i == (unsigned)cur_first_not_false || subst_TermEqualModuloSubsts(symbstate, clause_GetAtom(Clause, i), inst_GetSubst(inst),
                                                                                    clause_GetAtom(Clause, cur_first_not_false), inst_GetSubst(inst)))
                continue;
              if (!subst_TermIsGrounded(Termstate, clause_GetAtom(Clause, i), inst_GetSubst(inst)))
                break;
            }
            if (i >= clause_GetFolLiterals(Clause)) {
              inst_CheckWatchedCorrectAfterExhaustiveApplication(inst, Termstate, Trail);
              break;
            }
          }
        }
      }
      if (it >= array_GetSize(instances)) {
        misc_StartErrorReport();
        misc_ErrorReport("\n In %s: The propagating instance from clause\n ", __func__);
        clause_Print(Termstate, Clause);
        printf("\n");
        misc_ErrorReport(" with substitution\n ");
        subst_Print(Termstate, symbstate, cur_subst);
        printf("\n");
        misc_ErrorReport(" is not in the set of instances.");
        misc_FinishErrorReport();
      }
      subst_Delete(Mem, cur_subst);
      continue;
    }
    for (it = 0; it < array_GetSize(instances); it++) {
      inst = (INST)array_GetElement(instances, it);
      w1 = inst_GetFirstWatched(inst);
      w2 = inst_GetSecondWatched(inst);
      if (((int)w1 == cur_first_not_false && (int)w2 == cur_second_not_false) || ((int)w1 == cur_second_not_false && (int)w2 == cur_first_not_false)) {
        if (subst_IsInstance(Subststate, symbstate, Termstate, inst_GetSubst(inst), cur_subst)) {
          inst_CheckWatchedCorrectAfterExhaustiveApplication(inst, Termstate, Trail);
          break;
        }
      }
    }
    if (it >= array_GetSize(instances)) {
      misc_StartErrorReport();
      misc_ErrorReport("\n In %s: The clause\n ", __func__);
      clause_Print(Termstate, Clause);
      printf("\n");
      misc_ErrorReport(" with substitution\n ");
      subst_Print(Termstate, symbstate, cur_subst);
      printf("\n");
      misc_ErrorReport(" has exactly two not false literals but a respective instance (can be generalisation) is not in the set of instances.");
      misc_FinishErrorReport();
    }
    subst_Delete(Mem, cur_subst);
  }
  *next_substs = instances;
}
void instset_CheckIfInstancesAreGeneratedForClause(MEMORY Mem, INSTSET Instset, TERMSTATE Termstate, SUBSTSTATE Subststate, FOLSTATE Folstate,
                                                   KBOSTATE Kbostate, SHARER Sharer, CLAUSE Clause, TRAIL Trail, TERM Beta)
{
  ARRAY substs, first_not_false, second_not_false, next_substs, next_first_not_false, next_second_not_false;
  substs = array_Create(Mem, insts_CHECKGENINSTINITIALCAPACITY);
  first_not_false = array_Create(Mem, insts_CHECKGENINSTINITIALCAPACITY);
  second_not_false = array_Create(Mem, insts_CHECKGENINSTINITIALCAPACITY);
  next_substs = array_Create(Mem, insts_CHECKGENINSTINITIALCAPACITY);
  next_first_not_false = array_Create(Mem, insts_CHECKGENINSTINITIALCAPACITY);
  next_second_not_false = array_Create(Mem, insts_CHECKGENINSTINITIALCAPACITY);
  instset_CheckIfInstancesAreGeneratedForClauseInternal(Mem, Instset, Termstate, Subststate, Folstate, Kbostate, Sharer, Clause, Trail, Beta,
                                                        &substs, &first_not_false, &second_not_false, &next_substs, &next_first_not_false, &next_second_not_false);
  array_Delete(Mem, substs);
  array_Delete(Mem, first_not_false);
  array_Delete(Mem, second_not_false);
  array_Delete(Mem, next_substs);
  array_Delete(Mem, next_first_not_false);
  array_Delete(Mem, next_second_not_false);
}
void instset_CheckIfInstancesAreGenerated(MEMORY Mem, INSTSET Instset, TERMSTATE Termstate, SUBSTSTATE Subststate, FOLSTATE Folstate,
                                          KBOSTATE Kbostate, SHARER Sharer, TRAIL Trail, TERM Beta)
{
  ARRAY substs, first_not_false, second_not_false, next_substs, next_first_not_false, next_second_not_false, clauses, substmaps;
  unsigned it;
  OHASH clausemap;
  substs = array_Create(Mem, insts_CHECKGENINSTINITIALCAPACITY);
  first_not_false = array_Create(Mem, insts_CHECKGENINSTINITIALCAPACITY);
  second_not_false = array_Create(Mem, insts_CHECKGENINSTINITIALCAPACITY);
  next_substs = array_Create(Mem, insts_CHECKGENINSTINITIALCAPACITY);
  next_first_not_false = array_Create(Mem, insts_CHECKGENINSTINITIALCAPACITY);
  next_second_not_false = array_Create(Mem, insts_CHECKGENINSTINITIALCAPACITY);
  clausemap = instset_GetInsts(Instset);
  clauses = array_Create(Mem, ohash_GetNumberElems(clausemap));
  substmaps = array_Create(Mem, ohash_GetNumberElems(clausemap));
  ohash_CreateKeyAndDataArr(Mem, clausemap, &clauses, &substmaps);
  for (it = 0; it < array_GetSize(clauses); it++)
    instset_CheckIfInstancesAreGeneratedForClauseInternal(Mem, Instset, Termstate, Subststate, Folstate, Kbostate, Sharer, (CLAUSE)array_GetElement(clauses, it), Trail, Beta,
                                                          &substs, &first_not_false, &second_not_false, &next_substs, &next_first_not_false, &next_second_not_false);
  array_Delete(Mem, clauses);
  array_Delete(Mem, substmaps);
  array_Delete(Mem, substs);
  array_Delete(Mem, first_not_false);
  array_Delete(Mem, second_not_false);
  array_Delete(Mem, next_substs);
  array_Delete(Mem, next_first_not_false);
  array_Delete(Mem, next_second_not_false);
}
unsigned instset_TestSpecialConstantValue(SYMBSTATE Symbstate, SYMBOL Constant)
{
  char * Name;
  Name = symbol_GetName(Symbstate, Constant);
  if (Name[1] == '1') {
    if (string_Length(Name) == 2)
      return 1;
    else
      return 10;
  }
  if (Name[1] == '2')
    return 2;
  if (Name[1] == '3')
    return 3;
  if (Name[1] == '4')
    return 4;
  if (Name[1] == '5')
    return 5;
  if (Name[1] == '6')
    return 6;
  if (Name[1] == '7')
    return 7;
  if (Name[1] == '8')
    return 8;
  if (Name[1] == '9')
    return 9;
  if (Name[1] == '0')
    return 0;
  return 42;
}
void instset_Test(MEMORY Mem, ARRAY Clauses, SHARER Sharer, TERMSTATE Termstate, SUBSTSTATE Subststate, SYMBSTATE Symbstate, FOLSTATE Folstate, SYMBOL Control)
{
  INSTSET instset;
  ARRAY origins, false_cand, remove, dummy;
  int clause_it;
  unsigned it, n, vars, false_watched;
  SUBST subst;
  TRAIL trail;
  TYPING typing;
  CLAUSE clause, origin;
  TERM op, atom;
  INST inst, new;
  INST_QUERY query;
  new = NULL;
  vars = 0;
  origins = array_Create(Mem, 8);
  for (clause_it = 0; term_TopSymbol(clause_GetAtom((CLAUSE)array_GetElement(Clauses, clause_it),0)) != Control; clause_it++)
    origins = array_Add(Mem, origins, array_GetElement(Clauses, clause_it));
  false_cand = array_Create(Mem, 4);
  trail = trail_Create(Mem, Symbstate, Termstate, Folstate, Subststate, Sharer);
  dummy = array_Create(Mem, 0);
  instset = instset_Create(Mem, origins, Termstate, trail, &dummy);
  array_Delete(Mem, dummy);
  for (; clause_it < array_GetSize(Clauses); clause_it++) {
    clause = (CLAUSE)array_GetElement(Clauses, clause_it);
    printf("%d:\n", clause_it + 1);
    clause_Print(Termstate, clause);
    printf("\n");
    op = clause_GetAtom(clause,0);
    clause_RemoveLiteral(clause,0);
    n = instset_TestSpecialConstantValue(Symbstate, term_TopSymbol(term_SecondArgument(op)));
    switch (instset_TestSpecialConstantValue(Symbstate, term_TopSymbol(term_FirstArgument(op)))) {
    case 1:
      for (it = 0; it < clause_GetPremiseLiterals(clause); it++)
        trail_Add(trail, clause_GetAtom(clause, it), clause, NULL, it, FALSE, FALSE);
      for (; it < clause_GetFolLiterals(clause); it++)
        trail_Add(trail, clause_GetAtom(clause, it), clause, NULL, it, TRUE, FALSE);
      break;
    case 2:
      for (it = 0; it < n; it++)
      trail_Pop(trail);
      break;
    case 4:
      origin = clause;
      origins = array_Add(Mem, origins, (intptr_t)origin);
      instset_NewOriginClause(Mem, instset, origin, Termstate, trail, trail_GetSize(trail));
      break;
    case 6:
      if (n < array_GetSize(origins)) {
      remove = array_Create(Mem, clause_GetFolLiterals(clause) * 2 + 1);
      remove = array_Add(Mem, remove, array_GetElement(origins, n));
      for (it = 0; term_TopSymbol(clause_GetAtom(clause,it)) != Control; it++) {
        atom = clause_GetAtom(clause, it);
        remove = array_Add(Mem, remove, array_GetElement(origins, instset_TestSpecialConstantValue(Symbstate, term_TopSymbol(term_FirstArgument(atom)))));
        remove = array_Add(Mem, remove, array_GetElement(origins, instset_TestSpecialConstantValue(Symbstate, term_TopSymbol(term_SecondArgument(atom)))));
      }
      instset_RestartAndForget(Mem, Symbstate, instset, remove, TRUE);
      for (it = 0; it < array_GetSize(remove); it++)
        array_PointerRemoveElement(origins, array_GetElement(remove, it));
      array_Delete(Mem, remove);
      } else
      instset_RestartAndForget(Mem, Symbstate, instset, NULL, TRUE);
      break;
    case 7:
      array_Clean(false_cand);
      instset_SearchNewlyFalseWatched(Mem, instset, Termstate, clause_GetAtom(clause, 0), clause_LiteralIsPositive(clause, 0), &false_cand, 1);
      printf("False Candidates:\n");
      for (it = 0; it < array_GetSize(false_cand); it++) {
      query = (INST_QUERY)array_GetElement(false_cand, it);
      inst_Print(Termstate, inst_GetQueryInst(query));
      if (inst_GetQueryFirstWatched(query))
        printf(" for first watched literal\n");
      else
        printf(" for second watched literal\n");
      }
      break;
    case 8:
      query = (INST_QUERY)array_Pop(false_cand);
      inst = inst_GetQueryInst(query);
      if (inst_GetQueryFirstWatched(query))
      false_watched = 1;
      else
      false_watched = 2;
      typing = clause_GetTypes(clause);
      switch (n) {
      case 1:
        subst = subst_Create(Mem, vars);
        for (it = clause_GetPremiseLiterals(clause); it < clause_GetFolLiterals(clause); it++) {
          atom = clause_GetAtom(clause, it);
          subst_SetValue(subst, term_TopSymbol(term_FirstArgument(atom)), term_SecondArgument(atom));
        }
        new = instset_IfNotInAddNewInstanceFromSubst(Mem, Sharer, Termstate, instset, inst, subst, false_watched, trail);
        if (new == NULL)
          printf("Instance is already in the set of instances. \n");
        else if (subst != inst_GetSubst(new))
          subst_Delete(Mem, subst);
        break;
      case 2:
        subst_ContextStart(Subststate, Symbstate);
        for (it = clause_GetPremiseLiterals(clause); it < clause_GetFolLiterals(clause); it++) {
          atom = clause_GetAtom(clause, it);
          if (!subst_FolTermMatchTerms(Subststate, Symbstate, Termstate, Folstate, term_FirstArgument(atom), typing, term_SecondArgument(atom), typing))
            printf("Terms do not match.\n");
        }
        new = instset_IfNotInAddNewInstanceFromContext(Mem, Sharer, Termstate, instset, inst, Subststate, false_watched, trail, TRUE, trail_GetSize(trail));
        if (new == NULL)
          printf("Instance is already in the set of instances. \n");
        subst_ContextStop(Subststate);
        break;
      case 3:
        subst_ContextStart(Subststate, Symbstate);
        for (it = clause_GetPremiseLiterals(clause); it < clause_GetFolLiterals(clause); it++) {
          atom = clause_GetAtom(clause, it);
          if (!subst_FolTermUnifyIdenticalVars(Subststate, Folstate, Termstate, Symbstate, typing, term_FirstArgument(atom), term_SecondArgument(atom), TRUE))
            printf("Terms not unifiable.\n");
        }
        new = instset_IfNotInAddNewInstanceFromContext(Mem, Sharer, Termstate, instset, inst, Subststate, false_watched, trail, FALSE, trail_GetSize(trail));
        if (new == NULL)
          printf("Instance is already in the set of instances. \n");
        subst_ContextStop(Subststate);
        break;
      }
      if (new != NULL) {
      printf("Added new instance to set: ");
      inst_Print(Termstate, new);
      printf("\n");
      }
      break;
    case 9:
      query = (INST_QUERY)array_Pop(false_cand);
      inst = inst_GetQueryInst(query);
      if (!instset_TryUpdateWatched(Mem, instset, Termstate, inst, inst_GetQueryFirstWatched(query) ? 1 : 0, trail))
      printf("Found no unassigned literal.\n");
      else {
      printf("Assigned new watched literal: \n");
      inst_Print(Termstate, inst);
      printf("\n");
      }
      break;
    case 10:
      for (it = 0; it < n; it++)
      array_Pop(false_cand);
      break;
    }
    trail_Print(trail);
    printf("\n\n");
    if (false_cand != NULL && array_GetSize(false_cand) == 0) {
      array_Delete(Mem, false_cand);
      false_cand = NULL;
    }
  }
  if (false_cand != NULL)
    array_Delete(Mem, false_cand);
  trail_Delete(trail);
  instset_Delete(Mem, instset, Symbstate);
  array_Delete(Mem, origins);
}
void instset_Print (TERMSTATE Termstate, INSTSET Instset)
{
  uint32_t clausecap, instcap, i, j, k;
  OHASH clauseohash, instohash;
  INST inst;
  clauseohash = instset_GetInsts(Instset);
  clausecap = ohash_GetCapacity(clauseohash);
  printf("\nInstSet ClauseCap:%"PRIu32" Elm:%"PRIu32,
   clausecap, ohash_GetNumberElems(clauseohash));
  for(i = 0; i < clausecap; i++) {
    if (ohash_GetOccupancyAtIndex(clauseohash,i) == ohash_ENTRY_OCCUPIED) {
      printf("\n Clause: %u ", clause_GetId((CLAUSE)ohash_GetKeyAtIndex(clauseohash,i)));
      instohash = (OHASH)ohash_GetDataAtIndex(clauseohash,i);
      instcap = ohash_GetCapacity(instohash);
      k = 0;
      for(j = 0; j < instcap; j++) {
 if (ohash_GetOccupancyAtIndex(instohash,j) == ohash_ENTRY_OCCUPIED) {
   k++;
   inst = (INST)ohash_GetDataAtIndex(instohash,j);
   printf("\n %p %d,%d:", (void *)inst, inst_GetFirstWatched(inst),inst_GetSecondWatched(inst));
   subst_Print(Termstate, term_GetSymbstate(Termstate), inst_GetSubst(inst));
   inst_Print(Termstate, inst);
 }
      }
      printf(" Instances: %u ", k);
    }
  }
}
void instset_PrintClause(TERMSTATE Termstate, INSTSET Instset, CLAUSE Clause)
{
  uint32_t instcap, j, k;
  OHASH instohash;
  INST inst;
  instohash = (OHASH)ohash_Search(instset_GetInsts(Instset), (OHASH_KEY_TYPE)Clause);
  instcap = ohash_GetCapacity(instohash);
  k = 0;
  for(j = 0; j < instcap; j++) {
    if (ohash_GetOccupancyAtIndex(instohash,j) == ohash_ENTRY_OCCUPIED) {
      k++;
      inst = (INST)ohash_GetDataAtIndex(instohash,j);
      printf("\n %p %d,%d:", (void *)inst, inst_GetFirstWatched(inst),inst_GetSecondWatched(inst));
      subst_Print(Termstate, term_GetSymbstate(Termstate), inst_GetSubst(inst));
    }
  }
  printf("\n Instances: %u ", k);
}
