Add simple entailment regime and associated tests
Makefile.am
1 | 1 | include guile.am | |
2 | 2 | ||
3 | 3 | SOURCES= \ | |
4 | + | rdf/entailment/simple.scm \ | |
4 | 5 | rdf/rdf.scm \ | |
5 | 6 | rdf/xsd.scm \ | |
6 | 7 | turtle/parser.scm \ | |
… | |||
12 | 13 | ||
13 | 14 | TEST_EXTENSIONS = .scm | |
14 | 15 | SCM_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) $(top_srcdir)/tap-driver.sh --color-tests yes --ignore-exit | |
15 | - | TESTS = tests/turtle.scm | |
16 | + | TESTS = tests/turtle.scm tests/semantics.scm | |
16 | 17 | EXTRA_DIST += $(TESTS) |
configure.ac
11 | 11 | GUILE_SITE_DIR | |
12 | 12 | ||
13 | 13 | AC_CONFIG_FILES([pre-inst-env], [chmod +x pre-inst-env]) | |
14 | + | AC_CONFIG_FILES([tests/semantics.scm], [chmod +x tests/semantics.scm]) | |
14 | 15 | AC_CONFIG_FILES([tests/turtle.scm], [chmod +x tests/turtle.scm]) | |
15 | 16 | AC_CONFIG_FILES(Makefile) | |
16 | 17 | AC_REQUIRE_AUX_FILE([tap-driver.sh]) |
rdf/entailment/simple.scm unknown status 1
1 | + | ;;;; Copyright (C) 2020 Julien Lepiller <julien@lepiller.eu> | |
2 | + | ;;;; | |
3 | + | ;;;; This library is free software; you can redistribute it and/or | |
4 | + | ;;;; modify it under the terms of the GNU Lesser General Public | |
5 | + | ;;;; License as published by the Free Software Foundation; either | |
6 | + | ;;;; version 3 of the License, or (at your option) any later version. | |
7 | + | ;;;; | |
8 | + | ;;;; This library is distributed in the hope that it will be useful, | |
9 | + | ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | + | ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
11 | + | ;;;; Lesser General Public License for more details. | |
12 | + | ;;;; | |
13 | + | ;;;; You should have received a copy of the GNU Lesser General Public | |
14 | + | ;;;; License along with this library; if not, write to the Free Software | |
15 | + | ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
16 | + | ;;;; | |
17 | + | ||
18 | + | (define-module (rdf entailment simple) | |
19 | + | #:use-module (ice-9 match) | |
20 | + | #:use-module (rdf rdf) | |
21 | + | #:use-module (srfi srfi-1) | |
22 | + | #:export (consistent-graph? | |
23 | + | entails?)) | |
24 | + | ||
25 | + | ;; The simple entailment regime doesn't impose any condition of graph consistency. | |
26 | + | (define consistent-graph? (const #t)) | |
27 | + | ||
28 | + | ;; G entails E if E has an instance (where blank nodes are replaced by literals | |
29 | + | ;; or IRIs) that is a subgraph of G. | |
30 | + | ;; | |
31 | + | ;; We re-use similar procedures to verifying isomorphism of graphs, but this time | |
32 | + | ;; blank nodes can also map to literals and IRIs. | |
33 | + | ||
34 | + | (define (sat? equivalences) | |
35 | + | "Return whether the set of equivalences satisfies the condition that it represents | |
36 | + | an isomorphism between two blank node sets: for every equality, check that the | |
37 | + | first component is always associated to the same second component, and that the | |
38 | + | second component is always associated with the first." | |
39 | + | (match equivalences | |
40 | + | ('() #t) | |
41 | + | (((first . second) equivalences ...) | |
42 | + | (if (and (null? (filter | |
43 | + | (lambda (eq) | |
44 | + | (and (equal? (car eq) first) | |
45 | + | (not (equal? (cdr eq) second)))) | |
46 | + | equivalences)) | |
47 | + | (null? (filter | |
48 | + | (lambda (eq) | |
49 | + | (and (not (equal? (car eq) first)) | |
50 | + | (equal? (cdr eq) second))) | |
51 | + | equivalences))) | |
52 | + | (sat? equivalences) | |
53 | + | #f)))) | |
54 | + | ||
55 | + | (define (merge-joins l1 l2) | |
56 | + | (cond | |
57 | + | ((null? l1) l2) | |
58 | + | ((null? l2) l1) | |
59 | + | (else | |
60 | + | (fold | |
61 | + | (lambda (e1 res) | |
62 | + | (append | |
63 | + | (map (lambda (e2) | |
64 | + | (append e1 e2)) | |
65 | + | l2) | |
66 | + | res)) | |
67 | + | '() | |
68 | + | l1)))) | |
69 | + | ||
70 | + | (define (to-disjunctions constraints) | |
71 | + | (match constraints | |
72 | + | (('equiv b1 b2) (list (list (cons b1 b2)))) | |
73 | + | ('none (list (list))) | |
74 | + | ('bot 'bot) | |
75 | + | (('or e1 e2) | |
76 | + | (let ((e1 (to-disjunctions e1)) | |
77 | + | (e2 (to-disjunctions e2))) | |
78 | + | (cond | |
79 | + | ((equal? e2 'bot) | |
80 | + | e1) | |
81 | + | ((equal? e1 'bot) | |
82 | + | e2) | |
83 | + | (else | |
84 | + | (append e1 e2))))) | |
85 | + | (('and e1 e2) | |
86 | + | (let ((e1 (to-disjunctions e1)) | |
87 | + | (e2 (to-disjunctions e2))) | |
88 | + | (cond | |
89 | + | ((equal? e1 'bot) | |
90 | + | 'bot) | |
91 | + | ((equal? e2 'bot) | |
92 | + | 'bot) | |
93 | + | (else | |
94 | + | (merge-joins e1 e2))))))) | |
95 | + | ||
96 | + | (define (generate-triple-constraints t1 t2) | |
97 | + | (pk 'generate t1 t2) | |
98 | + | (match t1 | |
99 | + | (($ rdf-triple s1 p1 o1) | |
100 | + | (match t2 | |
101 | + | (($ rdf-triple s2 p2 o2) | |
102 | + | (if (and (or (equal? s1 s2) (blank-node? s1)) | |
103 | + | (equal? p1 p2) | |
104 | + | (or (equal? o1 o2) (blank-node? o1))) | |
105 | + | (list 'and | |
106 | + | (if (blank-node? s1) | |
107 | + | (list 'equiv s1 s2) | |
108 | + | 'none) | |
109 | + | (if (blank-node? o1) | |
110 | + | (list 'equiv o1 o2) | |
111 | + | 'none)) | |
112 | + | #f)))))) | |
113 | + | ||
114 | + | (define (generate-constraints t1 g2) | |
115 | + | (match g2 | |
116 | + | ('() 'bot) | |
117 | + | ((t2 g2 ...) | |
118 | + | (let ((c (generate-triple-constraints t1 t2))) | |
119 | + | (if c | |
120 | + | (list 'or c (generate-constraints t1 g2)) | |
121 | + | (generate-constraints t1 g2)))))) | |
122 | + | ||
123 | + | (define (validate-mapping mapping g1 g2) | |
124 | + | (match g1 | |
125 | + | ('() #t) | |
126 | + | ((t1 g1 ...) | |
127 | + | (and (not (null? (filter | |
128 | + | (lambda (t2) | |
129 | + | (let ((s1 (rdf-triple-subject t1)) | |
130 | + | (s2 (rdf-triple-subject t2)) | |
131 | + | (p1 (rdf-triple-predicate t1)) | |
132 | + | (p2 (rdf-triple-predicate t2)) | |
133 | + | (o1 (rdf-triple-object t1)) | |
134 | + | (o2 (rdf-triple-object t2))) | |
135 | + | (and | |
136 | + | (if (blank-node? s1) | |
137 | + | (equal? (assoc-ref mapping s1) s2) | |
138 | + | (equal? s1 s2)) | |
139 | + | (equal? p1 p2) | |
140 | + | (if (blank-node? o1) | |
141 | + | (equal? (assoc-ref mapping o1) o2) | |
142 | + | (equal? o1 o2))))) | |
143 | + | g2))) | |
144 | + | (validate-mapping mapping g1 g2))))) | |
145 | + | ||
146 | + | (define (entails? g e) | |
147 | + | "Return true if g entails e" | |
148 | + | (or (not (consistent-graph? g)) | |
149 | + | (let* ((constraints (fold (lambda (t constraints) | |
150 | + | (list 'and (generate-constraints t g) constraints)) | |
151 | + | 'none e)) | |
152 | + | (disjunctions (to-disjunctions constraints))) | |
153 | + | (if (equal? disjunctions 'bot) | |
154 | + | #f | |
155 | + | (let loop ((disjunctions (filter sat? disjunctions))) | |
156 | + | (match disjunctions | |
157 | + | ('() #f) | |
158 | + | ((mapping disjunctions ...) | |
159 | + | (if (validate-mapping mapping e g) | |
160 | + | #t | |
161 | + | (loop disjunctions))))))))) |
test-modules/online.scm
20 | 20 | #:use-module (rnrs bytevectors) | |
21 | 21 | #:use-module (srfi srfi-1) | |
22 | 22 | #:use-module (test-modules result) | |
23 | + | #:use-module ((rdf entailment simple) #:prefix simple:) | |
23 | 24 | #:use-module (rdf rdf) | |
24 | 25 | #:use-module (srfi srfi-1) | |
25 | 26 | #:use-module (turtle tordf) | |
… | |||
47 | 48 | (define (execute-test test) | |
48 | 49 | (let* ((predicates (test-case-document test)) | |
49 | 50 | (type (car (get-objects predicates "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"))) | |
50 | - | (type (substring type (string-length "http://www.w3.org/ns/rdftest#"))) | |
51 | + | (type (car (reverse (string-split type #\#)))) | |
51 | 52 | (action (car (get-objects predicates "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#action")))) | |
52 | 53 | (turtle->rdf (get-test-doc action) action))) | |
53 | 54 | ||
54 | 55 | (define (run-test test) | |
55 | 56 | (let* ((predicates (test-case-document test)) | |
56 | 57 | (type (car (get-objects predicates "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"))) | |
57 | - | (type (substring type (string-length "http://www.w3.org/ns/rdftest#"))) | |
58 | + | (type (car (reverse (string-split type #\#)))) | |
58 | 59 | (result | |
59 | 60 | (catch #t | |
60 | 61 | (lambda () | |
… | |||
100 | 101 | #:result 'fail | |
101 | 102 | #:reason (format #f "expected ~a but got ~a" | |
102 | 103 | expected result))))))) | |
104 | + | ((member type '("PositiveEntailmentTest" "NegativeEntailmentTest")) | |
105 | + | (let* ((regime (rdf-literal-lexical-form | |
106 | + | (car | |
107 | + | (get-objects | |
108 | + | predicates | |
109 | + | (string-append | |
110 | + | "http://www.w3.org/2001/sw/DataAccess/tests/" | |
111 | + | "test-manifest#entailmentRegime"))))) | |
112 | + | (expected | |
113 | + | (car | |
114 | + | (get-objects | |
115 | + | predicates | |
116 | + | (string-append "http://www.w3.org/2001/sw/DataAccess/tests/" | |
117 | + | "test-manifest#result")))) | |
118 | + | (expected | |
119 | + | (catch #t | |
120 | + | (lambda () | |
121 | + | (if expected | |
122 | + | (turtle->rdf (get-test-doc expected) expected) | |
123 | + | #f)) | |
124 | + | (lambda (key . value) | |
125 | + | (cons key value))))) | |
126 | + | (match regime | |
127 | + | ("simple" | |
128 | + | (if (if (equal? expected #f) | |
129 | + | (simple:consistent-graph? result) | |
130 | + | (simple:entails? result expected)) | |
131 | + | (if (equal? type "PositiveEntailmentTest") | |
132 | + | (update-test-case test #:result 'pass) | |
133 | + | (update-test-case test | |
134 | + | #:result 'fail | |
135 | + | #:reason "Expected negative result, got positive")) | |
136 | + | (if (equal? type "PositiveEntailmentTest") | |
137 | + | (update-test-case test | |
138 | + | #:result 'fail | |
139 | + | #:reason (format #f "Expected positive result, got negative")) | |
140 | + | (update-test-case test #:result 'pass)))) | |
141 | + | (_ (update-test-case test | |
142 | + | #:result 'skip | |
143 | + | #:reason (format #f "Unrecognized entailment regime: ~a" | |
144 | + | regime)))))) | |
103 | 145 | (else | |
104 | 146 | (update-test-case test | |
105 | 147 | #:result 'skip | |
… | |||
157 | 199 | manifest)))) | |
158 | 200 | ||
159 | 201 | (define (find-rest node) | |
160 | - | (pk 'rest node) | |
161 | 202 | (rdf-triple-object | |
162 | 203 | (car | |
163 | 204 | (filter |
test-modules/testsuite.scm
17 | 17 | ||
18 | 18 | (define-module (test-modules testsuite) | |
19 | 19 | #:export (expected-failures | |
20 | - | turtle-test-manifest)) | |
20 | + | turtle-test-manifest | |
21 | + | semantics-test-manifest)) | |
21 | 22 | ||
22 | 23 | (define expected-failures | |
23 | 24 | '()) | |
24 | 25 | ||
25 | 26 | (define turtle-test-manifest "http://www.w3.org/2013/TurtleTests/manifest.ttl") | |
27 | + | (define semantics-test-manifest | |
28 | + | "https://www.w3.org/2013/rdf-mt-tests/manifest.ttl") |
tests/semantics.scm.in unknown status 1
1 | + | #!@abs_top_srcdir@/pre-inst-env guile | |
2 | + | !# | |
3 | + | ;;;; Copyright (C) 2020 Julien Lepiller <julien@lepiller.eu> | |
4 | + | ;;;; | |
5 | + | ;;;; This library is free software; you can redistribute it and/or | |
6 | + | ;;;; modify it under the terms of the GNU Lesser General Public | |
7 | + | ;;;; License as published by the Free Software Foundation; either | |
8 | + | ;;;; version 3 of the License, or (at your option) any later version. | |
9 | + | ;;;; | |
10 | + | ;;;; This library is distributed in the hope that it will be useful, | |
11 | + | ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | + | ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | + | ;;;; Lesser General Public License for more details. | |
14 | + | ;;;; | |
15 | + | ;;;; You should have received a copy of the GNU Lesser General Public | |
16 | + | ;;;; License along with this library; if not, write to the Free Software | |
17 | + | ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
18 | + | ;;;; | |
19 | + | ||
20 | + | (use-modules (test-modules online)) | |
21 | + | (use-modules (test-modules result)) | |
22 | + | (use-modules (test-modules testsuite)) | |
23 | + | ||
24 | + | (run-test-suite semantics-test-manifest expected-failures tap-driver) |
turtle/tordf.scm
89 | 89 | (not (string-any #\> iri)))) | |
90 | 90 | ||
91 | 91 | (define (parse-iri iri state) | |
92 | - | (pk 'iri iri) | |
93 | 92 | (match iri | |
94 | 93 | (('iri ('prefixed-name ('pname-ln ('pname-ns ns) ('pn-local suffix)))) | |
95 | 94 | `(("iri" . ,(string-append (assoc-ref (parser-state-namespaces state) ns) |