#ifndef LMODEL_H
#define LMODEL_H 
#include <stdlib.h>
#include "array.h"
#include "term.h"
#include "fol.h"
#include "state.h"
#include "sorting.h"
#include "trail.h"
#include "clause.h"
#include "folsubst.h"
#include "prlits.h"
#define LMODEL_PRINTABLE_REPRESENTATION "enabled if defined"
#define LMODEL_GLOBAL_VERBOSITY 0
typedef struct lmodel_binding {
  SYMBOL symb;
  unsigned arity;
  unsigned idx;
  TERM dummyVar;
  unsigned depth;
} LMODEL_BINDING_NODE, *LMODEL_BINDING;
typedef struct lmodstate {
  SCLSTATE sclstate;
  int symbOffset;
  ARRAY symbToID;
  ARRAY cfidToSymb;
  unsigned maxVar, nextVar, currentBindingDepth;
  LMODEL_BINDING bindings;
  ARRAY boundVars;
  ARRAY bindingDepths;
  unsigned depth;
  unsigned long long backtrackNr;
  unsigned onCounterexample_MaxVar;
  SUBST onCounterexample_subst;
  unsigned onCounterexample_depth;
} LMODSTATE_NODE, *LMODSTATE;
typedef struct lmodlit_struct {
  int status;
  unsigned front;
  ARRAY arr;
} LMODLIT_NODE, *LMODLIT;
typedef intptr_t *LMODEL_I;
typedef struct lmodel_struct {
  ARRAY literals;
  LMODEL_I *predRoots;
  int cleanBehaviour;
} LMODEL_NODE, *LMODEL;
LMODSTATE lmodel_Init(SCLSTATE);
void lmodel_Free(LMODSTATE);
SCLSTATE lmodel_GetSclstate(LMODSTATE);
FOLSTATE lmodel_GetFolstate(LMODSTATE);
TERMSTATE lmodel_GetTermstate(LMODSTATE);
SYMBSTATE lmodel_GetSymbstate(LMODSTATE);
MEMORY lmodel_GetMemory(LMODSTATE);
unsigned lmodel_SymbID(LMODSTATE, SYMBOL);
void lmodel_SetSymbID(LMODSTATE, SYMBOL, unsigned);
unsigned lmodel_MaxCFID(LMODSTATE);
unsigned lmodel_MaxPredID(LMODSTATE);
SYMBOL lmodel_PredIDToSymb(LMODSTATE, unsigned);
SYMBOL lmodel_CFIDToSymb(LMODSTATE, unsigned);
int lmodel_StatusTrue(void);
int lmodel_StatusFalse(void);
int lmodel_StatusClean(void);
int lmodel_StatusBad(void);
int lmodel_StatusBlank(void);
int lmodel_GreedyComplete(void);
int lmodel_GreedyReject(void);
int lmodel_AllPositive(void);
int lmodel_AllNegative(void);
LMODEL_BINDING lmodel_GetBinding(LMODSTATE, SYMBOL Var);
void lmodel_ResizeBinding(LMODSTATE, unsigned NewMax);
void lmodel_ReserveBinding(LMODSTATE, unsigned AtLeast);
LMODEL_BINDING lmodel_CreateBinding(LMODSTATE, SYMBOL Var,
                                    SYMBOL Symb, unsigned Arity);
unsigned lmodel_CreateBindingHypotheticalDepth(LMODSTATE, SYMBOL Var,
                                                     SYMBOL Symb, unsigned Arity);
void lmodel_UndoLastBinding(LMODSTATE);
void lmodel_PrintBindingEntry(LMODSTATE, unsigned Idx);
void lmodel_PrintDefinedBindings(LMODSTATE);
TERM lmodel_FormBoundTerm(LMODSTATE, unsigned Var);
LMODLIT lmodlit_Create(MEMORY, TERM Root, int STATUS);
LMODLIT lmodlit_CreateFromFOL(FOLSTATE, TERM Literal);
void lmodlit_Free(MEMORY, LMODLIT);
int lmodlit_GetStatus(LMODLIT);
void lmodlit_SetStatus(LMODLIT, int);
unsigned lmodlit_GetFront(LMODLIT);
void lmodlit_SetFront(LMODLIT, unsigned);
void lmodlit_IncrementFront(LMODLIT, int Inc);
unsigned lmodlit_GetBack(LMODLIT);
void lmodlit_SetBack(LMODLIT, unsigned);
TERM lmodlit_GetTerm(LMODLIT, unsigned);
void lmodlit_SetTerm(LMODLIT, unsigned, TERM);
SYMBOL lmodlit_GetSymbol(LMODLIT, unsigned);
TERM lmodlit_GetFrontTerm(LMODLIT);
void lmodlit_SetFrontTerm(LMODLIT, TERM);
SYMBOL lmodlit_GetFrontSymbol(LMODLIT);
void lmodlit_UnfoldFrontTerm(MEMORY, LMODLIT);
void lmodlit_UnfoldFrontBinding(LMODSTATE, LMODLIT);
LMODLIT lmodlit_Copy(LMODSTATE, LMODLIT);
void lmodlit_PrintRoot(LMODSTATE, LMODLIT, BOOL ShowVariables);
void lmodlit_PrintLong(LMODSTATE, LMODLIT);
unsigned lmodlit_RepairTerms(LMODSTATE, LMODLIT, unsigned VarNr);
ARRAY lmodlit_GrabLiterals(FOLSTATE, TERM Clause, ARRAY Acc);
LMODEL_I lmodel_NodeCreate(LMODSTATE);
void lmodel_NodeFree(LMODSTATE, LMODEL_I);
int lmodel_NodeGetStatus(LMODEL_I);
void lmodel_NodeSetStatus(LMODEL_I, int);
LMODEL_I lmodel_NodeGetChild(LMODEL_I, unsigned ID);
void lmodel_NodeSetChild(LMODEL_I, unsigned ID, LMODEL_I);
LMODLIT lmodel_NodeGetPrintable(LMODEL_I);
void lmodel_NodeSetPrintable(LMODEL_I, LMODLIT);
void lmodel_Delete(LMODSTATE, LMODEL);
LMODEL lmodel_BuildFromLmodlits(LMODSTATE, ARRAY GroundLmodlits, int CleanBehaviour);
LMODEL lmodel_BuildFromTrail(LMODSTATE, TRAIL, int CleanBehaviour);
LMODEL lmodel_BuildFromTrailAndProplits(LMODSTATE, TRAIL, ARRAY, int);
SUBST lmodel_CheckSPASSClause(LMODSTATE, LMODEL Model, CLAUSE Clause);
SUBST lmodel_CheckLmodlitClause(LMODSTATE, LMODEL Model, ARRAY Clause, unsigned MaxVar);
unsigned lmodel_GetPruningDepth(LMODSTATE);
void lmodel_SetPruningDepth(LMODSTATE, unsigned);
void lmodel_ResetPruningDepth(LMODSTATE);
SUBST lmodel_CheckSPASSClauseLowestDepth(LMODSTATE, LMODEL Model, CLAUSE Clause);
void lmodel_RepresentNode(LMODSTATE, LMODEL_I RootNode, SYMBOL RootSymbol);
void lmodel_RepresentModel(LMODSTATE, LMODEL);
void lmodel_PrintModel(LMODSTATE, LMODEL);
ARRAY lmodel_RepresentAsArrayOfLiterals(LMODSTATE, LMODEL);
#endif
