4 $Id: graph-container.lisp,v 1.12 2005/07/20 20:39:09 moody Exp $
6 Copyright 1992 - 2003 Experimental Knowledge Systems Lab,
7 University of Massachusetts Amherst MA, 01003-4610
8 Professor Paul Cohen, Director
16 (in-package metabang.graph)
18 ;;; ---------------------------------------------------------------------------
20 ;;; ---------------------------------------------------------------------------
22 (defclass* graph-container (iteratable-container-mixin
23 non-associative-container-mixin
24 initial-contents-mixin
26 container-uses-nodes-mixin)
29 :vertex-class 'graph-container-vertex
30 :directed-edge-class 'graph-container-directed-edge
31 :undirected-edge-class 'graph-container-edge)
33 (:documentation "A graph container is essentially an adjacency list graph representation [?? The Bad name comes from it being implemented with containers... ugh]"))
35 ;;; ---------------------------------------------------------------------------
37 (defclass* graph-container-edge (basic-edge)
38 ((vertex-1 nil ir "`Vertex-1` is one of the two vertexes that an edge connects. In a directed-edge, `vertex-1` is also the `source-edge`.")
39 (vertex-2 nil ir "`Vertex-2` is one of the two vertexes that an edge connects. In a directed edge, `vertex-2` is also the `target-vertex`."))
40 (:export-slots vertex-1 vertex-2)
42 (:documentation "This is the root class for edges in graph-containers. It adds vertex-1 and vertex-2 slots."))
44 ;;; ---------------------------------------------------------------------------
46 (defmethod print-object ((object graph-container-edge) stream)
47 (print-unreadable-object (object stream :type t)
48 (format stream "<~A ~A ~A>" (vertex-1 object) (vertex-2 object)
51 ;;; ---------------------------------------------------------------------------
53 (defclass* weighted-edge (weighted-edge-mixin graph-container-edge)
56 (:documentation "A weighted edge is both a weighted-edge-mixin and a graph-container-edge."))
58 ;;; ---------------------------------------------------------------------------
60 (defclass* graph-container-vertex (basic-vertex)
61 ((vertex-edges nil r))
64 :vertex-edges-container-class 'vector-container)
65 (:documentation "A graph container vertex keeps track of its edges in the the vertex-edges slot. The storage for this defaults to a vector-container but can be changed using the vertex-edges-container-class initarg."))
67 ;;; ---------------------------------------------------------------------------
70 (defcopy-methods graph-container-vertex :copy-all t)
72 ;;; ---------------------------------------------------------------------------
74 (defmethod make-vertex-edges-container ((vertex graph-container-vertex)
75 container-class &rest args)
76 (apply #'make-container container-class args))
78 ;;; ---------------------------------------------------------------------------
80 (defmethod initialize-instance :after ((object graph-container-vertex) &key
81 vertex-edges-container-class)
82 (setf (slot-value object 'vertex-edges)
83 (make-vertex-edges-container object vertex-edges-container-class)))
85 ;;; ---------------------------------------------------------------------------
87 (defmethod make-vertex-container ((graph graph-container) initial-size)
88 (make-container 'simple-associative-container
89 :initial-size initial-size
90 :test (vertex-test graph)))
92 ;;; ---------------------------------------------------------------------------
94 (defmethod make-edge-container ((graph graph-container) initial-size)
95 (make-container 'vector-container :initial-size initial-size
99 ;;; ---------------------------------------------------------------------------
100 ;;; graph-container-directed-edge
101 ;;; ---------------------------------------------------------------------------
103 (defclass* graph-container-directed-edge (directed-edge-mixin
104 graph-container-edge)
107 (:documentation "A graph-container-directed-edge is both a directed-edge-mixin and a graph-container-edge."))
109 ;;; ---------------------------------------------------------------------------
111 (defmethod initialize-instance :after ((object graph-container-directed-edge)
112 &key source-vertex target-vertex)
113 (when (and source-vertex (vertex-1 object))
114 (error "Specify source-vertex or vertex-1, but not both"))
115 (when (and target-vertex (vertex-2 object))
116 (error "Specify target-vertex or vertex-2, but not both"))
118 (setf (slot-value object 'vertex-1) source-vertex))
120 (setf (slot-value object 'vertex-2) target-vertex)))
122 ;;; ---------------------------------------------------------------------------
123 ;;; vertex-1 is defined to be the source vertex of an undirected edge
124 ;;; ---------------------------------------------------------------------------
126 (defmethod source-vertex ((edge graph-container-edge))
129 ;;; ---------------------------------------------------------------------------
130 ;;; vertex-2 is defined to be the target vertex of an undirected edge
131 ;;; ---------------------------------------------------------------------------
133 (defmethod target-vertex ((edge graph-container-edge))
136 ;;; ---------------------------------------------------------------------------
138 (defmethod other-vertex ((edge graph-container-edge)
139 (v graph-container-vertex))
140 (cond ((eq v (vertex-1 edge))
141 (values (vertex-2 edge)))
143 ((eq v (vertex-2 edge))
144 (values (vertex-1 edge)))
146 (t (error "Vertex ~A not part of Edge ~A" v edge))))
148 ;;; ---------------------------------------------------------------------------
150 (defmethod other-vertex ((edge graph-container-edge)
152 (other-vertex edge (find-vertex edge value)))
154 ;;; ---------------------------------------------------------------------------
156 (defmethod add-edge ((graph graph-container) (edge graph-container-edge)
158 (declare (ignore force-new?))
160 (bind ((vertex-1 (vertex-1 edge))
161 (vertex-2 (vertex-2 edge)))
163 (cond ((eq vertex-1 vertex-2)
164 (add-edge-to-vertex edge vertex-1))
166 (add-edge-to-vertex edge vertex-1)
167 (add-edge-to-vertex edge vertex-2))))
170 ;;; ---------------------------------------------------------------------------
172 (defmethod add-edge-to-vertex :around ((edge graph-container-edge)
173 (vertex graph-container-vertex))
174 (insert-item (vertex-edges vertex) edge))
176 ;;; ---------------------------------------------------------------------------
178 (defmethod make-node-for-container ((graph graph-container) (node t) &key)
179 (make-vertex-for-graph graph :element node))
181 ;;; ---------------------------------------------------------------------------
183 (defmethod find-edge-between-vertexes ((graph graph-container)
184 (vertex-1 graph-container-vertex)
185 (vertex-2 graph-container-vertex)
186 &key error-if-not-found?)
187 (declare (ignore error-if-not-found?))
188 (search-for-match (vertex-edges vertex-1)
190 (eq vertex-2 (other-vertex edge vertex-1)))))
192 ;;; ---------------------------------------------------------------------------
194 (defmethod find-edge-between-vertexes-if ((graph graph-container)
195 (vertex-1 graph-container-vertex)
196 (vertex-2 graph-container-vertex)
198 &key error-if-not-found?)
199 (declare (ignore error-if-not-found?))
200 (search-for-match (vertex-edges vertex-1)
202 (and (eq vertex-2 (other-vertex edge vertex-1))
203 (funcall fn edge)))))
205 ;;; ---------------------------------------------------------------------------
207 (defmethod find-edge-between-vertexes-if ((graph graph-container)
211 &key error-if-not-found?)
212 (bind ((v1 (find-vertex graph value-1 error-if-not-found?))
213 (v2 (find-vertex graph value-2 error-if-not-found?)))
214 (find-edge-between-vertexes-if
216 :error-if-not-found? error-if-not-found?)))
218 ;;; ---------------------------------------------------------------------------
221 (defmethod find-edge ((graph graph-container) (edge graph-container-edge)
222 &optional error-if-not-found?)
223 (find-edge-between-vertexes
224 graph (vertex-1 edge) (vertex-2 edge)
225 :error-if-not-found? error-if-not-found?))
227 ;;; ---------------------------------------------------------------------------
229 (defmethod delete-edge ((graph graph-container) (edge graph-container-edge))
230 (delete-item (vertex-edges (vertex-1 edge)) edge)
231 (delete-item (vertex-edges (vertex-2 edge)) edge)
234 ;;; ---------------------------------------------------------------------------
236 (defmethod iterate-edges ((graph graph-container) fn)
237 (iterate-elements (graph-edges graph) fn))
239 ;;; ---------------------------------------------------------------------------
241 (defmethod iterate-edges ((vertex graph-container-vertex) fn)
242 (iterate-elements (vertex-edges vertex) fn))
244 ;;; ---------------------------------------------------------------------------
246 (defmethod iterate-source-edges ((vertex graph-container-vertex) fn)
247 (iterate-elements (vertex-edges vertex)
249 (when (or (undirected-edge-p edge)
250 (eq vertex (target-vertex edge)))
251 (funcall fn edge)))))
253 ;;; ---------------------------------------------------------------------------
255 (defmethod iterate-target-edges ((vertex graph-container-vertex) fn)
256 (iterate-elements (vertex-edges vertex)
258 (when (or (undirected-edge-p edge)
259 (eq vertex (source-vertex edge)))
260 (funcall fn edge)))))
262 ;;; ---------------------------------------------------------------------------
264 (defmethod iterate-children ((vertex graph-container-vertex) fn)
265 (iterate-target-edges vertex
267 (funcall fn (other-vertex edge vertex)))))
269 ;;; ---------------------------------------------------------------------------
271 (defmethod iterate-parents ((vertex graph-container-vertex) fn)
272 (iterate-source-edges vertex
274 (funcall fn (other-vertex edge vertex)))))
276 ;;; ---------------------------------------------------------------------------
278 (defmethod iterate-neighbors ((vertex graph-container-vertex) fn)
279 (iterate-edges vertex
281 (funcall fn (other-vertex edge vertex)))))
283 ;;; ---------------------------------------------------------------------------
285 (defmethod vertexes ((edge graph-container-edge))
286 (collect-using #'iterate-vertexes nil edge))
288 ;;; ---------------------------------------------------------------------------
290 (defmethod has-children-p ((vertex graph-container-vertex))
291 (iterate-target-edges vertex
293 (declare (ignore edge))
294 (return-from has-children-p t)))
297 ;;; ---------------------------------------------------------------------------
299 (defmethod has-parent-p ((vertex graph-container-vertex))
300 (iterate-source-edges vertex
302 (declare (ignore edge))
303 (return-from has-parent-p t)))
306 ;;; ---------------------------------------------------------------------------
308 (defmethod vertices-share-edge-p ((vertex-1 graph-container-vertex)
309 (vertex-2 graph-container-vertex))
310 (iterate-target-edges vertex-1
312 (when (or (eq (target-vertex e) vertex-2)
313 (eq (source-vertex e) vertex-2))
314 (return-from vertices-share-edge-p t))))
316 (iterate-source-edges vertex-1
318 (when (or (eq (target-vertex e) vertex-2)
319 (eq (source-vertex e) vertex-2))
320 (return-from vertices-share-edge-p t))))
325 ;;; ***************************************************************************
327 ;;; ***************************************************************************