#include "Kernel/Clause.hpp"
#include "Kernel/Formula.hpp"
#include "Kernel/FormulaUnit.hpp"
#include "Kernel/Term.hpp"
#include "Property.hpp"
#include "TheoryFinder.hpp"
#define TRACE_FINDER 0
#define SHOW_FOUND 0
using namespace std;
using namespace Lib;
using namespace Shell;
using namespace Kernel;
TheoryFinder::TheoryFinder (const UnitList* units,Property* property)
: _units(units),
_property(property)
{
}
TheoryFinder::~TheoryFinder ()
{
}
int TheoryFinder::search()
{
int found = 0;
UnitList::Iterator uit(_units);
while (uit.hasNext()) {
if (matchAll(uit.next())) {
found++;
}
}
return found;
}
bool TheoryFinder::matchAll(const Unit* unit)
{
if (unit->isClause()) {
return matchAll(static_cast<const Clause*>(unit));
}
return matchAll(static_cast<const FormulaUnit*>(unit)->formula());
}
bool TheoryFinder::matchAll(const Clause* clause)
{
switch (clause->length()) {
case 1:
return matchAll((*clause)[0]);
case 2:
return matchSubset(clause);
return false;
case 3:
return matchFLD2(clause) ||
matchCondensedDetachment1(clause) ||
matchCondensedDetachment2(clause) ||
matchExtensionality(clause);
case 4:
return matchFLD1(clause);
default:
return false;
}
}
bool TheoryFinder::matchAll(const Formula* formula)
{
while (formula->connective() == FORALL) {
formula = formula->qarg();
}
if (formula->connective() == LITERAL) {
return matchAll(formula->literal());
}
return matchExtensionality(formula) ||
matchSubset(formula) ||
matchListConstructors(formula);
}
class TheoryFinder::Backtrack
{
public:
unsigned cp;
unsigned objPos;
const void* obj;
};
bool TheoryFinder::matchCode(const void* obj,
const unsigned char* code,
uint64_t prop)
{
bool found = matchCode(obj, code);
if (found && prop) {
_property->addProp(prop);
}
return found;
}
bool TheoryFinder::matchCode(const void* obj,
const unsigned char* code)
{
Backtrack backtrack[20];
unsigned backtrackPos = 0;
const void* objects[100];
int objectPos = 1;
objects[0] = obj;
unsigned vars[10];
unsigned funs[10];
unsigned preds[10];
unsigned cp = 0;
const Clause* clause = nullptr;
int clength = 0;
int literals[4];
match:
switch (code[cp]) {
case END:
#if TRACE_FINDER
cout << "Matched\n";
#endif
return true;
case NEWVAR: {
ASS(objectPos > 0);
obj = objects[--objectPos];
const TermList* ts = reinterpret_cast<const TermList*>(obj);
#if TRACE_FINDER
cout << "M: NEWVAR " << (int)code[cp+1] << ": " << ts->toString() << "\n";
#endif
if (! ts->isVar()) {
goto backtrack;
}
vars[code[cp+1]] = ts->var();
if (! ts->next()->isEmpty()) {
objects[objectPos++] = ts->next();
}
cp += 2;
goto match;
}
case NEWFUN:
case NEWFUN1: {
ASS(objectPos > 0);
obj = objects[--objectPos];
const TermList* ts = reinterpret_cast<const TermList*>(obj);
int funNumber = code[cp+1];
#if TRACE_FINDER
cout << "M: NEWFUN" << (code[cp] == NEWFUN1 ? "1" : "") << ' ' << funNumber
<< '/' << (int)code[cp+2] << ": " << ts->toString() << "\n";
#endif
if (ts->isVar()) {
goto backtrack;
}
const Term* t = ts->term();
if (t->arity() != code[cp+2]) {
goto backtrack;
}
for (int k = funNumber - 1; k >= 0; k--) {
if (funs[k] == t->functor()) {
goto backtrack;
}
}
funs[funNumber] = t->functor();
if (code[cp] == NEWFUN && ! ts->next()->isEmpty()) {
objects[objectPos++] = ts->next();
}
ts = t->args();
if (! ts->isEmpty()) {
objects[objectPos++] = ts;
}
cp += 3;
goto match;
}
case NEWPRED: {
ASS(objectPos > 0);
obj = objects[--objectPos];
const Literal* lit = reinterpret_cast<const Literal*>(obj);
int predNumber = code[cp+1];
#if TRACE_FINDER
cout << "M: NEWPRED " << predNumber << '/' << (int)code[cp+2] << ": " << lit->toString() << "\n";
#endif
if (lit->arity() != code[cp+2]) {
goto backtrack;
}
for (int k = predNumber - 1; k >= 0; k--) {
if (preds[k] == lit->functor()) {
goto backtrack;
}
}
preds[predNumber] = lit->functor();
const TermList* ts = lit->args();
if (! ts->isEmpty()) {
objects[objectPos++] = ts;
}
cp += 3;
goto match;
}
case OLDFUN:
case OLDFUN1: {
ASS(objectPos > 0);
obj = objects[--objectPos];
const TermList* ts = reinterpret_cast<const TermList*>(obj);
#if TRACE_FINDER
cout << "M: OLDFUN" << (code[cp] == OLDFUN1 ? "1" : "") << " " << (int)code[cp+1] << ": " << ts->toString() << "\n";
#endif
if (ts->isVar()) {
goto backtrack;
}
const Term* t = ts->term();
if (t->isSort()) {
#if TRACE_FINDER
cout << "Failing to match a sort argument against an OLDFUN" << endl;
#endif
goto backtrack;
}
if (funs[code[cp+1]] != t->functor()) {
#if TRACE_FINDER
cout << "found a different functor, going to backtrack" << endl;
#endif
goto backtrack;
}
if (code[cp] == OLDFUN && ! ts->next()->isEmpty()) {
objects[objectPos++] = ts->next();
}
ts = t->args();
if (! ts->isEmpty()) {
objects[objectPos++] = ts;
}
cp += 2;
goto match;
}
case OLDPRED: {
#if TRACE_FINDER
cout << "M: OLDPRED " << (int)code[cp+1] << "\n";
#endif
ASS(objectPos > 0);
obj = objects[--objectPos];
const Literal* lit = reinterpret_cast<const Literal*>(obj);
if (preds[code[cp+1]] != lit->functor()) {
goto backtrack;
}
const TermList* ts = lit->args();
if (! ts->isEmpty()) {
objects[objectPos++] = ts;
}
cp += 2;
goto match;
}
case OLDVAR:
case OLDVAR1: {
ASS(objectPos > 0);
obj = objects[--objectPos];
const TermList* ts = reinterpret_cast<const TermList*>(obj);
#if TRACE_FINDER
cout << "M: OLDVAR" << (code[cp] == OLDVAR1 ? "1" : "")
<< ' ' << (int)code[cp+1] << ": " << ts->toString() << "\n";
#endif
if (! ts->isVar()) {
goto backtrack;
}
if (vars[code[cp+1]] != ts->var()) {
goto backtrack;
}
if (code[cp] == OLDVAR && ! ts->next()->isEmpty()) {
objects[objectPos++] = ts->next();
}
cp += 2;
goto match;
}
case EQL: {
ASS(objectPos > 0);
obj = objects[--objectPos];
const Literal* lit = reinterpret_cast<const Literal*>(obj);
#if TRACE_FINDER
cout << "M: EQL: " << lit->toString() << "\n";
#endif
if (! lit->isEquality()) {
goto backtrack;
}
Backtrack& back = backtrack[backtrackPos++];
back.cp = cp;
back.obj = obj;
back.objPos = objectPos;
const TermList* ts = lit->args();
objects[objectPos++] = ts->next();
objects[objectPos++] = ts;
cp++;
goto match;
}
case CLS: {
ASS(objectPos > 0);
obj = objects[--objectPos];
clause = reinterpret_cast<const Clause*>(obj);
#if TRACE_FINDER
cout << "M: CLS: " << clause->toString() << endl;
#endif
clength = clause->length();
cp++;
goto match;
}
case PLIT:
case NLIT: {
#if TRACE_FINDER
cout << "M: LIT " << (int)code[cp+1] << "\n";
#endif
unsigned l = code[cp+1];
unsigned choice = (1u << clength) - 1;
for (int i = l-1;i >= 0;i--) {
choice -= 1u << literals[i];
}
int c = 0;
while (c < clength) {
if (choice & (1 << c)) {
if ((*clause)[c]->isPositive()) {
if (code[cp] == PLIT) {
break;
}
}
else if (code[cp] == NLIT) {
break;
}
}
c++;
}
if (c == clength) { goto backtrack;
}
Backtrack& back = backtrack[backtrackPos++];
back.cp = cp;
back.objPos = objectPos;
literals[l] = c;
objects[objectPos++] = (*clause)[c];
cp += 2;
goto match;
}
case CIFF:
case NBCIFF: {
ASS(objectPos > 0);
obj = objects[--objectPos];
const Formula* f = reinterpret_cast<const Formula*>(obj);
#if TRACE_FINDER
cout << "M: IFF: " << f->toString() << "\n";
#endif
if (f->connective() != IFF) {
goto backtrack;
}
if (code[cp] == CIFF) {
Backtrack& back = backtrack[backtrackPos++];
back.cp = cp;
back.obj = obj;
back.objPos = objectPos;
}
objects[objectPos++] = f->right();
objects[objectPos++] = f->left();
cp++;
goto match;
}
case COR: {
ASS(objectPos > 0);
obj = objects[--objectPos];
const Formula* f = reinterpret_cast<const Formula*>(obj);
#if TRACE_FINDER
cout << "M: OR " << (int)code[cp+1] << ": " << f->toString() << "\n";
#endif
if (f->connective() != OR) {
goto backtrack;
}
ASS(code[cp+1] == 2);
const FormulaList* args = f->args();
if (FormulaList::length(args) != code[cp+1]) {
goto backtrack;
}
FormulaList::Iterator as(args);
while (as.hasNext()) {
objects[objectPos++] = as.next();
}
cp += 2;
goto match;
}
case CIMP: {
ASS(objectPos > 0);
obj = objects[--objectPos];
const Formula* f = reinterpret_cast<const Formula*>(obj);
#if TRACE_FINDER
cout << "M: IMP: " << f->toString() << "\n";
#endif
if (f->connective() != IMP) {
goto backtrack;
}
objects[objectPos++] = f->right();
objects[objectPos++] = f->left();
cp++;
goto match;
}
case CFORALL: {
ASS(objectPos > 0);
obj = objects[--objectPos];
const Formula* f = reinterpret_cast<const Formula*>(obj);
#if TRACE_FINDER
cout << "M: FORALL " << (int)code[cp+1] << ": " << f->toString() << "\n";
#endif
if (f->connective() != FORALL) {
goto backtrack;
}
if (VList::length(f->vars()) != code[cp+1]) {
goto backtrack;
}
cp += 2;
VList::Iterator vs(f->vars());
while (vs.hasNext()) {
vars[code[cp++]] = vs.next();
}
objects[objectPos++] = f->qarg();
goto match;
}
case POS: {
ASS(objectPos > 0);
obj = objects[--objectPos];
const Formula* f = reinterpret_cast<const Formula*>(obj);
#if TRACE_FINDER
cout << "M: POS: " << f->toString() << "\n";
#endif
if (f->connective() != LITERAL) {
goto backtrack;
}
const Literal* lit = f->literal();
if (! lit->isPositive()) {
goto backtrack;
}
objects[objectPos++] = lit;
cp++;
goto match;
}
#if VDEBUG
case CAND:
case CNOT:
case CXOR:
case CEXISTS:
case NEG:
case TERM:
case FORM:
default:
ASSERTION_VIOLATION;
#endif
}
backtrack:
if (backtrackPos == 0) {
#if TRACE_FINDER
cout << "M: fail\n";
#endif
return false;
}
Backtrack& back = backtrack[--backtrackPos];
cp = back.cp;
obj = back.obj;
ASS_GE(objectPos,(int)back.objPos);
objectPos = back.objPos;
switch (code[cp]) {
case EQL: {
const Literal* lit = reinterpret_cast<const Literal*>(obj);
#if TRACE_FINDER
cout << "B: EQL: " << lit->toString() << "\n";
#endif
const TermList* ts = lit->args();
objects[objectPos++] = ts;
objects[objectPos++] = ts->next();
cp++;
goto match;
}
case CIFF: {
const Formula* f = reinterpret_cast<const Formula*>(obj);
#if TRACE_FINDER
cout << "B: IFF: " << f->toString() << "\n";
#endif
objects[objectPos++] = f->left();
objects[objectPos++] = f->right();
cp++;
goto match;
}
case PLIT:
case NLIT: {
#if TRACE_FINDER
cout << "B: LIT\n";
#endif
unsigned l = code[cp+1];
unsigned choice = (1u << clength) - 1;
for (int i = l-1;i >= 0;i--) {
choice -= 1u << literals[i];
}
int c = literals[l]+1;
while (c < clength) {
if (choice & (1 << c)) {
if ((*clause)[c]->isPositive()) {
if (code[cp] == PLIT) {
break;
}
}
else if (code[cp] == NLIT) {
break;
}
}
c++;
}
if (c == clength) { goto backtrack;
}
Backtrack& back = backtrack[backtrackPos++];
back.cp = cp;
back.objPos = objectPos;
literals[l] = c;
objects[objectPos++] = (*clause)[c];
cp += 2;
goto match;
}
default:
ASSERTION_VIOLATION;
}
}
bool TheoryFinder::matchC(const Literal* lit)
{
#if TRACE_FINDER
cout << lit->toString() << "\n";
#endif
static const unsigned char code[] =
{EQL, NEWFUN1,0,2,NEWVAR,0,NEWVAR,1, OLDFUN1,0,OLDVAR,1,OLDVAR,0,
END};
if (matchCode(lit,code,0)) {
#if SHOW_FOUND
cout << "C: " << lit->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchA(const Literal* lit)
{
static const unsigned char code[] =
{EQL, NEWFUN1,0,2,OLDFUN,0,
NEWVAR,0,NEWVAR,1,NEWVAR,2, OLDFUN1,0,OLDVAR,0,OLDFUN,0,
OLDVAR,1,OLDVAR,2, END};
if (matchCode(lit,code,0)) {
#if SHOW_FOUND
cout << "A: " << lit->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchExtensionality (const Clause* c)
{
static const unsigned char code[] =
{CLS,
NLIT,0,
NEWPRED,0,2, NEWFUN,0,2,NEWVAR,0,NEWVAR,1,OLDVAR,0,
NLIT,1,
OLDPRED,0, OLDFUN,0,OLDVAR,0,OLDVAR,1,OLDVAR,1,
PLIT,2,
EQL,OLDVAR,0,OLDVAR,1,END};
if (matchCode(c,code,Property::PR_HAS_EXTENSIONALITY)) {
#if SHOW_FOUND
cout << "Extensionality: " << c->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchCondensedDetachment1(const Clause* c)
{
static const unsigned char code[] =
{CLS,
PLIT,0,
NEWPRED,0,1,NEWVAR,0, NLIT,1,
OLDPRED,0,NEWVAR,1, NLIT,2,
OLDPRED,0,NEWFUN,0,2,OLDVAR,1,OLDVAR,0,END};
if (matchCode(c,code,Property::PR_HAS_CONDENSED_DETACHMENT1)) {
#if SHOW_FOUND
cout << "Condensed detachment 1: " << c->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchCondensedDetachment2(const Clause* c)
{
static const unsigned char code[] =
{CLS,
PLIT,0,
NEWPRED,0,1,NEWVAR,0, NLIT,1,
OLDPRED,0,NEWVAR,1, NLIT,2,
OLDPRED,0,NEWFUN,0,2,NEWFUN,1,1,OLDVAR,1,OLDVAR,0,END};
if (matchCode(c,code,Property::PR_HAS_CONDENSED_DETACHMENT2)) {
#if SHOW_FOUND
cout << "Condensed detachment 2: " << c->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchFLD1(const Clause* c)
{
static const unsigned char code[] =
{CLS,
PLIT,0,
NEWPRED,0,2,NEWFUN,0,2,NEWFUN,1,2,NEWVAR,0,NEWVAR,1, OLDFUN,1,NEWVAR,2,OLDVAR,1, OLDFUN,1,OLDFUN,0,OLDVAR,0,OLDVAR,2,OLDVAR,1, NLIT,1,
NEWPRED,1,1,OLDVAR,0, NLIT,2,
OLDPRED,1,OLDVAR,2, NLIT,3,
OLDPRED,1,OLDVAR,1,END};
if (matchCode(c,code,Property::PR_HAS_FLD1)) {
#if SHOW_FOUND
cout << "FLD1: " << c->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchFLD2(const Clause* c)
{
static const unsigned char code[] =
{CLS,
PLIT,0,
NEWPRED,0,3,NEWFUN,0,1,NEWVAR,0,OLDVAR,0,NEWFUN,0,0, PLIT,1,
NEWPRED,1,3,NEWFUN,2,0,OLDVAR,0,OLDFUN,2, NLIT,2,
NEWPRED,2,1,OLDVAR,0,END};
if (matchCode(c,code,Property::PR_HAS_FLD2)) {
#if SHOW_FOUND
cout << "FLD2: " << c->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchSubset (const Clause* c)
{
static const unsigned char code[] =
{CLS,
PLIT,0,
NEWPRED,0,2, NEWFUN,0,2,NEWVAR,0,NEWVAR,1,OLDVAR,0,
PLIT,1,
NEWPRED,1,2,OLDVAR,0,OLDVAR,1,END};
if (matchCode(c,code,Property::PR_HAS_SUBSET)) {
#if SHOW_FOUND
cout << "Subset: " << c->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchSubset (const Formula* f)
{
static const unsigned char code[] =
{CIFF, POS,NEWPRED,0,2,NEWVAR,0,NEWVAR,1, CFORALL,1,2,CIMP, POS,NEWPRED,1,2,OLDVAR,2,OLDVAR,0, POS,OLDPRED,1,OLDVAR,2,OLDVAR,1,END};
if (matchCode(f,code,Property::PR_HAS_SUBSET)) {
#if SHOW_FOUND
cout << "Subset: " << f->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchListConstructors (const Formula* f)
{
#if TRACE_FINDER
cout << "M: [match list constructors axiom]\n";
#endif
static const unsigned char code1[] =
{COR,2, POS,EQL,NEWVAR,0, NEWFUN1,0,2, NEWFUN,1,1,OLDVAR,0, NEWFUN,2,1,OLDVAR,0, POS,EQL,OLDVAR1,0,NEWFUN1,3,0,END}; static const unsigned char code2[] =
{COR,2, POS,EQL,NEWVAR,0,NEWFUN1,0,0, POS,EQL,OLDVAR1,0, NEWFUN1,1,2, NEWFUN,2,1,OLDVAR,0, NEWFUN,3,1,OLDVAR,0, END};
if (matchCode(f,code1,Property::PR_LIST_AXIOMS) ||
matchCode(f,code2,Property::PR_LIST_AXIOMS)) {
#if SHOW_FOUND
cout << "List constructors: " << f->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchExtensionality (const Formula* f)
{
static const unsigned char code1[] =
{CIFF, CFORALL,1,0,NBCIFF, POS,NEWPRED,0,2,OLDVAR,0,NEWVAR,1, POS,OLDPRED,0,OLDVAR,0,NEWVAR,2, POS,EQL,OLDVAR1,1,OLDVAR1,2,END}; static const unsigned char code2[] =
{CIMP, CFORALL,1,0,NBCIFF, POS,NEWPRED,0,2,OLDVAR,0,NEWVAR,1, POS,OLDPRED,0,OLDVAR,0,NEWVAR,2, POS,EQL,OLDVAR1,1,OLDVAR1,2,END};
if (matchCode(f,code1,Property::PR_HAS_EXTENSIONALITY) ||
matchCode(f,code2,Property::PR_HAS_EXTENSIONALITY)) {
#if SHOW_FOUND
cout << "Extensionality: " << f->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchLeftInverse(const Literal* lit)
{
static const unsigned char code[] =
{EQL, NEWFUN1,0,2,NEWFUN,1,1,NEWVAR,0,OLDVAR,0, NEWFUN1,2,0, END};
if (matchCode(lit,code,0)) {
#if SHOW_FOUND
cout << "Left inverse: " << lit->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchRightInverse(const Literal* lit)
{
static const unsigned char code[] =
{EQL, NEWFUN1,0,2,NEWVAR,0,NEWFUN,1,1,OLDVAR,0, NEWFUN1,2,0, END};
if (matchCode(lit,code,0)) {
#if SHOW_FOUND
cout << "Right inverse: " << lit->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchLeftIdentity(const Literal* lit)
{
static const unsigned char code[] =
{EQL, NEWFUN1,0,2,NEWFUN,1,0,NEWVAR,0, OLDVAR1,0, END};
if (matchCode(lit,code,0)) {
#if SHOW_FOUND
cout << "Left identity: " << lit->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchIdempotence(const Literal* lit)
{
static const unsigned char code[] =
{EQL,NEWFUN1,0,2,NEWVAR,0,OLDVAR,0,
OLDVAR1,0,END};
if (matchCode(lit,code,0)) {
#if SHOW_FOUND
cout << "Idempotence: " << lit->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchRightIdentity(const Literal* lit)
{
static const unsigned char code[] =
{EQL, NEWFUN1,0,2,NEWVAR,0,NEWFUN,1,0, OLDVAR1,0,END};
if (matchCode(lit,code,0)) {
#if SHOW_FOUND
cout << "Right identity: " << lit->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchAssociator(const Literal* lit)
{
static const unsigned char code[] =
{EQL, NEWFUN1,0,3,NEWVAR,0,NEWVAR,1,NEWVAR,2, NEWFUN1,1,2,NEWFUN,2,2,OLDFUN,2,OLDVAR,0,OLDVAR,1,OLDVAR,2, NEWFUN,3,1,OLDFUN,2,OLDVAR,0,OLDFUN,2,OLDVAR,1,OLDVAR,2, END};
if (matchCode(lit,code,0)) {
#if SHOW_FOUND
cout << "Associator: " << lit->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchCommutator(const Literal* lit)
{
static const unsigned char code[] =
{EQL, NEWFUN1,0,3,NEWVAR,0,NEWVAR,1, NEWFUN1,1,2,NEWFUN,2,2,OLDVAR,1,OLDVAR,0, NEWFUN,3,1,OLDFUN,2,OLDVAR,0,OLDVAR,1, END};
if (matchCode(lit,code,0)) {
#if SHOW_FOUND
cout << "Commutator: " << lit->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchLeftDistributivity(const Literal* lit)
{
static const unsigned char code[] =
{EQL, NEWFUN1,0,2,NEWFUN,1,2,NEWVAR,0,
NEWVAR,1,NEWVAR,2, OLDFUN1,1,OLDFUN,0,OLDVAR,0,OLDVAR,2,
OLDFUN,0,OLDVAR,1,OLDVAR,2,END};
if (matchCode(lit,code,0)) {
#if SHOW_FOUND
cout << "Left distributivity: " << lit->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchRightDistributivity (const Literal* lit)
{
static const unsigned char code[] =
{EQL, NEWFUN1,0,2,NEWVAR,0,NEWFUN,1,2,
NEWVAR,1,NEWVAR,2, OLDFUN1,1,OLDFUN,0,OLDVAR,0,OLDVAR,1,
OLDFUN,0,OLDVAR,0,OLDVAR,2,END};
if (matchCode(lit,code,0)) {
#if SHOW_FOUND
cout << "Right distributivity: " << lit->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchRobbins(const Literal* lit)
{
static const unsigned char code1[] =
{EQL, NEWFUN1,0,1,NEWFUN,1,2,OLDFUN,0,OLDFUN,1,NEWVAR,0,NEWVAR,1, OLDFUN,0,OLDFUN,1,OLDVAR,0,OLDFUN,0,OLDVAR,1, OLDVAR1,0,END}; static const unsigned char code2[] =
{EQL, NEWFUN1,0,1,NEWFUN,1,2,OLDFUN,0,OLDFUN,1,NEWVAR,0,NEWVAR,1, OLDFUN,0,OLDFUN,1,OLDFUN,0,OLDVAR,0,OLDVAR,1, OLDVAR1,1,END}; static const unsigned char code3[] =
{EQL, NEWFUN1,0,1,NEWFUN,1,2,OLDFUN,0,OLDFUN,1,NEWVAR,0,OLDFUN,0,NEWVAR,1, OLDFUN,0,OLDFUN,1,OLDVAR,0,OLDVAR,1, OLDVAR1,0,END}; static const unsigned char code4[] =
{EQL, NEWFUN,0,1,NEWFUN,1,2,OLDFUN,0,OLDFUN,1,OLDFUN,0,NEWVAR,0,NEWVAR,1, OLDFUN,0,OLDFUN,1,OLDVAR,0,OLDVAR,1, OLDVAR,1,END};
if (matchCode(lit,code1,0) ||
matchCode(lit,code2,0) ||
matchCode(lit,code3,0) ||
matchCode(lit,code4,0)) {
#if SHOW_FOUND
cout << "Robbins: " << lit->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchAlternative(const Literal* lit)
{
static const unsigned char code1[] =
{EQL, NEWFUN1,0,2,OLDFUN,0,NEWVAR,0,OLDVAR,0,NEWVAR,1, OLDFUN1,0,OLDVAR,0,OLDFUN,0,OLDVAR,0,OLDVAR,1,END}; static const unsigned char code2[] =
{EQL, NEWFUN1,0,2,OLDFUN,0,NEWVAR,0,NEWVAR,1,OLDVAR,1, OLDFUN1,0,OLDVAR,0,OLDFUN,0,OLDVAR,1,OLDVAR,1,END};
if (matchCode(lit,code1,0) ||
matchCode(lit,code2,0)) {
#if SHOW_FOUND
cout << "Alternative: " << lit->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchAbsorption(const Literal* lit)
{
static const unsigned char code[] =
{EQL, NEWFUN1,0,2,NEWVAR,0,NEWFUN,1,2,OLDVAR,0,NEWVAR,1, OLDVAR1,0,END};
if (matchCode(lit,code,0)) {
#if SHOW_FOUND
cout << "Absorption: " << lit->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchCombinatorS(const Literal* lit)
{
static const unsigned char code[] =
{EQL, NEWFUN1,0,2,OLDFUN,0,OLDFUN,0,NEWFUN,1,0,
NEWVAR,0,NEWVAR,1,NEWVAR,2, OLDFUN1,0,OLDFUN,0,OLDVAR,0,OLDVAR,2,
OLDFUN,0,OLDVAR,1,OLDVAR,2,END};
if (matchCode(lit,code,Property::PR_COMBINATOR)) {
#if SHOW_FOUND
cout << "S: " << lit->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchCombinatorB(const Literal* lit)
{
static const unsigned char code[] =
{EQL, NEWFUN1,0,2,OLDFUN,0,OLDFUN,0,NEWFUN,1,0,
NEWVAR,0,NEWVAR,1,NEWVAR,2, OLDFUN1,0,OLDVAR,0,OLDFUN,0,OLDVAR,1,OLDVAR,2,END};
if (matchCode(lit,code,Property::PR_COMBINATOR_B)) {
#if SHOW_FOUND
cout << "B: " << lit->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchCombinatorT(const Literal* lit)
{
static const unsigned char code[] =
{EQL, NEWFUN1,0,2,OLDFUN,0,NEWFUN,1,0,NEWVAR,0,NEWVAR,1, OLDFUN1,0,OLDVAR,1,OLDVAR,0,END};
if (matchCode(lit,code,Property::PR_COMBINATOR)) {
#if SHOW_FOUND
cout << "T: " << lit->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchCombinatorO(const Literal* lit)
{
static const unsigned char code[] =
{EQL, NEWFUN1,0,2,OLDFUN,0,NEWFUN,1,0,NEWVAR,0,NEWVAR,1, OLDFUN1,0,OLDVAR,1,OLDFUN,0,OLDVAR,0,OLDVAR,1,END};
if (matchCode(lit,code,Property::PR_COMBINATOR)) {
#if SHOW_FOUND
cout << "O: " << lit->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchCombinatorQ(const Literal* lit)
{
static const unsigned char code[] =
{EQL, NEWFUN1,0,2,OLDFUN,0,OLDFUN,0,NEWFUN,1,0,
NEWVAR,0,NEWVAR,1,NEWVAR,2, OLDFUN1,0,OLDVAR,1,OLDFUN,0,OLDVAR,0,OLDVAR,2,END};
if (matchCode(lit,code,Property::PR_COMBINATOR)) {
#if SHOW_FOUND
cout << "Q: " << lit->toString() << "\n";
#endif
return true;
}
return false;
}
bool TheoryFinder::matchAll (const Literal* lit)
{
if (! lit->isPositive()) {
return false;
}
return matchC(lit) ||
matchA(lit) ||
matchIdempotence(lit) ||
matchLeftInverse(lit) ||
matchLeftIdentity(lit) ||
matchRightInverse(lit) ||
matchRightIdentity(lit) ||
matchLeftDistributivity(lit) ||
matchRightDistributivity(lit) ||
matchAssociator(lit) ||
matchCommutator(lit) ||
matchAlternative(lit) ||
matchAbsorption(lit) ||
matchRobbins(lit) ||
matchCombinatorS(lit) ||
matchCombinatorB(lit) ||
matchCombinatorT(lit) ||
matchCombinatorO(lit) ||
matchCombinatorQ(lit);
}
bool TheoryFinder::matchKnownExtensionality(const Clause* c) {
static const unsigned char setCode[] =
{CLS,
NLIT,0,
NEWPRED,0,2, NEWFUN,0,2,NEWVAR,0,NEWVAR,1,OLDVAR,0,
NLIT,1,
OLDPRED,0, OLDFUN,0,OLDVAR,0,OLDVAR,1,OLDVAR,1,
PLIT,2,
EQL,OLDVAR1,0,OLDVAR1,1,END}; static const unsigned char arrayCode[] =
{CLS,
NLIT,0,
EQL,
NEWFUN1,0,2,NEWVAR,0,NEWFUN,1,2,OLDVAR,0,NEWVAR,1, OLDFUN1,0 ,OLDVAR,1,OLDFUN,1 ,OLDVAR,0,OLDVAR,1,
PLIT,1,
EQL,OLDVAR1,0,OLDVAR1,1,END}; static const unsigned char subsetCode[] =
{CLS,
NLIT,0,
NEWPRED,0,2,NEWVAR,0,NEWVAR,1, NLIT,1,
OLDPRED,0, OLDVAR,1,OLDVAR,0, PLIT,2,
EQL,OLDVAR1,0,OLDVAR1,1,END};
switch (c->length()) {
case 2:
return matchCode(c, arrayCode);
case 3:
return (matchCode(c, setCode) || matchCode(c, subsetCode));
default:
return false;
}
}