guile-rdf/rdf/entailment/simple.scm

simple.scm

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
  (match t1
98
    (($ rdf-triple s1 p1 o1)
99
     (match t2
100
       (($ rdf-triple s2 p2 o2)
101
        (if (and (or (equal? s1 s2) (blank-node? s1))
102
                 (equal? p1 p2)
103
                 (or (equal? o1 o2) (blank-node? o1)))
104
            (list 'and
105
                  (if (blank-node? s1)
106
                      (list 'equiv s1 s2)
107
                      'none)
108
                  (if (blank-node? o1)
109
                      (list 'equiv o1 o2)
110
                      'none))
111
            #f))))))
112
113
(define (generate-constraints t1 g2)
114
  (match g2
115
    ('() 'bot)
116
    ((t2 g2 ...)
117
     (let ((c (generate-triple-constraints t1 t2)))
118
       (if c
119
         (list 'or c (generate-constraints t1 g2))
120
         (generate-constraints t1 g2))))))
121
122
(define (validate-mapping mapping g1 g2)
123
  (match g1
124
    ('() #t)
125
    ((t1 g1 ...)
126
     (and (not (null? (filter
127
                        (lambda (t2)
128
                          (let ((s1 (rdf-triple-subject t1))
129
                                (s2 (rdf-triple-subject t2))
130
                                (p1 (rdf-triple-predicate t1))
131
                                (p2 (rdf-triple-predicate t2))
132
                                (o1 (rdf-triple-object t1))
133
                                (o2 (rdf-triple-object t2)))
134
                            (and
135
                              (if (blank-node? s1)
136
                                  (equal? (assoc-ref mapping s1) s2)
137
                                  (equal? s1 s2))
138
                              (equal? p1 p2)
139
                              (if (blank-node? o1)
140
                                  (equal? (assoc-ref mapping o1) o2)
141
                                  (equal? o1 o2)))))
142
                        g2)))
143
          (validate-mapping mapping g1 g2)))))
144
145
(define (entails? g e)
146
  "Return true if g entails e"
147
  (or (not (consistent-graph? g))
148
      (let* ((constraints (fold (lambda (t constraints)
149
                                  (list 'and (generate-constraints t g) constraints))
150
                                'none e))
151
             (disjunctions (to-disjunctions constraints)))
152
        (if (equal? disjunctions 'bot)
153
            #f
154
            (let loop ((disjunctions (filter sat? disjunctions)))
155
              (match disjunctions
156
                ('() #f)
157
                ((mapping disjunctions ...)
158
                 (if (validate-mapping mapping e g)
159
                   #t
160
                   (loop disjunctions)))))))))
161