%two level L-stratification
%one stable model
%does not pass finite domain check
%does not terminate with -nofinitecheck argument
%returns stable model only with -functionnesting=3 argument

formicAcid(fa).
oxalicAcid(oa).

molecule(X):- formicAcid(X).
hasAtom(X,f1(X)):- formicAcid(X).
hasAtom(X,f2(X)):- formicAcid(X).
hasAtom(X,f3(X)):- formicAcid(X).
hasAtom(X,f4(X)):- formicAcid(X).
hasAtom(X,f5(X)):- formicAcid(X).
c(f1(X)):- formicAcid(X).
o(f2(X)):- formicAcid(X).
h(f3(X)):- formicAcid(X).
h(f4(X)):- formicAcid(X).
o(f5(X)):- formicAcid(X).
singleBond(f1(X),f2(X)):- formicAcid(X).
singleBond(f2(X),f3(X)):- formicAcid(X).
singleBond(f1(X),f4(X)):- formicAcid(X).
doubleBond(f1(X),f5(X)):- formicAcid(X).

molecule(X):- oxalicAcid(X).
hasAtom(X,g1(X)):- oxalicAcid(X).
hasAtom(X,g2(X)):- oxalicAcid(X).
hasAtom(X,g3(X)):- oxalicAcid(X).
hasAtom(X,g4(X)):- oxalicAcid(X).
hasAtom(X,g5(X)):- oxalicAcid(X).
hasAtom(X,g6(X)):- oxalicAcid(X).
hasAtom(X,g7(X)):- oxalicAcid(X).
hasAtom(X,g8(X)):- oxalicAcid(X).
c(g1(X)):- oxalicAcid(X).
o(g2(X)):- oxalicAcid(X).
h(g3(X)):- oxalicAcid(X).
o(g4(X)):- oxalicAcid(X).
c(g5(X)):- oxalicAcid(X).
o(g6(X)):- oxalicAcid(X).
h(g7(X)):- oxalicAcid(X).
o(g8(X)):- oxalicAcid(X).
singleBond(g1(X),g2(X)):- oxalicAcid(X).
singleBond(g2(X),g3(X)):- oxalicAcid(X).
doubleBond(g1(X),g4(X)):- oxalicAcid(X).
singleBond(g1(X),g5(X)):- oxalicAcid(X).
doubleBond(g5(X),g8(X)):- oxalicAcid(X).
singleBond(g5(X),g6(X)):- oxalicAcid(X).
singleBond(g6(X),g7(X)):- oxalicAcid(X).

rc(u(Z1,Z2,Z3,Z4)):- molecule(X), c(Z1), o(Z2), o(Z3), h(Z4), doubleBond(Z1,Z2), singleBond(Z1,Z3), singleBond(Z3,Z4), not gc(Z1), not gc(Z2), not gc(Z3), not gc(Z4).
carboxyl(u(Z1,Z2,Z3,Z4)):- molecule(X), c(Z1), o(Z2), o(Z3), h(Z4), doubleBond(Z1,Z2), singleBond(Z1,Z3), singleBond(Z3,Z4), not gc(Z1), not gc(Z2), not gc(Z3), not gc(Z4).
hasAtom(u(Z1,Z2,Z3,Z4),Z1):- molecule(X), c(Z1), o(Z2), o(Z3), h(Z4), doubleBond(Z1,Z2), singleBond(Z1,Z3), singleBond(Z3,Z4), not gc(Z1), not gc(Z2), not gc(Z3), not gc(Z4).
hasAtom(u(Z1,Z2,Z3,Z4),Z2):- molecule(X), c(Z1), o(Z2), o(Z3), h(Z4), doubleBond(Z1,Z2), singleBond(Z1,Z3), singleBond(Z3,Z4), not gc(Z1), not gc(Z2), not gc(Z3), not gc(Z4).
hasAtom(u(Z1,Z2,Z3,Z4),Z3):- molecule(X), c(Z1), o(Z2), o(Z3), h(Z4), doubleBond(Z1,Z2), singleBond(Z1,Z3), singleBond(Z3,Z4), not gc(Z1), not gc(Z2), not gc(Z3), not gc(Z4).
hasAtom(u(Z1,Z2,Z3,Z4),Z4):- molecule(X), c(Z1), o(Z2), o(Z3), h(Z4), doubleBond(Z1,Z2), singleBond(Z1,Z3), singleBond(Z3,Z4), not gc(Z1), not gc(Z2), not gc(Z3), not gc(Z4).

hasGroup(X,Y):- molecule(X), hasAtom(Y,Z1), hasAtom(Y,Z2), hasAtom(Y,Z3), hasAtom(Y,Z4), c(Z1), o(Z2), o(Z3), h(Z4), doubleBond(Z1,Z2), singleBond(Z1,Z3), singleBond(Z3,Z4), hasAtom(X,Z1), hasAtom(X,Z2), hasAtom(X,Z3), hasAtom(X,Z4), carboxyl(Y), X != Y.

carboxylicAcid(X):- hasGroup(X,Y), carboxyl(Y).
atLeast2Carboxyls(X):- hasGroup(X,Y1), hasGroup(X,Y2), carboxyl(Y1), carboxyl(Y2), Y1!=Y2.
monoCarboxylicAcid(X):- carboxylicAcid(X), not atLeast2Carboxyls(X).

hasAtom(X,h1(X)):- carboxyl(X), not rc(X).
hasAtom(X,h2(X)):- carboxyl(X), not rc(X).
hasAtom(X,h3(X)):- carboxyl(X), not rc(X).
hasAtom(X,h4(X)):- carboxyl(X), not rc(X).
c(h1(X)):- carboxyl(X), not rc(X).
o(h2(X)):- carboxyl(X), not rc(X).
o(h3(X)):- carboxyl(X), not rc(X).
h(h4(X)):- carboxyl(X), not rc(X).
doubleBond(h1(X),h2(X)):- carboxyl(X), not rc(X).
singleBond(h1(X),h3(X)):- carboxyl(X), not rc(X).
singleBond(h3(X),h4(X)):- carboxyl(X), not rc(X).
gc(h1(X)):- carboxyl(X), not rc(X).
gc(h2(X)):- carboxyl(X), not rc(X).
gc(h3(X)):- carboxyl(X), not rc(X).
gc(h4(X)):- carboxyl(X), not rc(X).

%rc(u(X,Z1,Z2,Z3,Z4)):- molecule(X), hasAtom(X,Z1), hasAtom(X,Z2), hasAtom(X,Z3), hasAtom(X,Z4), c(Z1), o(Z2), o(Z3), h(Z4), doubleBond(Z1,Z2), singleBond(Z1,Z3), singleBond(Z3,Z4), not gc(Z1), not gc(Z2), not gc(Z3), not gc(Z4).
%carboxyl(u(X,Z1,Z2,Z3,Z4)):- molecule(X), hasAtom(X,Z1), hasAtom(X,Z2), hasAtom(X,Z3), hasAtom(X,Z4), c(Z1), o(Z2), o(Z3), h(Z4), doubleBond(Z1,Z2), singleBond(Z1,Z3), singleBond(Z3,Z4), not gc(Z1), not gc(Z2), not gc(Z3), not gc(Z4).
%hasAtom(u(X,Z1,Z2,Z3,Z4),Z1):- molecule(X), hasAtom(X,Z1), hasAtom(X,Z2), hasAtom(X,Z3), hasAtom(X,Z4), c(Z1), o(Z2), o(Z3), h(Z4), doubleBond(Z1,Z2), singleBond(Z1,Z3), singleBond(Z3,Z4), not gc(Z1), not gc(Z2), not gc(Z3), not gc(Z4).
%hasAtom(u(X,Z1,Z2,Z3,Z4),Z2):- molecule(X), hasAtom(X,Z1), hasAtom(X,Z2), hasAtom(X,Z3), hasAtom(X,Z4), c(Z1), o(Z2), o(Z3), h(Z4), doubleBond(Z1,Z2), singleBond(Z1,Z3), singleBond(Z3,Z4), not gc(Z1), not gc(Z2), not gc(Z3), not gc(Z4).
%hasAtom(u(X,Z1,Z2,Z3,Z4),Z3):- molecule(X), hasAtom(X,Z1), hasAtom(X,Z2), hasAtom(X,Z3), hasAtom(X,Z4), c(Z1), o(Z2), o(Z3), h(Z4), doubleBond(Z1,Z2), singleBond(Z1,Z3), singleBond(Z3,Z4), not gc(Z1), not gc(Z2), not gc(Z3), not gc(Z4).
%hasAtom(u(X,Z1,Z2,Z3,Z4),Z4):- molecule(X), hasAtom(X,Z1), hasAtom(X,Z2), hasAtom(X,Z3), hasAtom(X,Z4), c(Z1), o(Z2), o(Z3), h(Z4), doubleBond(Z1,Z2), singleBond(Z1,Z3), singleBond(Z3,Z4), not gc(Z1), not gc(Z2), not gc(Z3), not gc(Z4).
%hasGroup(X,u(X,Z1,Z2,Z3,Z4)):- molecule(X), hasAtom(X,Z1), hasAtom(X,Z2), hasAtom(X,Z3), hasAtom(X,Z4), c(Z1), o(Z2), o(Z3), h(Z4), doubleBond(Z1,Z2), singleBond(Z1,Z3), singleBond(Z3,Z4), not gc(Z1), not gc(Z2), not gc(Z3), not gc(Z4).
