#ifdef DOC_BUILD_INTERNAL
#endif
#include "hlcl.h"
const unsigned MAX_VARS = 500;
const unsigned PROFIT_MATCHED_ATOMS = 20;
const unsigned PROFIT_INSTANCE = 5;
const unsigned PROFIT_PROPAGATION = 10;
const unsigned PROFIT_RESOLUTION = 30;
const unsigned FREQUENCY_NEXT = 10;
ARRAY hlcl_CreateTautoTerms(SCLSTATE State, TWFO Twfo)
{
  static const char *onefunction[] = {
    "XXf",
    "XXXXfff",
    "XXYYfff",
    "XYXYfff",
    "XYYXfff",
    "XXXfXff",
    "XXYfYff",
    "XYXfYff",
    "XYYfXff",
    "XXfXXff",
    "XXfYYff",
    "XYfXYff",
    "XYfYXff",
    "XXXffXf",
    "XXYffYf",
    "XYXffYf",
    "XYYffXf",
    "XXfXfXf",
    "XXfYfYf",
    "XYfXfYf",
    "XYfYfXf",
    "XXXff",
    "XYXff",
    "XYYff",
    "XXYXfff",
    "XYXXfff",
    "XYYYfff",
    "XYZXfff",
    "XYZYfff",
    "XYZZfff",
    "XXYfXff",
    "XYXfXff",
    "XYZfXff",
    "XYfXXff",
    "XYfYYff",
    "XYfZZff",
    "XYfXfXf"
  };
  static const char *twofunctions[] = {
    "XXf",
    "XXXgf",
    "XXgXf",
    "XXXXfff",
    "XXXXfgf",
    "XXXXggf",
    "XXYYfff",
    "XXYYfgf",
    "XYXYfff",
    "XYYXfff",
    "XXXfXff",
    "XXXfXgf",
    "XXXgXgf",
    "XXYfYff",
    "XYXfYff",
    "XYYfXff",
    "XYYfXgf",
    "XXfXXff",
    "XXfXXfg",
    "XXfYYff",
    "XXfYYfg",
    "XXgXXgf",
    "XYfXYff",
    "XYfYXff",
    "XYgXYgf",
    "XYgYXgf",
    "XXXffXf",
    "XXXfgXf",
    "XXXggXf",
    "XXYffYf",
    "XYXffYf",
    "XYYffXf",
    "XYYfgXf",
    "XXfXfXf",
    "XXfXgXf",
    "XXfYfYf",
    "XXfYgYf",
    "XXgXgXf",
    "XYfXfYf",
    "XYfYfXf",
    "XXXfg",
    "XYYfg",
    "XXfXg",
    "XXfYg",
    "XXXXfgg",
    "XXXXgfg",
    "XXYYfgg",
    "XYXXfgg",
    "XYXYfgg",
    "XYXYgfg",
    "XYYXfgg",
    "XYYXgfg",
    "XYYYfgg",
    "XYYYgfg",
    "XYZZfgg",
    "XXXfXgg",
    "XXXfYgg",
    "XXXgXfg",
    "XXYfYgg",
    "XXYgYfg",
    "XYXfYgg",
    "XYXgYfg",
    "XYYfXgg",
    "XYYfYgg",
    "XYYfZgg",
    "XYYgYfg",
    "XXfXXgg",
    "XXfXYfg",
    "XXfXYgg",
    "XXfYXfg",
    "XXfYXgg",
    "XXfYYgg",
    "XXfYZfg",
    "XXfYZgg",
    "XXgXXfg",
    "XXgYYfg",
    "XYfXXfg",
    "XYfXYgg",
    "XYfYXgg",
    "XYfYYfg",
    "XYfZZfg",
    "XYgXXfg",
    "XYgXYfg",
    "XYgYXfg",
    "XYgYYfg",
    "XYgZZfg",
    "XXXfgXg",
    "XXXfgYg",
    "XXXgfXg",
    "XXXgfYg",
    "XXYfgYg",
    "XXYgfYg",
    "XYXfgYg",
    "XYXgfYg",
    "XYYfgXg",
    "XYYfgYg",
    "XYYfgZg",
    "XXfXgXg",
    "XXfXgYg",
    "XXfYgXg",
    "XXfYgYg",
    "XXfYgZg",
    "XXgXfXg",
    "XXgXfYg",
    "XYfXgYg",
    "XYfYgXg",
    "XYgXfYg",
    "XYgYfXg",
    "XXg",
    "XXXff",
    "XYXff",
    "XYYff",
    "XYYgf",
    "XXXXgff",
    "XXXXggg",
    "XXYXfff",
    "XXYXfgf",
    "XXYYgff",
    "XXYYggf",
    "XXYYggg",
    "XYXXfff",
    "XYXXgff",
    "XYXYfgf",
    "XYXYgff",
    "XYXYggf",
    "XYXYggg",
    "XYYXgff",
    "XYYXggf",
    "XYYXggg",
    "XYYYfff",
    "XYYYgff",
    "XYZXfff",
    "XYZYfff",
    "XYZZfff",
    "XYZZgff",
    "XXXfXfg",
    "XXXgXff",
    "XXXgXgg",
    "XXYfXff",
    "XXYfXfg",
    "XXYfYgf",
    "XXYgXff",
    "XXYgYff",
    "XXYgYgf",
    "XXYgYgg",
    "XYXfXff",
    "XYXfXgf",
    "XYXgXff",
    "XYXgYff",
    "XYXgYgf",
    "XYXgYgg",
    "XYYfXfg",
    "XYYgXff",
    "XYYgXfg",
    "XYYgXgf",
    "XYYgXgg",
    "XYZfXff",
    "XYZgXff",
    "XXfXXgf",
    "XXfYYgf",
    "XXgXXff",
    "XXgXXgg",
    "XXgYYff",
    "XXgYYgf",
    "XXgYYgg",
    "XYfXXff",
    "XYfXXgf",
    "XYfXYfg",
    "XYfYYff",
    "XYfYYgf",
    "XYfZZff",
    "XYfZZgf",
    "XYgXXff",
    "XYgXXgf",
    "XYgXYff",
    "XYgXYgg",
    "XYgYXff",
    "XYgYXgg",
    "XYgYYff",
    "XYgYYgf",
    "XYgZZff",
    "XYgZZgf",
    "XXXggXg",
    "XXYfgXf",
    "XXYfgYf",
    "XXYggYf",
    "XXYggYg",
    "XYXggYf",
    "XYXggYg",
    "XYYggXf",
    "XYYggXg",
    "XXfXfXg",
    "XXfYfYg",
    "XXgXfXf",
    "XXgXgXg",
    "XXgYfYf",
    "XXgYfYg",
    "XXgYgYf",
    "XXgYgYg",
    "XYfXfXf",
    "XYfXfXg",
    "XYfXgXf",
    "XYfXgYf",
    "XYgXgYf",
    "XYgXgYg",
    "XYgYgXf",
    "XYgYgXg"
  };
  static const char *threefunctions[] = {
    "XXf",
    "XXXfh",
    "XXXgf",
    "XXXhf",
    "XYYfh",
    "XXfXh",
    "XXfYh",
    "XXgXf",
    "XXhXf",
    "XXXXfff",
    "XXXXfgf",
    "XXXXfhh",
    "XXXXgfh",
    "XXXXggf",
    "XXXXghf",
    "XXXXhfh",
    "XXXXhgf",
    "XXXXhhf",
    "XXXYgfh",
    "XXXYghf",
    "XXXYhgf",
    "XXYXgfh",
    "XXYXghf",
    "XXYXhgf",
    "XXYYfff",
    "XXYYfgf",
    "XXYYfhh",
    "XYXXfhh",
    "XYXYfff",
    "XYXYfhh",
    "XYXYhfh",
    "XYYXfff",
    "XYYXfhh",
    "XYYXhfh",
    "XYYYfhh",
    "XYYYgfh",
    "XYYYhfh",
    "XYZZfhh",
    "XXXfXff",
    "XXXfXgf",
    "XXXfXhh",
    "XXXfYhh",
    "XXXgXfh",
    "XXXgXgf",
    "XXXgXhf",
    "XXXhXfh",
    "XXXhXgf",
    "XXXhXhf",
    "XXYfYff",
    "XXYfYhh",
    "XXYgXfh",
    "XXYgXhf",
    "XXYhXgf",
    "XXYhYfh",
    "XYXfYff",
    "XYXfYhh",
    "XYXgXfh",
    "XYXgXhf",
    "XYXhXgf",
    "XYXhYfh",
    "XYYfXff",
    "XYYfXgf",
    "XYYfXhh",
    "XYYfYhh",
    "XYYfZhh",
    "XYYgYfh",
    "XYYhYfh",
    "XXfXXff",
    "XXfXXfg",
    "XXfXXfh",
    "XXfXXgh",
    "XXfXXhh",
    "XXfXYfh",
    "XXfXYgh",
    "XXfXYhh",
    "XXfYXfh",
    "XXfYXgh",
    "XXfYXhh",
    "XXfYYff",
    "XXfYYfg",
    "XXfYYfh",
    "XXfYYgh",
    "XXfYYhh",
    "XXfYZfh",
    "XXfYZgh",
    "XXfYZhh",
    "XXgXXfh",
    "XXgXXgf",
    "XXgXXhf",
    "XXgYYfh",
    "XXhXXfh",
    "XXhXXgf",
    "XXhXXhf",
    "XXhYYfh",
    "XYfXXfh",
    "XYfXYff",
    "XYfXYhh",
    "XYfYXff",
    "XYfYXhh",
    "XYfYYfh",
    "XYfZZfh",
    "XYgXXfh",
    "XYgXYgf",
    "XYgYXgf",
    "XYgYYfh",
    "XYgZZfh",
    "XYhXXfh",
    "XYhXYfh",
    "XYhXYhf",
    "XYhYXfh",
    "XYhYXhf",
    "XYhYYfh",
    "XYhZZfh",
    "XXXffXf",
    "XXXfgXf",
    "XXXfhXh",
    "XXXfhYh",
    "XXXgfXh",
    "XXXgfYh",
    "XXXggXf",
    "XXXghXf",
    "XXXhfXh",
    "XXXhfYh",
    "XXXhgXf",
    "XXXhhXf",
    "XXYffYf",
    "XXYfhYh",
    "XXYgfXh",
    "XXYghXf",
    "XXYhfYh",
    "XXYhgXf",
    "XYXffYf",
    "XYXfhYh",
    "XYXgfXh",
    "XYXghXf",
    "XYXhfYh",
    "XYXhgXf",
    "XYYffXf",
    "XYYfgXf",
    "XYYfhXh",
    "XYYfhYh",
    "XYYfhZh",
    "XXfXfXf",
    "XXfXgXf",
    "XXfXhXh",
    "XXfXhYh",
    "XXfYfYf",
    "XXfYgYf",
    "XXfYhXh",
    "XXfYhYh",
    "XXfYhZh",
    "XXgXfXh",
    "XXgXfYh",
    "XXgXgXf",
    "XXgXhXf",
    "XXhXfXh",
    "XXhXfYh",
    "XXhXgXf",
    "XXhXhXf",
    "XYfXfYf",
    "XYfXhYh",
    "XYfYfXf",
    "XYfYhXh",
    "XYgXfXh",
    "XYgXhXf",
    "XYgYfYh",
    "XYgYhYf",
    "XYhXfYh",
    "XYhXgXf",
    "XYhYfXh",
    "XYhYgYf"
  };
  static const char *notonefunction[] = {
    "XXf",
    "XXfnn",
    "XXnnf",
    "XXXff",
    "XYXff",
    "XYYff",
    "XnXnf",
    "XnnXf",
    "XXnXff",
    "XXnYff",
    "XYnXff",
    "XnXXff",
    "XnXYff",
    "XnYYff",
    "XXfnXf",
    "XXfnYf",
    "XYfnXf",
    "XnXfXf",
    "XXfnnnn",
    "XXnnfnn",
    "XXXffnn",
    "XYXffnn",
    "XYYffnn",
    "XnXnfnn",
    "XnnXfnn",
    "XXnnnnf",
    "XXXfnnf",
    "XYXfnnf",
    "XYYfnnf",
    "XXXnfnf",
    "XXXnnff",
    "XXXXfff",
    "XXYXfff",
    "XXYYfff",
    "XYXnnff",
    "XYYnnff",
    "XYXXfff",
    "XYXYfff",
    "XYYXfff",
    "XYYYfff",
    "XYZXfff",
    "XYZYfff",
    "XYZZfff",
    "XXnXnff",
    "XXnYnff",
    "XYnYnff",
    "XXnnXff",
    "XYnnXff",
    "XYnnYff",
    "XXXfXff",
    "XXYfXff",
    "XXYfYff",
    "XYXfXff",
    "XYYfXff",
    "XYZfXff",
    "XnXnnnf",
    "XnXXnff",
    "XnXYnff",
    "XnYXnff",
    "XnnXnnf",
    "XnnXXff",
    "XnnYXff",
    "XnnYYff",
    "XXfXXff",
    "XXfYYff",
    "XYfXXff",
    "XYfXYff",
    "XYfYYff",
    "XYfZZff",
    "XnnnXnf",
    "XXfnXnf",
    "XXfnYnf",
    "XYfnYnf",
    "XXnfXnf",
    "XnnnnXf",
    "XXnfnXf",
    "XYnfnXf",
    "XYnfnYf",
    "XXfXfXf",
    "XXfYfYf",
    "XYfXfXf"
  };
  static const char *nottwofunctions[] = {
    "XXng",
    "XnXg",
    "XXnfn",
    "XnXfn",
    "XXngnn",
    "XnXgnn",
    "XXnnng",
    "XXXfng",
    "XXXgng",
    "XXYfng",
    "XYXfng",
    "XXXngg",
    "XYXngg",
    "XYYngg",
    "XXnXgg",
    "XXnYgg",
    "XYnYgg",
    "XnXnng",
    "XnXXfg",
    "XnXXgg",
    "XnXYgg",
    "XnYXgg",
    "XnnXng",
    "XXfXng",
    "XXgXng",
    "XYgXng",
    "XYgYng",
    "XnnnXg",
    "XXfnXg",
    "XXgnXg",
    "XYfnXg",
    "XYfnYg",
    "XXngXg",
    "XXngYg",
    "XYngYg",
    "XnXgXg",
    "XnXgYg",
    "XnYgXg",
    "XXnfnnn",
    "XnXfnnn",
    "XXnnnfn",
    "XXXfnfn",
    "XXXgnfn",
    "XXYgnfn",
    "XYXgnfn",
    "XXXnffn",
    "XYXnffn",
    "XYYnffn",
    "XXnXffn",
    "XXnYffn",
    "XYnYffn",
    "XnXnnfn",
    "XnXXffn",
    "XnXXgfn",
    "XnXYffn",
    "XnYXffn",
    "XnnXnfn",
    "XXfXnfn",
    "XXgXnfn",
    "XYfXnfn",
    "XYfYnfn",
    "XnnnXfn",
    "XXfnXfn",
    "XXgnXfn",
    "XYgnXfn",
    "XYgnYfn",
    "XXnfXfn",
    "XXnfYfn",
    "XYnfYfn",
    "XnXfXfn",
    "XnXfYfn",
    "XnYfXfn",
    "XXXnfng",
    "XXYnfng",
    "XYYnfng",
    "XXnXfng",
    "XYnXfng",
    "XYnYfng",
    "XXnXnfg",
    "XXnXngg",
    "XXnYngg",
    "XYnXngg",
    "XnXXngg",
    "XnXYngg",
    "XnYYngg",
    "XnXnXgg",
    "XnYnXgg",
    "XnYnYgg",
    "XXngXng",
    "XXngYng",
    "XYngXng",
    "XnXgXng",
    "XnXgYng",
    "XnYgYng",
    "XXnfnXg",
    "XXnfnYg",
    "XYnfnXg",
    "XnXfnXg",
    "XnXfnYg",
    "XnYfnYg",
    "XnXnfXg",
    "XnXngXg",
    "XnYngXg",
    "XnYngYg"
  };
  const char **patterns;
  const char *pattern;
  unsigned assignment[3], used[3];
  unsigned patterncount, functioncount, binaryfunctioncount, functionindex, i, j, sp, f, g, h;
  ARRAY result, predicates, functions;
  TERM stack[16], term, atom, sharedatom;
  SYMBOL predicate, function, var, notfunction, binaryfunctions[3];
  BOOL hasnot;
  int index;
  TERMSTATE termstate;
  SYMBSTATE symbstate;
  MEMORY mem;
  mem = state_GetMemory(State);
  termstate = state_GetTermstate(State);
  symbstate = state_GetSymbstate(State);
  predicates = state_GetPredicates(State);
  functions = state_GetFunctions(State);
  functioncount = array_GetSize(functions);
  if (array_GetSize(predicates) != 1 || functioncount < 1 || functioncount > 3) {
    misc_StartUserErrorReport();
    misc_UserErrorReport("%s: LCL needs exactly one predicate and one to three functions.", __func__);
    misc_FinishUserErrorReport();
  }
  predicate = (SYMBOL)array_GetElement(predicates, 0);
  if (symbol_GetArity(symbstate, predicate) != 1) {
    misc_StartUserErrorReport();
    misc_UserErrorReport("%s: LCL needs one unary predicate.", __func__);
    misc_FinishUserErrorReport();
  }
  hasnot = FALSE;
  notfunction = 0;
  binaryfunctioncount = 0;
  for (i = 0; i < functioncount; i++) {
    function = (SYMBOL)array_GetElement(functions, i);
    if (symbol_GetArity(symbstate, function) == 1) {
      if (hasnot) {
 misc_StartUserErrorReport();
 misc_UserErrorReport("%s: LCL needs at most one unary function.", __func__);
 misc_FinishUserErrorReport();
      }
      hasnot = TRUE;
      notfunction = function;
    }
    else if (symbol_GetArity(symbstate, function) == 2) {
      binaryfunctions[binaryfunctioncount++] = function;
    }
    else {
      misc_StartUserErrorReport();
      misc_UserErrorReport("%s: LCL needs only one unary function and binary functions.", __func__);
      misc_FinishUserErrorReport();
    }
  }
  if (hasnot) {
    if (binaryfunctioncount == 1) {
      patterns = notonefunction;
      patterncount = sizeof(notonefunction) / sizeof(notonefunction[0]);
    }
    else if (binaryfunctioncount == 2) {
      patterns = nottwofunctions;
      patterncount = sizeof(nottwofunctions) / sizeof(nottwofunctions[0]);
    }
    else {
      misc_StartUserErrorReport();
      misc_UserErrorReport("%s: LCL with not needs one or two binary functions.", __func__);
      misc_FinishUserErrorReport();
    }
  }
  else {
    if (binaryfunctioncount == 1) {
      patterns = onefunction;
      patterncount = sizeof(onefunction) / sizeof(onefunction[0]);
    }
    else if (binaryfunctioncount == 2) {
      patterns = twofunctions;
      patterncount = sizeof(twofunctions) / sizeof(twofunctions[0]);
    }
    else if (binaryfunctioncount == 3) {
      patterns = threefunctions;
      patterncount = sizeof(threefunctions) / sizeof(threefunctions[0]);
    }
    else {
      misc_StartUserErrorReport();
      misc_UserErrorReport("%s: LCL needs at least one binary function.", __func__);
      misc_FinishUserErrorReport();
    }
  }
  if (symbol_GetMaxVars(symbstate) < 3)
    symbol_AdjustStateMaxVarsLimit(symbstate, 3);
  result = array_Create(mem, patterncount * 6);
  for (i = 0; i < patterncount; i++) {
    pattern = patterns[i];
    used[0] = used[1] = used[2] = FALSE;
    for (j = 0; pattern[j] != '\0'; j++) {
      if (pattern[j] >= 'f' && pattern[j] <= 'h')
 used[pattern[j] - 'f'] = TRUE;
    }
    for (f = 0; f < (used[0] ? binaryfunctioncount : 1); f++) {
      assignment[0] = f;
      for (g = 0; g < (used[1] ? binaryfunctioncount : 1); g++) {
 assignment[1] = g;
 if (used[0] && used[1] && assignment[0] == assignment[1])
   continue;
 for (h = 0; h < (used[2] ? binaryfunctioncount : 1); h++) {
   assignment[2] = h;
   if ((used[0] && used[2] && assignment[0] == assignment[2]) ||
       (used[1] && used[2] && assignment[1] == assignment[2]))
     continue;
   sp = 0;
   for (j = 0; pattern[j] != '\0'; j++) {
     if (pattern[j] >= 'f' && pattern[j] <= 'h') {
       if (sp < 2) {
  misc_StartErrorReport();
  misc_ErrorReport("\n In %s: Broken LCL tautology pattern.", __func__);
  misc_FinishErrorReport();
       }
       functionindex = assignment[pattern[j] - 'f'];
       function = binaryfunctions[functionindex];
       term = term_CreateArity(termstate, function, 2);
       term_SetArgument(term, 1, stack[--sp]);
       term_SetArgument(term, 0, stack[--sp]);
       stack[sp++] = term;
     }
     else if (pattern[j] == 'n') {
       if (!hasnot || sp < 1) {
  misc_StartErrorReport();
  misc_ErrorReport("\n In %s: Broken LCL tautology pattern.", __func__);
  misc_FinishErrorReport();
       }
       term = term_CreateArity(termstate, notfunction, 1);
       term_SetArgument(term, 0, stack[--sp]);
       stack[sp++] = term;
     }
     else {
       var = symbol_MinimalStandardVar() + (SYMBOL)(pattern[j] - 'X');
       stack[sp++] = term_CreateArity(termstate, var, 0);
     }
   }
   if (sp != 1) {
     misc_StartErrorReport();
     misc_ErrorReport("\n In %s: Broken LCL tautology pattern.", __func__);
     misc_FinishErrorReport();
   }
   atom = term_CreateArity(termstate, predicate, 1);
   term_SetArgument(atom, 0, stack[0]);
   sharedatom = sharing_GetSharedTerm(state_GetSharer(State), atom);
   if (!array_ContainsElement(result, (intptr_t)sharedatom, &index))
     result = array_Add(mem, result, (intptr_t)sharedatom);
 }
      }
    }
  }
  return result;
}
TERM hlcl_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)hlcl_RenameVariablesInTerm(Termstate, (TERM)Term[i], Offset));
  }
  result = term_Create(Termstate, top, args);
  array_Delete(term_GetMemory(Termstate), args);
  return result;
}
BOOL hlcl_IsInstance(HLCLSTATE Hlcl, TERM Atom, TERM Ground) {
  subst_ContextStart(state_GetSubststate(Hlcl->sclstate), state_GetSymbstate(Hlcl->sclstate));
  if (subst_TermUnifyIdenticalVarsNoTypes(state_GetSubststate(Hlcl->sclstate), state_GetTermstate(Hlcl->sclstate), state_GetSymbstate(Hlcl->sclstate), Atom, Ground, FALSE)) {
    subst_ContextStop(state_GetSubststate(Hlcl->sclstate));
    return TRUE;
  }
  subst_ContextStop(state_GetSubststate(Hlcl->sclstate));
  return FALSE;
}
TERM hlcl_TriviallyInstantiate(HLCLSTATE Hlcl, TERM Atom) {
  TERM copy;
  copy = term_Copy(state_GetTermstate(Hlcl->sclstate), Atom);
  return sharing_GetSharedTerm(state_GetSharer(Hlcl->sclstate), subst_SubstApplyTerm(state_GetTermstate(Hlcl->sclstate), copy, Hlcl->triviallyInstantiate, TRUE));
}
unsigned hlcl_GetProfit(HLCLSTATE Hlcl, TERM Atom) {
  return term_GetProfit(Atom) + Hlcl->maxsize - term_Size(Atom);
}
void hlcl_AddActive(HLCLSTATE Hlcl, TERM Atom, BOOL Phase, unsigned Profit)
{
  if (term_Size(Atom) > Hlcl->maxsize) {
    return;
  }
  if (!term_IsActive(Atom)) {
    term_SetActive(Atom, TRUE);
    Hlcl->active = array_Add(Hlcl->memory, Hlcl->active, (intptr_t)Atom);
    term_SetHasPhase(Atom, TRUE);
    term_PropertySetPhase(Atom, Phase);
    term_SetProfit(Atom, 0);
  }
  term_IncreaseProfit(Atom, Profit);
}
void hlcl_MatchAxiomWithAtom(HLCLSTATE Hlcl, TERM Axiom, TERM Atom, TERM Original, unsigned Profit)
{
  unsigned i;
  TERM unified;
  if (!term_IsComplex(Atom)) {
    return;
  }
  subst_ContextStart(state_GetSubststate(Hlcl->sclstate), state_GetSymbstate(Hlcl->sclstate));
  if (subst_TermUnifyIdenticalVarsNoTypes(state_GetSubststate(Hlcl->sclstate), state_GetTermstate(Hlcl->sclstate), state_GetSymbstate(Hlcl->sclstate), Axiom, Atom, TRUE)) {
    unified = sharing_GetSharedTerm(state_GetSharer(Hlcl->sclstate), subst_ContextTermApplyToTerm(state_GetSubststate(Hlcl->sclstate), state_GetTermstate(Hlcl->sclstate), Original));
    hlcl_AddActive(Hlcl, hlcl_TriviallyInstantiate(Hlcl, unified), FALSE, Profit);
  }
  subst_ContextStop(state_GetSubststate(Hlcl->sclstate));
  for (i = 0; i < term_GetArity(Atom); i++) {
    hlcl_MatchAxiomWithAtom(Hlcl, Axiom, term_GetArgument(Atom, i), Original, Profit);
  }
}
void hlcl_MatchAxiomWithClause(HLCLSTATE Hlcl, TERM Axiom, CLAUSE Clause, TERM Original, unsigned Profit)
{
  unsigned i, offset;
  offset = term_MaxVar(state_GetTermstate(Hlcl->sclstate), Axiom) + 1;
  for (i = 0; i < clause_GetFolLiterals(Clause); i++) {
    hlcl_MatchAxiomWithAtom(Hlcl, Axiom, sharing_GetSharedTerm(state_GetSharer(Hlcl->sclstate), hlcl_RenameVariablesInTerm(state_GetTermstate(Hlcl->sclstate), term_GetArgument(clause_GetAtom(Clause, i), 0), offset)), Original, Profit);
  }
}
void hlcl_MatchAtoms(HLCLSTATE Hlcl, TERM Atom1, TERM Atom2)
{
  TERM copy, unified;
  copy = sharing_GetSharedTerm(state_GetSharer(Hlcl->sclstate), hlcl_RenameVariablesInTerm(state_GetTermstate(Hlcl->sclstate), Atom2, term_MaxVar(state_GetTermstate(Hlcl->sclstate), Atom1) + 1));
  subst_ContextStart(state_GetSubststate(Hlcl->sclstate), state_GetSymbstate(Hlcl->sclstate));
  if (subst_TermUnifyIdenticalVarsNoTypes(state_GetSubststate(Hlcl->sclstate), state_GetTermstate(Hlcl->sclstate), state_GetSymbstate(Hlcl->sclstate), Atom1, copy, TRUE)) {
    unified = sharing_GetSharedTerm(state_GetSharer(Hlcl->sclstate), subst_ContextTermApplyToTerm(state_GetSubststate(Hlcl->sclstate), state_GetTermstate(Hlcl->sclstate), Atom1));
    hlcl_AddActive(Hlcl, hlcl_TriviallyInstantiate(Hlcl, unified), FALSE, PROFIT_MATCHED_ATOMS);
  }
  subst_ContextStop(state_GetSubststate(Hlcl->sclstate));
}
HLCLSTATE hlcl_Create(SCLSTATE State, TWFO Twfo)
{
  MEMORY mem;
  HLCLSTATE result;
  TERM thisIsJustA;
  CLAUSE tmpClause, otherClause;
  unsigned i, j, k, l;
  mem = state_GetMemory(State);
  result = memory_Malloc(mem, sizeof(HLCL_NODE));
  result->sclstate = State;
  result->twfo = Twfo;
  result->memory = mem;
  result->tautoterms = hlcl_CreateTautoTerms(State, Twfo);
  thisIsJustA = sharing_GetSharedTerm(state_GetSharer(State), term_CreateArity(state_GetTermstate(State), (SYMBOL)array_GetElement(state_GetConstants(State), 0), 0));
  result->triviallyInstantiate = subst_Create(mem, MAX_VARS);
  for (i = 0; i < MAX_VARS; i++) {
    subst_SetValue(result->triviallyInstantiate, i, thisIsJustA);
  }
  result->active = array_Create(mem, 128);
  result->maxsize = 60;
  result->untilNext = FREQUENCY_NEXT;
  for (i = 0; i < array_GetSize(result->tautoterms); i++) {
    for (j = 0; j < array_GetSize(state_GetClauses(State)); j++) {
      hlcl_MatchAxiomWithClause(result, term_GetArgument((TERM)array_GetElement(result->tautoterms, i), 0), (CLAUSE)array_GetElement(state_GetClauses(State), j), (TERM)array_GetElement(result->tautoterms, i), array_GetSize(result->tautoterms) - i);
    }
  }
  for (i = 0; i < array_GetSize(state_GetClauses(State)); i++) {
    tmpClause = (CLAUSE)array_GetElement(state_GetClauses(State), i);
    for (j = 0; j < array_GetSize(state_GetClauses(State)); j++) if (i != j) {
      otherClause = (CLAUSE)array_GetElement(state_GetClauses(State), j);
      for (k = 0; k < clause_GetPremiseLiterals(tmpClause); k++) {
        for (l = clause_GetPremiseLiterals(otherClause); l < clause_GetFolLiterals(otherClause); l++) {
          hlcl_MatchAtoms(result, clause_GetAtom(tmpClause, k), clause_GetAtom(otherClause, l));
        }
      }
    }
  }
  for (i = 0; i < array_GetSize(state_GetClauses(State)); i++) {
    tmpClause = (CLAUSE)array_GetElement(state_GetClauses(State), i);
    for (j = 0; j < clause_GetFolLiterals(tmpClause); j++) {
      hlcl_AddActive(result, hlcl_TriviallyInstantiate(result, clause_GetAtom(tmpClause, j)), j < clause_GetPremiseLiterals(tmpClause), PROFIT_INSTANCE);
    }
  }
  return result;
}
void hlcl_Delete(MEMORY Mem, HLCLSTATE Hlcl)
{
  array_Delete(Mem, Hlcl->tautoterms);
  array_Delete(Mem, Hlcl->active);
  subst_Delete(Mem, Hlcl->triviallyInstantiate);
  memory_Free(Mem, Hlcl, sizeof(HLCL_NODE));
}
unsigned hlcl_ActiveAtoms(HLCLSTATE Hlcl)
{
  return array_GetSize(Hlcl->active);
}
TERM hlcl_NextTrailLiteral(SCLSTATE State, HLCLSTATE Hlcl, TRAIL Trail, TWFO Twfo)
{
  unsigned i, maxscore;
  int j;
  TERM lit, cur;
  for (j = array_GetSize(prlits_GetStack(twfo_GetPrlit(Twfo))) - 1; j >= 0 && prlits_GetAnnoLitTrailsize((PRLITS_ANNO_LIT)array_GetElement(prlits_GetStack(twfo_GetPrlit(Twfo)), j)) == trail_GetSize(Trail); j--) {
    hlcl_AddActive(Hlcl, hlcl_TriviallyInstantiate(Hlcl, prlits_GetAnnoLitAtom((PRLITS_ANNO_LIT)array_GetElement(prlits_GetStack(twfo_GetPrlit(Twfo)), j))), FALSE, PROFIT_PROPAGATION);
  }
  maxscore = 0;
  for (i = 0; i < array_GetSize(Hlcl->active); i++) {
    cur = (TERM)array_GetElement(Hlcl->active, i);
    if (!trail_IsLitSet(Trail, cur, NULL) && hlcl_GetProfit(Hlcl, cur) > maxscore) {
      if (maxscore == 0) {
        if (Hlcl->untilNext == 0) {
          Hlcl->untilNext = FREQUENCY_NEXT;
          maxscore = hlcl_GetProfit(Hlcl, cur);
          lit = cur;
          break;
        } else {
          Hlcl->untilNext--;
        }
      }
      maxscore = hlcl_GetProfit(Hlcl, cur);
      lit = cur;
    }
  }
  if (maxscore == 0) {
    return (TERM)NULL;
  }
  term_SetPropagatable(lit, FALSE);
  for (i = 0; i < array_GetSize(prlits_GetStack(twfo_GetPrlit(Twfo))); i++) {
    if (hlcl_IsInstance(Hlcl, prlits_GetAnnoLitAtom((PRLITS_ANNO_LIT)array_GetElement(prlits_GetStack(twfo_GetPrlit(Twfo)), i)), lit)) {
      term_SetPropagatable(lit, TRUE);
      term_SetPrLitIndex(lit, i);
      break;
    }
  }
  return lit;
}
void hlcl_UpdateBacktrack(SCLSTATE State, HLCLSTATE Hlcl, TRAIL Trail, TWFO Twfo, unsigned Level)
{
}
void hlcl_UpdateRestart(SCLSTATE State, HLCLSTATE Hlcl, TRAIL Trail, TWFO Twfo)
{
  hlcl_UpdateBacktrack(State, Hlcl, Trail, Twfo, 0);
}
void hlcl_UpdateReduction(SCLSTATE State, HLCLSTATE Hlcl, TRAIL Trail, TWFO Twfo)
{
}
BOOL hlcl_PerformReduction(SCLSTATE State, HLCLSTATE Hlcl)
{
  return FALSE;
}
void hlcl_UpdateNewResolution(SCLSTATE State, HLCLSTATE Hlcl, TERM Atom, CLAUSE Resolvent, SUBST Grounding, ARRAY Parents)
{
  term_IncreaseProfit(Atom, PROFIT_RESOLUTION);
}
void hlcl_UpdateLearnedClause(SCLSTATE State, HLCLSTATE Hlcl, TRAIL Trail, CLAUSE Clause, SUBST Subst)
{
  unsigned i, j, k;
  CLAUSE other;
  for (i = 0; i < array_GetSize(Hlcl->tautoterms); i++) {
    hlcl_MatchAxiomWithClause(Hlcl, term_GetArgument((TERM)array_GetElement(Hlcl->tautoterms, i), 0), Clause, (TERM)array_GetElement(Hlcl->tautoterms, i), array_GetSize(Hlcl->tautoterms) - i);
  }
  for (i = 0; i < array_GetSize(state_GetClauses(Hlcl->sclstate)); i++) {
    other = (CLAUSE)array_GetElement(state_GetClauses(Hlcl->sclstate), i);
    for (j = 0; j < clause_GetPremiseLiterals(Clause); j++) {
      for (k = clause_GetPremiseLiterals(other); k < clause_GetFolLiterals(other); k++) {
        hlcl_MatchAtoms(Hlcl, clause_GetAtom(Clause, j), clause_GetAtom(other, k));
      }
    }
    for (j = clause_GetPremiseLiterals(Clause); j < clause_GetFolLiterals(Clause); j++) {
      for (k = 0; k < clause_GetPremiseLiterals(other); k++) {
        hlcl_MatchAtoms(Hlcl, clause_GetAtom(Clause, j), clause_GetAtom(other, k));
      }
    }
  }
  for (i = 0; i < clause_GetFolLiterals(Clause); i++) {
    hlcl_AddActive(Hlcl, hlcl_TriviallyInstantiate(Hlcl, clause_GetAtom(Clause, i)), i < clause_GetPremiseLiterals(Clause), PROFIT_INSTANCE);
  }
}
BOOL hlcl_ExtendActiveLiterals(SCLSTATE State, HLCLSTATE Hlcl, TRAIL Trail, BOOL *DetectSAT)
{
  *DetectSAT = FALSE;
  return TRUE;
}
BOOL hlcl_PerformSATTest(SCLSTATE State, HLCLSTATE Hlcl)
{
  return FALSE;
}
BOOL hlcl_PerformSATAbstraction(SCLSTATE State, HLCLSTATE Hlcl)
{
  return FALSE;
}
BOOL hlcl_IsApplicable(SCLSTATE State) {
  unsigned functioncount, binaryfunctioncount, i;
  SYMBOL predicate, function;
  CLAUSE clause;
  ARRAY predicates, functions, clauses;
  BOOL hasnot, has_modus_ponens;
  predicates = state_GetPredicates(State);
  functions = state_GetFunctions(State);
  clauses = state_GetClauses(State);
  functioncount = array_GetSize(functions);
  if (array_GetSize(predicates) != 1 || functioncount < 1 || functioncount > 3 || array_GetSize(clauses) > 10) {
    return FALSE;
  }
  predicate = (SYMBOL)array_GetElement(predicates, 0);
  if (symbol_GetArity(state_GetSymbstate(State), predicate) != 1) {
    return FALSE;
  }
  hasnot = FALSE;
  binaryfunctioncount = 0;
  for (i = 0; i < functioncount; i++) {
    function = (SYMBOL)array_GetElement(functions, i);
    if (symbol_GetArity(state_GetSymbstate(State), function) == 1) {
      if (hasnot) {
        return FALSE;
      }
      hasnot = TRUE;
    }
    else if (symbol_GetArity(state_GetSymbstate(State), function) == 2) {
      binaryfunctioncount++;
    }
    else {
      return FALSE;
    }
  }
  if (hasnot) {
    if (binaryfunctioncount != 1 && binaryfunctioncount != 2) {
      return FALSE;
    }
  }
  else {
    if (binaryfunctioncount != 1 && binaryfunctioncount != 2 && binaryfunctioncount != 3) {
      return FALSE;
    }
  }
  has_modus_ponens = FALSE;
  for (i = 0; i < array_GetSize(clauses); i++) {
    clause = (CLAUSE)array_GetElement(clauses, i);
    if (clause_GetFolLiterals(clause) != 3 || clause_GetConclusionLiterals(clause) != 1) {
      continue;
    }
    if (!term_IsVariable(state_GetTermstate(State), term_GetArgument(clause_GetAtom(clause, 2), 0))) {
      continue;
    }
    if (term_IsVariable(state_GetTermstate(State), term_GetArgument(clause_GetAtom(clause, 0), 0))) {
      if (term_IsComplex(term_GetArgument(clause_GetAtom(clause, 1), 0))) {
        has_modus_ponens = TRUE;
      }
    }
    if (term_IsVariable(state_GetTermstate(State), term_GetArgument(clause_GetAtom(clause, 1), 0))) {
      if (term_IsComplex(term_GetArgument(clause_GetAtom(clause, 0), 0))) {
        has_modus_ponens = TRUE;
      }
    }
  }
  if (!has_modus_ponens) {
    return FALSE;
  }
  return TRUE;
}
void hlcl_Print(SCLSTATE State, HLCLSTATE Hlcl)
{
  printf("\n\n==HLCL Tautoterms: %u ",
  Hlcl->tautoterms ? (unsigned)array_GetSize(Hlcl->tautoterms) : 0);
}
void hlcl_PrintTautoTerms(SCLSTATE State, HLCLSTATE Hlcl)
{
  unsigned i;
  printf("\n\n==HLCL Tautoterms: %u ", (unsigned)array_GetSize(Hlcl->tautoterms));
  for (i = 0; i < array_GetSize(Hlcl->tautoterms); i++) {
    printf("\n");
    term_PrintPrefix(state_GetTermstate(State), (TERM)array_GetElement(Hlcl->tautoterms, i));
  }
}
void hlcl_PrintStat(HLCLSTATE Hlcl)
{
  printf("\n HLCL State Tautoterms: %u ",
  Hlcl->tautoterms ? (unsigned)array_GetSize(Hlcl->tautoterms) : 0);
}
void hlcl_PrintScores(HLCLSTATE Hlcl)
{
  unsigned i;
  printf("\n-------------------------------\n");
  for (i = 0; i < array_GetSize(Hlcl->active); i++) {
    printf("%u: %u (", i, hlcl_GetProfit(Hlcl, (TERM)array_GetElement(Hlcl->active, i)));
    term_PrettyPrint(state_GetTermstate(Hlcl->sclstate), (TERM)array_GetElement(Hlcl->active, i));
    printf(")\n");
  }
}
