#ifndef __TheoryAxioms__
#define __TheoryAxioms__
#include <initializer_list>
#include "Forwards.hpp"
#include "Kernel/Theory.hpp"
namespace Shell {
using namespace Lib;
using namespace Kernel;
class TheoryAxioms {
public:
TheoryAxioms(Problem& prb) : _prb(prb) {}
static unsigned const CHEAP = 0;
static unsigned const EXPENSIVE = 1;
void apply();
void applyFOOL();
private:
Problem& _prb;
void addCommutativity(Interpretation op);
void addAssociativity(Interpretation op);
void addRightIdentity(Interpretation op, TermList idElement);
void addLeftIdentity(Interpretation op, TermList idElement);
void addCommutativeGroupAxioms(Interpretation op, Interpretation inverse, TermList idElement);
void addRightInverse(Interpretation op, Interpretation inverse);
void addNonReflexivity(Interpretation op);
void addTransitivity(Interpretation op);
void addOrderingTotality(Interpretation less);
void addTotalOrderAxioms(Interpretation less);
void addMonotonicity(Interpretation less, Interpretation addition);
void addPlusOneGreater(Interpretation plus, TermList oneElement, Interpretation less);
void addAdditionAndOrderingAxioms(TermList sort, Interpretation plus, Interpretation unaryMinus,
TermList zeroElement, TermList oneElement,
Interpretation less);
void addAdditionOrderingAndMultiplicationAxioms(Interpretation plus, Interpretation unaryMinus,
TermList zeroElement, TermList oneElement,
Interpretation less, Interpretation multiply);
void addExtraIntegerOrderingAxiom(Interpretation plus, TermList oneElement, Interpretation less);
void addQuotientAxioms(Interpretation quotient, Interpretation multiply, TermList zeroElement, TermList oneElement,
Interpretation less);
void addIntegerDivisionWithModuloAxioms(Interpretation plus, Interpretation unaryMinus, Interpretation less,
Interpretation multiply, Interpretation divide, Interpretation divides,
Interpretation modulo, Interpretation abs, TermList zeroElement,
TermList oneElement);
void addIntegerAbsAxioms(Interpretation abs, Interpretation less,
Interpretation unaryMinus, TermList zeroElement);
void addIntegerDividesAxioms(Interpretation divides, Interpretation multiply, TermList zero, TermList n);
friend struct AlascaAxioms;
void addAlascaAxioms();
void addBooleanArrayExtensionalityAxioms(TermList arraySort, unsigned skolem);
void addArrayExtensionalityAxioms(TermList arraySort, unsigned skolem);
void addBooleanArrayWriteAxioms(TermList arraySort);
void addArrayWriteAxioms(TermList arraySort);
void addFloorAxioms(Interpretation floor, Interpretation less, Interpretation unaryMinus,
Interpretation plus, TermList oneElement);
void addCeilingAxioms(Interpretation ceiling, Interpretation less, Interpretation plus,
TermList oneElement);
void addRoundAxioms(Interpretation round, Interpretation floor, Interpretation ceiling);
void addTruncateAxioms(Interpretation truncate, Interpretation less, Interpretation unaryMinus,
Interpretation plus, TermList zeroElement, TermList oneElement);
void addExhaustivenessAxiom(TermAlgebra* ta);
void addDistinctnessAxiom(TermAlgebra* ta);
void addInjectivityAxiom(TermAlgebra* ta);
void addDiscriminationAxiom(TermAlgebra* ta);
void addAcyclicityAxiom(TermAlgebra* ta);
bool addSubtermDefinitions(unsigned subtermPredicate, TermAlgebraConstructor* c);
void addTheoryClauseFromLits(std::initializer_list<Literal*> lits, InferenceRule rule, unsigned level);
void addAndOutputTheoryUnit(Unit* unit, unsigned level);
};
}
#endif