Skip to content

Commit

Permalink
Add support for paths
Browse files Browse the repository at this point in the history
  • Loading branch information
pseifer committed Jun 19, 2021
1 parent f232e8a commit e41c011
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 63 deletions.
10 changes: 5 additions & 5 deletions movie-example/shapes.progs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ NODE movieShape [:movie] {
NODE actorShape [BOTTOM] {
:person &
>=1 :acted_in.movieShape &
>=1 name.string
=1 name.string
};

EDGE actedInShape [:acted_in] {
Expand All @@ -17,7 +17,7 @@ EDGE actedInShape [:acted_in] {
NODE directorShape [BOTTOM] {
:person &
>=1 :directed.movieShape &
>=1 name.string
=1 name.string
};

EDGE directedShape [:directed] {
Expand All @@ -28,7 +28,7 @@ EDGE directedShape [:directed] {
NODE producerShape [BOTTOM] {
:person &
>=1 :produced.movieShape &
>=1 name.string
=1 name.string
};

EDGE producedShape [:produced] {
Expand All @@ -39,10 +39,10 @@ EDGE producedShape [:produced] {
NODE writerShape [BOTTOM] {
:person &
>=1 :wrote.movieShape &
>=1 name.string
=1 name.string
};

EDGE wroteShape [:wrote] {
<< writerShape &
>> movieShape
};
};
2 changes: 1 addition & 1 deletion paper-example/graph.lp
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ property(101, name, string("Wernham Hogg")).
property(102, name, string("Gareth Keenan")).
property(203, since, integer(2020)).
property(200, since, integer(1970)).
property(200, since, integer(2007)).
property(200, since, integer(2007)).
9 changes: 4 additions & 5 deletions paper-example/shapes.progs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
NODE employeeShape [:employee] {
:employee &
>= 1 :worksFor.organizationShape
>= 1 worksForShape
};

NODE organizationShape [BOTTOM] {
:company
};
EDGE worksForShape [BOTTOM] {
:worksFor
};
File renamed without changes.
48 changes: 45 additions & 3 deletions scripts/shapeTranslator.py → scripts/shape-transpiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from lark import Lark, Transformer

constraint_store = set()
path_store = set()

class ShapeTransformer(Transformer):

Expand All @@ -30,6 +31,33 @@ def bot(self, b):
def property(self, k):
return "hasProperty({})".format(k[0])

def shaperef(self, s):
c = 'shapeRef({})'.format(s[0])
constraint_store.add(c)
return c

# Paths

def concatpath(self, ps):
p = 'concatpath({},{})'.format(ps[0],ps[1])
path_store.add(p)
return p

def negatepath(self, ps):
p = 'negatepath({})'.format(ps[0])
path_store.add(p)
return p

def choicepath(self, ps):
p = 'choicepath({},{})'.format(ps[0],ps[1])
path_store.add(p)
return p

def repeatpath(self, ps):
p = 'repeatpath({})'.format(ps[0])
path_store.add(p)
return p

# Node Constraint

def nodeconstraint_basic(self, items):
Expand Down Expand Up @@ -61,7 +89,9 @@ def negate(self, n):
return c

def path(self, p):
return p[0]
p = p[0]
path_store.add(p)
return p

def greatereq(self, p):
dat = p[0].data
Expand Down Expand Up @@ -219,8 +249,18 @@ def WORD(self, word):
def NUMBER(self, nr):
return int(nr)


def print_paths():
paths = list(path_store)
paths.sort()
for p in paths:
print('path({}).'.format(p))


def print_constraints():
for c in constraint_store:
constraints = list(constraint_store)
constraints.sort()
for c in constraints:
print('constraint({}).'.format(c))


Expand All @@ -245,13 +285,15 @@ def main(argv):

shapes = ''
with open(infile, 'r') as file:
shapes = file.read()
shapes = file.read() + '\n'

shape_parser = Lark(grammar, start='shapes')

tree = shape_parser.parse(shapes)
transformed = ShapeTransformer().transform(tree)

print_constraints()
print_paths()
print(transformed)

if __name__ == '__main__':
Expand Down
4 changes: 1 addition & 3 deletions scripts/validate-neo4j-dump.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ tmpfile=$(mktemp /tmp/converted-neo4j-dump-XXX.lp)

# Convert from JSON to ASP encoding.

./scripts/translate.py -i "$1" > "$tmpfile"

cat "$tmpfile"
./scripts/graph-encoder.py -i "$1" > "$tmpfile"

./validate.sh "$tmpfile" "$2"

Expand Down
49 changes: 27 additions & 22 deletions src/grammar.ebnf
Original file line number Diff line number Diff line change
Expand Up @@ -4,49 +4,54 @@ edgeshape : "EDGE" shape "[" edgetarget "]" "{" edgeconstraint "}" ";"
nodetarget : ":" label
| NUMBER -> nid
| "BOTTOM" -> bot
| property -> property
| "BOTTOM" -> bot
| property -> property
?nodeconstraint : nodeconstraint_or
?nodeconstraint_or : [nodeconstraint_or "|"] nodeconstraint_and
?nodeconstraint_and : [nodeconstraint_and "&"] nodeconstraint_basic
nodeconstraint_basic : "TOP" -> top
| "BOTTOM" -> bot
| shape
| shape -> shaperef
| ":" label
| NUMBER -> rnid
| "!" nodeconstraint -> negate
| comp NUMBER path "." nodeconstraint -> greatereq
| comp NUMBER property "." predicate -> countprop
| comp NUMBER edgeconstraint -> greatereqe
| path "==" path -> compare
| path property "==" path property -> comparevalue
| property "==" property -> equals
| NUMBER -> rnid
| "!" nodeconstraint_basic -> negate
| comp NUMBER choicepath "." nodeconstraint_basic -> greatereq
| comp NUMBER property "." predicate -> countprop
| comp NUMBER edgeconstraint -> greatereqe
| choicepath "==" choicepath -> compare
| choicepath property "==" path property -> comparevalue
| property "==" property -> equals
| "(" nodeconstraint ")"

path : ":" labelref
?choicepath : [choicepath "|"] concatpath
?concatpath : [concatpath "/"] path
path : ":" label
| "-" path -> negatepath
| "(" choicepath ")"
| path "+" -> repeatpath

predicate : "string" -> string
| "int" -> int

edgetarget : ":" label
| NUMBER -> eid
| "BOTTOM" -> bot
| property -> property
| "BOTTOM" -> bot
| property -> property

?edgeconstraint : edgeconstraint_or
?edgeconstraint_or : [edgeconstraint_or "|"] edgeconstraint_and
?edgeconstraint_and : [edgeconstraint_and "&"] edgeconstraint_basic
edgeconstraint_basic : "TOP" -> top
| "BOTTOM" -> bot
| shape
| shape -> shaperef
| ":" label
| NUMBER -> reid
| "!" edgeconstraint -> negate
| comp NUMBER property "." predicate -> countprop
| property "==" property -> equals
| "<<" nodeconstraint -> left
| ">>" nodeconstraint -> right
| NUMBER -> reid
| "!" edgeconstraint_basic -> negate
| comp NUMBER property "." predicate -> countprop
| property "==" property -> equals
| "<<" nodeconstraint_basic -> left
| ">>" nodeconstraint_basic -> right
| "(" edgeconstraint ")"

comp : "<=" -> le
Expand All @@ -64,7 +69,7 @@ WORD : LCASE_LETTER CHAR+
CHAR : LETTER | DIGIT | "_"
NUMBER : DIGIT+

COMMENT : "//" /(.)+/ NEWLINE
COMMENT : "%" /(.)*/ NEWLINE

%import common.LCASE_LETTER
%import common.LETTER
Expand Down
47 changes: 26 additions & 21 deletions src/progs.lp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ assignE(E,S,R) :- edgeshape(S,C,_), satisfiesE(E,C,R).
assignN(N,S,yes) | assignN(N,S,no) | assignN(N,S,maybe) :- node(N), nodeshape(S).
assignE(E,S,yes) | assignE(E,S,no) | assignE(E,S,maybe) :- edge(E), edgeshape(S).

% -- paths --

path(N1,N2,label(P)) :- edge(N1,E,N2), label(E,P).
path(N1,N2,concatpath(P1,P2)) :- path(P1), path(P2), path(N1,N,P1), path(N,N2,P2).
path(N1,N2,negatepath(P)) :- path(P), path(N2,N1,P).
path(N1,N2,choicepath(P1,P2)) :- path(P1), path(P2), path(N1,N2,P1).
path(N1,N2,choicepath(P1,P2)) :- path(P1), path(P2), path(N1,N2,P2).
path(N1,N2,repeatpath(P)) :- path(P), path(N1,N2,P).
path(N1,N2,repeatpath(P)) :- path(P), path(N1,N,P), path(N,N2,repeatpath(P)).

% -- top --

satisfiesN(N,top,yes) :- node(N).
Expand All @@ -58,7 +68,7 @@ satisfiesN(N,shapeRef(S),R) :- node(N), constraint(shapeRef(S)),
assignN(N,S,R).

satisfiesE(E,shapeRef(S),R) :- edge(E), constraint(shapeRef(S)),
assignN(E,S,R).
assignE(E,S,R).

% -- nodeId/edgeID --

Expand Down Expand Up @@ -100,25 +110,25 @@ satisfiesE(E,and(C1,C2),R) :- edge(E), constraint(and(C1,C2)),

% -- greaterEq --

satisfiesN(N,greaterEq(L,S,I),yes) :- node(N), constraint(greaterEq(L,S,I)),
countShape(N,L,S,C), C >= I.
satisfiesN(N,greaterEq(P,NC,I),yes) :- node(N), constraint(greaterEq(P,NC,I)),
countNC(N,P,NC,C), C >= I.

satisfiesN(N,greaterEq(L,S,I),no) :- node(N), constraint(greaterEq(L,S,I)),
countAll(N,L,C1), countNoShape(N,L,S,C2),
satisfiesN(N,greaterEq(P,NC,I),no) :- node(N), constraint(greaterEq(P,NC,I)),
countAll(N,P,C1), countNoNC(N,P,NC,C2),
C1 - C2 < I.

satisfiesN(N,greaterEq(L,S,I), maybe) :- node(N), constraint(greaterEq(L,S,I)),
not satisfiesN(N,greaterEq(L,S,I),yes),
not satisfiesN(N,greaterEq(L,S,I),no).
satisfiesN(N,greaterEq(P,NC,I), maybe) :- node(N), constraint(greaterEq(P,NC,I)),
not satisfiesN(N,greaterEq(P,NC,I),yes),
not satisfiesN(N,greaterEq(P,NC,I),no).

countAll(N,L,C) :- node(N), labels(L),
#count { Y: edge(N,E,Y), label(E,L) } = C.
countAll(N,P,C) :- node(N), path(P),
#count { Y: path(N,Y,P) } = C.

countShape(N,L,S,C) :- node(N), labels(L), nodeshape(S),
#count { Y: edge(N,E,Y), label(E,L), assignN(Y,S,yes) } = C.
countNC(N,P,NC,C) :- node(N), path(P), constraint(NC),
#count { Y: path(N,Y,P), satisfiesN(Y,NC,yes) } = C.

countNoShape(N,L,S,C) :- node(N), labels(L), nodeshape(S),
#count { Y: edge(N,E,Y), label(E,L), assignN(Y,S,no) } = C.
countNoNC(N,P,NC,C) :- node(N), path(P), constraint(NC),
#count { Y: path(N,Y,P), satisfiesN(Y,NC,no) } = C.

% -- compare -- TODO

Expand Down Expand Up @@ -189,10 +199,5 @@ satisfiesE(E,equals(K1,K2),no) :- edge(E), constraint(equals(K1,K2)),

% -- left/right --

satisfiesE(E,left(NC),yes) :- edge(E), edge(N,E,_), constraint(left(NC)), satisfiesN(N,NC,yes).
satisfiesE(E,left(NC),no) :- edge(E), edge(N,E,_), constraint(left(NC)), satisfiesN(N,NC,no).
satisfiesE(E,left(NC),maybe) :- edge(E), edge(N,E,_), constraint(left(NC)), satisfiesN(N,NC,maybe).

satisfiesE(E,right(NC),yes) :- edge(E), edge(_,E,N), constraint(right(NC)), satisfiesN(N,NC,yes).
satisfiesE(E,right(NC),no) :- edge(E), edge(_,E,N), constraint(right(NC)), satisfiesN(N,NC,no).
satisfiesE(E,right(NC),maybe) :- edge(E), edge(_,E,N), constraint(right(NC)), satisfiesN(N,NC,maybe).
satisfiesE(E,left(NC),R) :- edge(E), edge(N,E,_), constraint(left(NC)), satisfiesN(N,NC,R).
satisfiesE(E,right(NC),R) :- edge(E), edge(_,E,N), constraint(right(NC)), satisfiesN(N,NC,R).
4 changes: 1 addition & 3 deletions validate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@

tmpfile=$(mktemp /tmp/converted-shapes-XXX.lp)

./scripts/shapeTranslator.py -i "$2" > "$tmpfile"

cat "$tmpfile"
./scripts/shape-transpiler.py -i "$2" > "$tmpfile"

clingo src/progs.lp src/display.lp "$1" "$tmpfile"

Expand Down

0 comments on commit e41c011

Please sign in to comment.