#include "subsume.h"
#include "sharing.h"
static const unsigned int subsume_MIN_LITERALS_FOR_FILTER = 4;
BOOL subsume_ContextFilter(
  const SCLSTATE State,
  const CLAUSE C,
  const CLAUSE D
) {
  FOLSTATE folstate;
  SUBSTSTATE subststate;
  SYMBSTATE symbstate;
  TERMSTATE termstate;
  unsigned c_index, d_index, c_len, d_start, d_end;
  BOOL found;
  folstate = state_GetFolstate(State);
  subststate = state_GetSubststate(State);
  symbstate = state_GetSymbstate(State);
  termstate = state_GetTermstate(State);
  c_len = clause_GetFolLiterals(C);
  for (c_index = 0; c_index < c_len; c_index++) {
    if (C[c_index] == (uintptr_t) NULL) {
      continue;
    }
    found = FALSE;
    clause_RangeFolLiterals(D, clause_LiteralIsPositive(C, c_index), &d_start, &d_end);
    for (d_index = d_start; d_index < d_end; d_index++) {
      if (D[d_index] == (uintptr_t) NULL) {
        continue;
      }
      subst_ContextStackPush(subststate);
      found = subst_TermMatchTermsStackFol(
        subststate,
        symbstate,
        termstate,
        folstate,
        (TERM) C[c_index], (TYPING) NULL,
        (TERM) D[d_index], (TYPING) NULL
      );
      subst_ContextStackPop(subststate);
      if (found) {
        break;
      }
    }
    if (!found) {
      return FALSE;
    }
  }
  return TRUE;
}
BOOL subsume_ExistsMatcherFromIndex(
  const SCLSTATE State,
  const CLAUSE C,
  const CLAUSE D,
  const unsigned C_index
) {
  FOLSTATE folstate;
  SUBSTSTATE subststate;
  SYMBSTATE symbstate;
  TERMSTATE termstate;
  unsigned d_index, d_start, d_end;
  if (C_index == clause_GetFolLiterals(C)) {
    return TRUE;
  }
  if (C[C_index] == (uintptr_t) NULL) {
    return subsume_ExistsMatcherFromIndex(State, C, D, C_index + 1);
  }
  folstate = state_GetFolstate(State);
  subststate = state_GetSubststate(State);
  symbstate = state_GetSymbstate(State);
  termstate = state_GetTermstate(State);
  clause_RangeFolLiterals(D, clause_LiteralIsPositive(C, C_index), &d_start, &d_end);
  for (d_index = d_start; d_index < d_end; d_index++) {
    if (D[d_index] == (uintptr_t) NULL) {
      continue;
    }
    subst_ContextStackPush(subststate);
    if (
      subst_TermMatchTermsStackFol(
        subststate,
        symbstate,
        termstate,
        folstate,
        (TERM) C[C_index], (TYPING) NULL,
        (TERM) D[d_index], (TYPING) NULL
      ) &&
      subsume_ExistsMatcherFromIndex(State, C, D, C_index + 1)
    ) {
      return TRUE;
    }
    subst_ContextStackPop(subststate);
  }
  return FALSE;
}
BOOL subsume_Check(SCLSTATE State, CLAUSE C, CLAUSE D)
{
  TERMSTATE termstate;
  SUBSTSTATE subststate;
  SYMBSTATE symbstate;
  BOOL result;
  if (C == D) {
    return FALSE;
  }
  misc_ASSERT(clause_GetVariables(C) <= subst_MaxVars(state_GetSubststate(State)));
  misc_ASSERT(clause_GetVariables(D) <= subst_MaxVars(state_GetSubststate(State)));
  termstate = state_GetTermstate(State);
  if (
    (clause_GetPremiseLiterals(C) > clause_GetPremiseLiterals(D)) ||
    (clause_GetConclusionLiterals(C) > clause_GetConclusionLiterals(D)) ||
    (clause_GetSymbolOccurrences(termstate, C)
      >
     clause_GetSymbolOccurrences(termstate, D))
  ) {
    result = FALSE;
  } else {
    subststate = state_GetSubststate(State);
    symbstate = state_GetSymbstate(State);
    subst_ContextStart(subststate, symbstate);
    subst_ContextStackStart(subststate);
    if (clause_GetFolLiterals(C) >= subsume_MIN_LITERALS_FOR_FILTER) {
      result = subsume_ContextFilter(State, C, D);
      if (!result) {
        subst_ContextStackStop(subststate);
        subst_ContextStop(subststate);
        return FALSE;
      }
    }
    result = subsume_ExistsMatcherFromIndex(State, C, D, 0);
    subst_ContextStackStop(subststate);
    subst_ContextStop(subststate);
  }
  return result;
}
BOOL subsume_CheckWithResolvableLiterals(SCLSTATE State, CLAUSE C, unsigned int C_index, CLAUSE D, unsigned int D_index)
{
  SUBSTSTATE subststate;
  SYMBSTATE symbstate;
  FOLSTATE folstate;
  TERMSTATE termstate;
  BOOL result;
  unsigned int c_premises, c_conclusions, d_premises, d_conclusions;
  TERM c_l, d_l;
  termstate = state_GetTermstate(State);
  if (C == D) {
    return FALSE;
  }
  misc_ASSERT(clause_LiteralIsPositive(C, C_index) ^ clause_LiteralIsPositive(D, D_index));
  misc_ASSERT(clause_GetVariables(C) <= subst_MaxVars(state_GetSubststate(State)));
  misc_ASSERT(clause_GetVariables(D) <= subst_MaxVars(state_GetSubststate(State)));
  result = FALSE;
  if (!clause_IsMarkedNullAtoms(C) && !clause_IsMarkedNullAtoms(D)) {
    c_premises = clause_GetPremiseLiterals(C);
    c_conclusions = clause_GetConclusionLiterals(C);
    d_premises = clause_GetPremiseLiterals(D);
    d_conclusions = clause_GetConclusionLiterals(D);
    if (clause_LiteralIsPositive(C, C_index)) {
      c_conclusions -= 1;
      d_premises -= 1;
    } else {
      d_conclusions -= 1;
      c_premises -= 1;
    }
    if ((c_premises > d_premises) ||
 (c_conclusions > d_conclusions) ||
 (clause_GetSymbolOccurrences(termstate, C) - term_CountSymbolOccurrences(termstate, (TERM) C[C_index])
  >
  clause_GetSymbolOccurrences(termstate, D) - term_CountSymbolOccurrences(termstate, (TERM) D[D_index]))
 ) {
      return FALSE;
    }
  }
  subststate = state_GetSubststate(State);
  symbstate = state_GetSymbstate(State);
  folstate = state_GetFolstate(State);
  subst_ContextStart(subststate, symbstate);
  c_l = (TERM) C[C_index];
  d_l = (TERM) D[D_index];
  result = subst_FolTermMatchTerms(
       subststate,
       symbstate,
       termstate,
       folstate,
       c_l, (TYPING) NULL,
       d_l, (TYPING) NULL
       );
  if (result) {
    C[C_index] = (uintptr_t) NULL;
    D[D_index] = (uintptr_t) NULL;
    subst_ContextStackStart(subststate);
    result = subsume_ExistsMatcherFromIndex(State, C, D, 0);
    subst_ContextStackStop(subststate);
    C[C_index] = (uintptr_t) c_l;
    D[D_index] = (uintptr_t) d_l;
  }
  subst_ContextStop(subststate);
  return result;
}
ARRAY subsume_Sweep(
  const MEMORY Mem,
  const TERMSTATE Termstate,
  const ARRAY Clauses
) {
  CLAUSE clause;
  int i, j;
  j = 0;
  for (i = 0; i < array_GetSize(Clauses); i++) {
    clause = (CLAUSE) array_GetElement(Clauses, i);
    if (clause == NULL) {
      continue;
    }
    if (clause_IsMarkedDelete(clause)) {
      clause_Delete(Mem, Termstate, clause);
      array_SetElement(Clauses, i, (intptr_t) NULL);
      continue;
    }
    array_SetElement(Clauses, j++, (intptr_t) clause);
  }
  array_SetSize(Clauses, j);
  return Clauses;
}
ARRAY subsume_Backward(
  const SCLSTATE State,
  const CLAUSE Clause,
  ARRAY Pending
) {
  ARRAY clauses;
  CLAUSE subsumed;
  MEMORY memory;
  TERMSTATE termstate;
  int i;
  clauses = state_GetClauses(State);
  memory = state_GetMemory(State);
  termstate = state_GetTermstate(State);
  for (i = 0; Pending != NULL && i < array_GetSize(Pending); i++) {
    subsumed = (CLAUSE) Pending[i];
    if (
      subsumed != NULL &&
      !clause_IsMarkedDelete(subsumed) &&
      subsume_Check(State, Clause, subsumed)
    ) {
      clause_MarkDelete(subsumed, TRUE);
    }
  }
  if (Pending != NULL) {
    Pending = subsume_Sweep(memory, termstate, Pending);
  }
  for (i = 0; clauses != NULL && i < array_GetSize(clauses); i++) {
    subsumed = (CLAUSE) clauses[i];
    if (!clause_IsMarkedDelete(subsumed) && subsume_Check(State, Clause, subsumed)) {
      clause_MarkDelete(subsumed, TRUE);
    }
  }
  return Pending;
}
