-
Notifications
You must be signed in to change notification settings - Fork 1
/
substitution-set.cl
184 lines (163 loc) · 6.48 KB
/
substitution-set.cl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
;;; SNePS 3: Substitution-Set
;;; ====================
;;; Michael Kandefer
;;; Department of Computer Science and Engineering
;;; State University of New York at Buffalo
;;; The contents of this file are subject to the University at Buffalo
;;; Public License Version 1.0 (the "License"); you may not use this file
;;; except in compliance with the License. You may obtain a copy of the
;;; License at http://www.cse.buffalo.edu/sneps/Downloads/ubpl.pdf.
;;;
;;; Software distributed under the License is distributed on an "AS IS"
;;; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
;;; the License for the specific language governing rights and limitations
;;; under the License.
;;;
;;; The Original Code is SNePS 3.
;;;
;;; The Initial Developer of the Original Code is Research Foundation of
;;; State University of New York, on behalf of University at Buffalo.
;;;
;;; Portions created by the Initial Developer are Copyright (C) 2007
;;; Research Foundation of State University of New York, on behalf of
;;; University at Buffalo. All Rights Reserved.
;;;
;;; Contributor(s): ______________________________________.
(defpackage :sneps3-substitution-set
(:nicknames :subs-set)
(:export
#:copy-all
#:union #:union-into-first
#:add-binding
#:copy-substitution-set
#:get-all-terms-from-var #:join #:join-into-first
#:new-substitution-set #:remove-if
#:remove-if-contains-vars #:remove-if-contains-value
#:substitution-set
#:*emptysubset*)
(:shadow cl:remove-if cl:append cl:union))
(in-package :sneps3-substitution-set)
(eval-when (:compile-toplevel :load-toplevel :execute)
(defstruct (substitution-set
(:include set:set (set:type 'subs:substitution))
(:print-function set:print-set))
"Substitution-set definition. Like regular sets in structure, except
every element is a substitution.")
(defun new-substitution-set (&key (items '()) (size 12 size-given))
"Returns a new substitution-set."
(let ((new-subs-set
(make-substitution-set
:table (make-hash-table
:test #'equalp
:size (cond
(size-given size)
(items (length items))
(t size))
:rehash-size 2.0))))
(when (consp items)
(set:add-items items new-subs-set))
new-subs-set)))
(eval-when (:load-toplevel :execute)
(defconstant *emptysubset* (new-substitution-set :size 0)
"A constant empty set
to be used whenever an empty set is to be returned from some function.
It must never be destructively changed."))
(defun copy-substitution-set (subs-set)
"Returns a copy of the given substitution-set"
(check-type subs-set substitution-set)
(let ((subs-set-copy (new-substitution-set)))
(maphash #'(lambda (k v)
(declare (ignore v))
(set:add-item k subs-set-copy))
(substitution-set-table subs-set))
subs-set-copy))
(defmethod get-all-terms-from-var (var (subs-set substitution-set))
"Returns the set of terms bound to var in this substitution set."
(let ((result (set:new-set)))
(set:loopset
for subs in subs-set
for term = (subs:var-to-term var subs)
when term
do (set:add-item term result))
result))
(defun remove-if (pred set)
"Returns a new set without those elements in set that pass the pred test."
(check-type set substitution-set)
(let ((result (new-substitution-set)))
(set:loopset for subs in set
do (unless (funcall pred subs)
(set:add-item subs result)))
result))
(defmethod join ((first substitution-set) (second substitution-set))
"Joins two substitution sets together. Results in a permuation of
the elements between them, such that each substitution has the same
number of bindings, and the same variables. Bound terms differ
between substitutions.
This function was written for creating substitution-sets for matching
term-sets. As such some assumptions are made that wouldn't be used for
joining normal substitution sets together."
(cond ((set:emptyp first) second)
((set:emptyp second) first)
(t
(let ((result (new-substitution-set)))
(set:loopset
for subs1 in first
do (set:loopset
for subs2 in second
when (not (subs:equal-bound-term subs1 subs2))
do (set:add-item (subs:join subs1 subs2) result)))
result))))
(defmethod join-into-first ((first substitution-set) (second substitution-set))
"Same as join, except modifies the first parameter instead of
creating a new substitution."
(cond ((set:emptyp first)
(set:loopset for subs in second
do (set:add-item subs first))
first)
((set:emptyp second) first)
(t
(set:loopset
for subs1 in first
do (set:remove-item subs1 first)
(set:loopset
for subs2 in second
when (not (subs:equal-bound-term subs1 subs2))
do (set:add-item (subs:join subs1 subs2) first)))
first)))
(defmethod union ((s1 substitution-set) (s2 substitution-set))
"Returns a substitution set that is the union of the two argument sets."
(let ((s3 (new-substitution-set :size (+ (set:cardinality s1) (set:cardinality s2)))))
(loop for item being each hash-key of (substitution-set-table s1)
do (set:add-item item s3))
(loop for item being each hash-key of (substitution-set-table s2)
do (set:add-item item s3))
s3))
(defmethod union-into-first ((s1 substitution-set) (s2 substitution-set))
"Returns a substitution set that is the union of the two argument
sets. The first set gets any new values, as such, this function is destructive."
(loop for item being each hash-key of (substitution-set-table s2)
do (set:add-item item s1))
s1)
(defmethod add-binding (var term (subs-set substitution-set))
"Creates a new substitution from subs-set and adds a var-term binding to each
substitution in a new substitution set."
(let ((new-subs (subs:new-substitution :var-term-pairs (list var term)))
(new-subs-set (new-substitution-set)))
(if (set:emptyp subs-set)
(set:add-item new-subs new-subs-set)
(set:loopset
for subs in subs-set
do (set:add-item (subs:join subs new-subs) new-subs-set)))
new-subs-set))
(defmethod copy-all ((old-subs substitution-set)
(new-subs substitution-set))
"Copies all elements from the second supstitution into the first,
after clearing the first. Allows forreferences to be retained."
(setf (substitution-set-table old-subs)
(make-hash-table
:test #'equalp
:size (set:cardinality new-subs)
:rehash-size 2.0))
(union-into-first old-subs new-subs)
old-subs)