2 ;;; GRAPHS - graph theory package for Maxima
4 ;;; Copyright (C) 2007-2011 Andrej Vodopivec <andrej.vodopivec@gmail.com>
6 ;;; This program is free software; you can redistribute it and/or modify
7 ;;; it under the terms of the GNU General Public License as published by
8 ;;; the Free Software Foundation; either version 2 of the License, or
9 ;;; (at your option) any later version.
11 ;;; This program is distributed in the hope that it will be useful,
12 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ;;; GNU General Public License for more details.
16 ;;; You should have received a copy of the GNU General Public License
17 ;;; along with this program; if not, write to the Free Software
18 ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
24 ;;; graph and digraph datastructure
26 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
30 ($put
'$graphs
2.0 '$version
)
34 (lambda (stru strm depth
)
35 (format strm
"GRAPH(~a vertices, ~a edges)" (graph-order stru
) (graph-size stru
)))))
39 (vertex-labels (make-hash-table))
42 (edge-weights (make-hash-table :test
#'equal
))
43 (neighbors (make-hash-table)))
47 (lambda (stru strm depth
)
48 (format strm
"DIGRAPH(~a vertices, ~a arcs)" (digraph-order stru
) (digraph-size stru
)))))
52 (vertex-labels (make-hash-table))
55 (edge-weights (make-hash-table :test
#'equal
))
56 (in-neighbors (make-hash-table))
57 (out-neighbors (make-hash-table)))
59 (defun require-graph (m ar gr
)
61 ($error
(format nil
"Argument ~a to `~a' is not a graph:" ar m
) gr
)))
63 (defun require-digraph (m ar gr
)
64 (unless (digraph-p gr
)
65 ($error
(format nil
"Argument ~a to `~a' is not a directed graph:" ar m
) gr
)))
67 (defun require-graph-or-digraph (m ar gr
)
68 (unless (or (graph-p gr
) (digraph-p gr
))
69 ($error
(format nil
"Argument ~a to `~a' is not a graph:" ar m
) gr
)))
71 (defmfun $print_graph
(gr)
72 (require-graph-or-digraph 'print_graph
1 gr
)
75 (format t
"~%Graph on ~d vertices with ~d edges."
76 (graph-order gr
) (graph-size gr
))
77 (when (> (graph-order gr
) 0 )
78 (format t
"~%Adjacencies:"))
79 (dolist (v (graph-vertices gr
))
80 (format t
"~% ~2d :" v
)
81 (dolist (u (neighbors v gr
))
82 (format t
" ~2d" u
))))
84 (format t
"~%Digraph on ~d vertices with ~d arcs."
85 (digraph-order gr
) (digraph-size gr
))
86 (when (> (digraph-order gr
) 0 )
87 (format t
"~%Adjacencies:"))
88 (dolist (v (digraph-vertices gr
))
89 (format t
"~% ~2d :" v
)
90 (dolist (u (out-neighbors v gr
))
91 (format t
" ~2d" u
)))))
95 (defmfun $is_graph
(x)
98 (defmfun $is_digraph
(x)
101 (defmfun $is_graph_or_digraph
(x)
102 (or (graph-p x
) (digraph-p x
)))
104 (defmfun $graph_order
(gr)
105 (require-graph-or-digraph 'graph_order
1 gr
)
110 (defmfun $graph_size
(gr)
111 (require-graph-or-digraph 'graph_size
1 gr
)
116 (defmfun $get_positions
(gr)
117 (require-graph-or-digraph 'get_positions
1 gr
)
119 (graph-vertex-positions gr
)
120 (digraph-vertex-positions gr
)))
122 (defmfun $set_positions
(pos gr
)
123 (require-graph-or-digraph 'set_positions
2 gr
)
125 (setf (graph-vertex-positions gr
) pos
)
126 (setf (digraph-vertex-positions gr
) pos
)))
128 (defmfun $copy_graph
(gr)
129 (require-graph-or-digraph 'copy_graph
1 gr
)
131 (let ((g (make-graph)))
132 (dolist (v (graph-vertices gr
))
134 (let ((l (get-vertex-label v gr
)))
135 (if l
(set-vertex-label v l g
))))
136 (dolist (e (graph-edges gr
))
138 (let ((w (get-edge-weight e gr
)))
139 (if w
(set-edge-weight e w g
))))
140 ($set_positions
($get_positions gr
) g
)
142 (let ((g (make-digraph)))
143 (dolist (v (digraph-vertices gr
))
145 (let ((l (get-vertex-label v gr
)))
146 (if l
(set-vertex-label v l g
))))
147 (dolist (e (digraph-edges gr
))
149 (let ((w (get-edge-weight e gr
)))
150 (if w
(set-edge-weight e w g
))))
151 ($set_positions
($get_positions gr
) g
)
154 (defmfun $new_graph
()
157 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
159 ;;; vertex operations
161 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
163 (defmfun $vertices
(gr)
164 (require-graph-or-digraph 'vertices
1 gr
)
165 (let ((vrt (vertices gr
)))
166 `((mlist simp
) ,@(copy-list vrt
))))
169 (if (graph-p gr
) (graph-vertices gr
) (digraph-vertices gr
)))
171 (defun require-vertex (m i v
)
173 ($error
"Argument" i
"to" m
"is not a valid vertex.")))
175 (defun is-vertex-in-graph (i gr
)
176 (not (equal (gethash i
179 (digraph-out-neighbors gr
))
183 (defun require-vertex-in-graph (m i gr
)
184 (unless (is-vertex-in-graph i gr
)
185 ($error m
": vertex not in graph.")))
187 (defmfun $is_vertex_in_graph
(i gr
)
188 (require-vertex 'vertex_in_graph
1 i
)
189 (require-graph-or-digraph 'vertex_in_graph
2 gr
)
190 (is-vertex-in-graph i gr
))
192 (defmfun $add_vertex
(i &optional gr
)
195 (setq i
(1+ (apply #'max
(vertices gr
)))))
196 (require-vertex 'add_vertex
1 i
)
197 (require-graph-or-digraph 'add_vertex
2 gr
)
198 (when (is-vertex-in-graph i gr
)
199 ($error
"add_vertex: vertex is already in the graph!"))
203 (defmfun $add_vertices
(vl gr
)
204 (require-graph-or-digraph 'add_vertices
2 gr
)
205 (unless (or (integerp vl
) ($listp vl
))
206 ($error
"Argument 1 to add_vertices is not a list."))
213 (setf vl
(cons ($add_vertex gr
) vl
)))
214 (setf vl
(cons '(mlist simp
) (reverse vl
)))))
217 (defun add-vertex (i gr
)
220 (incf (graph-order gr
))
221 (push i
(graph-vertices gr
))
222 (setf (graph-vertex-positions gr
) nil
)
223 (setf (gethash i
(graph-neighbors gr
)) ()))
225 (incf (digraph-order gr
))
226 (push i
(digraph-vertices gr
))
227 (setf (digraph-vertex-positions gr
) nil
)
228 (setf (gethash i
(digraph-in-neighbors gr
)) ())
229 (setf (gethash i
(digraph-out-neighbors gr
)) ())) ))
231 (defun neighbors (i gr
)
232 (gethash i
(if (graph-p gr
)
234 (digraph-out-neighbors gr
))) )
236 (defun in-neighbors (i gr
)
237 (gethash i
(digraph-in-neighbors gr
)))
239 (defun out-neighbors (i gr
)
240 (gethash i
(digraph-out-neighbors gr
)))
242 (defmfun $neighbors
(i gr
)
243 (require-vertex 'neighbors
1 i
)
244 (require-graph 'neighbors
2 gr
)
245 (require-vertex-in-graph 'neighbors i gr
)
246 `((mlist simp
) ,@(copy-list (neighbors i gr
))))
248 (defmfun $out_neighbors
(i gr
)
249 (require-vertex 'out_neighbors
1 i
)
250 (require-digraph 'out_neighbors
2 gr
)
251 (require-vertex-in-graph 'out_neighbors i gr
)
252 `((mlist simp
) ,@(copy-list (out-neighbors i gr
))))
254 (defmfun $in_neighbors
(i gr
)
255 (require-vertex 'in_neighbors
1 i
)
256 (require-digraph 'in_neighbors
2 gr
)
257 (require-vertex-in-graph 'in_neighbors i gr
)
258 `((mlist simp
) ,@(copy-list (in-neighbors i gr
))))
260 (defmfun $degree_sequence
(gr)
261 (require-graph 'degree_sequence
1 gr
)
263 (dolist (v (graph-vertices gr
))
264 (push (length (neighbors v gr
)) s
))
265 (setq s
(sort s
#'<))
266 `((mlist simp
) ,@s
)))
268 (defmfun $remove_vertex
(v gr
)
269 (require-vertex 'remove_vertex
1 v
)
270 (require-graph-or-digraph 'remove_vertex
2 gr
)
271 (require-vertex-in-graph 'remove_vertex v gr
)
272 (clear-vertex-label v gr
)
273 (remove-vertex v gr
))
275 (defmfun $remove_vertices
(vl gr
)
276 (require-graph-or-digraph 'remove_vertices
2 gr
)
277 (when (not ($listp vl
))
278 ($error
"Argument 1 to remove_vertices is not a list."))
280 ($remove_vertex v gr
))
283 (defun remove-vertex (v gr
)
286 (dolist (u (neighbors v gr
))
287 (let ((e (list (min u v
) (max u v
))))
289 (clear-vertex-label v gr
)
290 (when (graph-vertex-positions gr
)
291 (setf (graph-vertex-positions gr
)
292 (cons '(mlist simp
) (remove-if (lambda (x) (= (cadr x
) v
))
293 (cdr (graph-vertex-positions gr
))))))
294 (setf (graph-vertices gr
) (remove v
(graph-vertices gr
) :count
1))
295 (remhash v
(graph-neighbors gr
))
296 (decf (graph-order gr
)))
298 (dolist (u (out-neighbors v gr
))
299 (remove-edge (list v u
) gr
))
300 (dolist (u (in-neighbors v gr
))
301 (remove-edge (list u v
) gr
))
302 (clear-vertex-label v gr
)
303 (when (digraph-vertex-positions gr
)
304 (setf (digraph-vertex-positions gr
)
305 (cons '(mlist simp
) (remove-if (lambda (x) (= (cadr x
) v
))
306 (cdr (digraph-vertex-positions gr
))))))
307 (setf (digraph-vertices gr
) (remove v
(digraph-vertices gr
) :count
1))
308 (remhash v
(digraph-in-neighbors gr
))
309 (remhash v
(digraph-out-neighbors gr
))
310 (decf (digraph-order gr
))))
313 (defmfun $first_vertex
(gr)
314 (require-graph-or-digraph 'first_vertex
1 gr
)
316 ((= 0 (if (graph-p gr
) (graph-order gr
) (digraph-order gr
)))
317 ($error
"first_vertex: no first vertex in an empty graph."))
318 (t (first (vertices gr
)))))
320 (defmfun $max_degree
(gr)
321 (require-graph 'max_degree
1 gr
)
323 ((= 0 (graph-order gr
))
324 ($error
"max_degree: no max degree in an empty graph."))
326 (let* ((v (first (graph-vertices gr
))) (d (length (neighbors v gr
))))
327 (dolist (u (graph-vertices gr
))
328 (when (> (length (neighbors u gr
)) d
)
329 (setq d
(length (neighbors u gr
)))
331 `((mlist simp
) ,d
,v
)))))
333 (defmfun $min_degree
(gr)
334 (require-graph 'min_degree
1 gr
)
336 ((= 0 (graph-order gr
))
337 ($error
"min_degree: no min degree in an empty graph."))
339 (let* ((v (first (graph-vertices gr
))) (d (length (neighbors v gr
))))
340 (dolist (u (graph-vertices gr
))
341 (when (< (length (neighbors u gr
)) d
)
342 (setq d
(length (neighbors u gr
)))
344 `((mlist simp
) ,d
,v
)))))
346 (defmfun $average_degree
(gr)
347 (require-graph 'average_degee
1 gr
)
348 (m* 2 (m// (graph-size gr
) (graph-order gr
))))
350 (defmfun $vertex_degree
(v gr
)
351 (require-vertex 'vertex_degree
1 v
)
352 (require-graph 'vertex_degree
2 gr
)
353 (require-vertex-in-graph 'vertex_degree v gr
)
354 (length (neighbors v gr
)))
356 (defmfun $vertex_in_degree
(v gr
)
357 (require-vertex 'vertex_in_degree
1 v
)
358 (require-digraph 'vertex_in_degree
2 gr
)
359 (require-vertex-in-graph 'vertex_in_degree v gr
)
360 (length (in-neighbors v gr
)))
362 (defmfun $vertex_out_degree
(v gr
)
363 (require-vertex 'vertex_out_degree
1 v
)
364 (require-digraph 'vertex_out_degree
2 gr
)
365 (require-vertex-in-graph 'vertex_out_degree v gr
)
366 (length (out-neighbors v gr
)))
368 (defmfun $get_vertex_label
(v gr
&optional default
)
369 (require-vertex 'get_vertex_label
1 v
)
370 (require-graph-or-digraph 'get_vertex_label
2 gr
)
371 (require-vertex-in-graph 'vertex_label v gr
)
372 (or (get-vertex-label v gr
) default
))
374 (defun get-vertex-label (v gr
)
375 (gethash v
(if (graph-p gr
)
376 (graph-vertex-labels gr
)
377 (digraph-vertex-labels gr
))))
379 (defmfun $get_unique_vertex_by_label
(l gr
)
380 (unless (stringp l
) (merror (intl:gettext
"get_unique_vertex_by_label: first argument must be a string; found ~M") l
))
381 (require-graph-or-digraph 'get_unique_vertex_by_label
2 gr
)
382 (get-unique-vertex-by-label l gr
))
384 (defun get-unique-vertex-by-label (l gr
)
385 (let ((vv (get-all-vertices-by-label l gr
)))
388 ((= (length vv
) 1) (first vv
))
389 (t (merror (intl:gettext
"get_unique_vertex_by_label: two or more vertices have the same label ~:M") l
)))))
391 (defun get-all-vertices-by-label (l gr
)
393 (maphash (lambda (v l1
) (when (string= l1 l
) (push v vv
)))
394 (if (graph-p gr
) (graph-vertex-labels gr
) (digraph-vertex-labels gr
)))
397 (defmfun $get_all_vertices_by_label
(l gr
)
398 (unless (stringp l
) (merror (intl:gettext
"get_all_vertices_by_label: first argument must be a string; found ~M") l
))
399 (require-graph-or-digraph 'get_all_vertices_by_label
2 gr
)
400 (cons '(mlist) (get-all-vertices-by-label l gr
)))
402 (defmfun $clear_vertex_label
(v gr
)
403 (require-vertex 'clear_vertex_label
1 v
)
404 (require-graph-or-digraph 'clear_vertex_label
2 gr
)
405 (require-vertex-in-graph 'clear_label v gr
)
406 (clear-vertex-label v gr
))
408 (defun clear-vertex-label (v gr
)
409 (remhash v
(if (graph-p gr
)
410 (graph-vertex-labels gr
)
411 (digraph-vertex-labels gr
)))
414 (defmfun $set_vertex_label
(v l gr
)
415 (require-vertex 'set_vertex_label
1 v
)
416 (require-graph-or-digraph 'set_vertex_label
3 gr
)
417 (require-vertex-in-graph 'set_label v gr
)
418 (set-vertex-label v l gr
))
420 (defun set-vertex-label (v l gr
)
421 (setf (gethash v
(if (graph-p gr
)
422 (graph-vertex-labels gr
)
423 (digraph-vertex-labels gr
)))
427 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
431 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
433 (defun require-medge (m ar e
)
435 ((not (and ($listp e
) (eql 2 ($length e
))))
436 ($error
"Argument" ar
"to" m
"is not an edge (0)."))
437 (t (let ((u ($first e
)) (v ($second e
)))
438 (unless (and (integerp u
) (integerp v
))
439 ($error
"Argument" ar
"to" m
"is not an edge (1)."))
441 ($error
"Argument" ar
"to" m
"is not an edge (2)."))))))
443 (defun require-edge-in-graph (m e gr
)
444 (unless (is-edge-in-graph e gr
)
445 ($error m
": edge not in graph.")))
447 (defun m-edge-to-l-edge (e)
449 (list (apply #'min uv
) (apply #'max uv
))))
451 (defun m-edge-to-l-dedge (e)
453 (list (first uv
) (second uv
))))
455 (defun l-edge-to-m-edge (e)
458 (defmfun $is_edge_in_graph
(e gr
)
459 (require-medge 'is_edge_in_graph
1 e
)
460 (require-graph-or-digraph 'is_edge_in_graph
2 gr
)
462 (is-edge-in-graph (m-edge-to-l-edge e
) gr
)
463 (is-edge-in-graph (m-edge-to-l-dedge e
) gr
)))
465 (defun is-edge-in-graph (e gr
)
467 (not (null (member (second e
) (neighbors (first e
) gr
))))
468 (not (null (member (second e
) (out-neighbors (first e
) gr
)))) ))
470 (defmfun $add_edge
(e gr
)
471 (require-medge 'add_edge
1 e
)
472 (require-graph-or-digraph 'add_edge
2 gr
)
473 (let* ((e1 (if (graph-p gr
)
475 (m-edge-to-l-dedge e
)))
476 (u (first e1
)) (v (second e1
)))
478 ((not (and (is-vertex-in-graph u gr
) (is-vertex-in-graph v gr
)))
479 ($error
"add_edge: end vertices are not in graph!"))
481 ($error
"add_edge: end vertices are equal!"))
482 ((is-edge-in-graph e1 gr
)
483 ($error
"add_edge: edge already in graph!")))
486 (defmfun $add_edges
(el gr
)
487 (require-graph-or-digraph 'add_edges
2 gr
)
488 (if (not ($listp el
))
489 ($error
"Argument 1 to add_edges is not a list!")
491 (require-medge 'add_edges
1 e
)
495 (defun add-edge (e gr
)
496 (let ((u (first e
)) (v (second e
)))
499 (push v
(gethash u
(graph-neighbors gr
)))
500 (push u
(gethash v
(graph-neighbors gr
)))
501 (push e
(graph-edges gr
))
502 (incf (graph-size gr
)))
504 (push v
(gethash u
(digraph-out-neighbors gr
)))
505 (push u
(gethash v
(digraph-in-neighbors gr
)))
506 (push e
(digraph-edges gr
))
507 (incf (digraph-size gr
))))
510 (defun add-edges (elist gr
)
515 (require-graph-or-digraph 'edges
1 gr
)
516 (let ((e (mapcar #'(lambda (u) `((mlist simp
) ,@(copy-list u
)))
518 `((mlist simp
) ,@e
)))
525 (defmfun $remove_edge
(e gr
)
526 (require-medge 'remove_edge
1 e
)
527 (require-graph-or-digraph 'remove_edge
2 gr
)
528 (unless ($is_edge_in_graph e gr
)
529 ($error
"remove_edge: edge" e
"is not in graph."))
530 (remove-edge (if (graph-p gr
)
532 (m-edge-to-l-dedge e
))
535 (defmfun $remove_edges
(el gr
)
536 (require-graph-or-digraph 'remove_edges
2 gr
)
538 ($error
"Argument 1 to remove_edges is not a list."))
543 (defun remove-edge (e gr
)
544 (let ((u (first e
)) (v (second e
)))
547 (setf (gethash u
(graph-neighbors gr
))
548 (remove v
(gethash u
(graph-neighbors gr
)) :count
1))
549 (setf (gethash v
(graph-neighbors gr
))
550 (remove u
(gethash v
(graph-neighbors gr
)) :count
1))
551 (clear-edge-weight e gr
)
552 (decf (graph-size gr
))
553 (setf (graph-edges gr
)
554 (remove `(,u
,v
) (graph-edges gr
) :test
#'equal
:count
1)))
556 (setf (gethash u
(digraph-out-neighbors gr
))
557 (remove v
(gethash u
(digraph-out-neighbors gr
)) :count
1))
558 (setf (gethash v
(digraph-in-neighbors gr
))
559 (remove u
(gethash v
(digraph-in-neighbors gr
)) :count
1))
560 (clear-edge-weight e gr
)
561 (decf (digraph-size gr
))
562 (setf (digraph-edges gr
)
563 (remove `(,u
,v
) (digraph-edges gr
) :test
#'equal
:count
1))))
566 (defmfun $contract_edge
(e gr
)
567 (require-medge 'contract_edge
1 e
)
568 (require-graph 'contract_edge
2 gr
)
569 (let* ((e1 (m-edge-to-l-edge e
)) (u (first e1
)) (v (second e1
)))
570 (dolist (x (neighbors v gr
))
572 (let ((e2 (list (min x u
) (max x u
))))
573 (unless (is-edge-in-graph e2 gr
)
575 (remove-vertex v gr
))
578 (defmfun $contract_edges
(el gr
)
579 (require-graph-or-digraph 'contract_edges
2 gr
)
581 ($error
"Argument 1 to contract_edges is not a list."))
583 ($contract_edge e gr
))
586 (defmfun $get_edge_weight
(e gr
&optional default not-present
)
587 (require-medge 'get_edge_weight
1 e
)
588 (require-graph-or-digraph 'get_edge_weight
2 gr
)
589 (unless ($is_edge_in_graph e gr
)
590 (if (null not-present
)
591 ($error
"get_edge_weight: edge not in graph")
592 (return-from $get_edge_weight not-present
)))
593 (let ((w (if (graph-p gr
)
594 (get-edge-weight (m-edge-to-l-edge e
) gr
)
595 (get-edge-weight (m-edge-to-l-dedge e
) gr
))))
598 (defun get-edge-weight (e gr
)
601 (graph-edge-weights gr
)
602 (digraph-edge-weights gr
))))
603 (gethash e edge-weights
)))
605 (defmfun $clear_edge_weight
(e gr
)
606 (require-medge 'clear_edge_weight
1 e
)
607 (require-graph-or-digraph 'clear_edge_weight
2 gr
)
608 (unless ($is_edge_in_graph e gr
)
609 ($error
"clear_edge_weight: edge not in graph"))
611 (clear-edge-weight (m-edge-to-l-edge e
) gr
)
612 (clear-edge-weight (m-edge-to-l-dedge e
) gr
)))
614 (defun clear-edge-weight (e gr
)
618 (graph-edge-weights gr
)
619 (digraph-edge-weights gr
))))
620 (remhash e edge-weights
)
623 (defmfun $set_edge_weight
(e w gr
)
624 (require-medge 'set_edge_weight
1 e
)
625 (require-graph-or-digraph 'set_edge_weight
3 gr
)
626 (unless ($is_edge_in_graph e gr
)
627 ($error
"set_edge_weight: edge not in graph"))
629 (set-edge-weight (m-edge-to-l-edge e
) w gr
)
630 (set-edge-weight (m-edge-to-l-dedge e
) w gr
)))
632 (defun set-edge-weight (e w gr
)
636 (graph-edge-weights gr
)
637 (digraph-edge-weights gr
))))
638 (setf (gethash e edge-weights
) w
)
641 (defmfun $connect_vertices
(sources sinks gr
)
642 (require-graph 'connect_vertices
3 gr
)
644 (setq sources
(cdr sources
))
645 (setq sources
`(,sources
)))
647 (setq sinks
(cdr sinks
))
648 (setq sinks
`(,sinks
)))
651 ($add_edge
`((mlist simp
) ,u
,v
) gr
)))
654 (defmfun $subdivide_edge
(e gr
)
655 (require-graph 'subdivide_edge
2 gr
)
656 (require-edge-in-graph 'subdivide_edge
(m-edge-to-l-edge e
) gr
)
657 (let ((new-vertex (1+ (apply #'max
(vertices gr
))))
660 ($remove_edge
(cons '(mlist simp
) (list x y
)) gr
)
661 ($add_vertex new-vertex gr
)
662 ($add_edge
(cons '(mlist simp
) (list x new-vertex
)) gr
)
663 ($add_edge
(cons '(mlist simp
) (list y new-vertex
)) gr
))
666 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
668 ;; implementation of a set using hash tables
670 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
673 (content (make-hash-table)))
675 (defun new-set (&rest initial-content
)
676 (let ((set (make-ht-set)))
677 (dolist (obj initial-content
)
681 (defun set-member (obj set
)
682 (gethash obj
(ht-set-content set
)))
684 (defun set-add (obj set
)
685 (setf (gethash obj
(ht-set-content set
)) t
))
687 (defun set-remove (obj set
)
688 (remhash obj
(ht-set-content set
)))
690 (defun set-emptyp (set)
691 (= 0 (hash-table-count (ht-set-content set
))))
693 (defun set-elements (set)
695 (maphash #'(lambda (key val
)
696 (declare (ignore val
))
698 (ht-set-content set
))
702 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
704 ;;; graph definitions
706 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
708 (defmfun $empty_graph
(n)
709 (let ((gr (make-graph)))
714 (defmfun $empty_digraph
(n)
715 (let ((gr (make-digraph)))
720 (defmfun $create_graph
(v_list e_list
&optional dir
)
721 (let ((directed nil
))
722 ;; check if the graph is a directed graph
724 (when dir
(setq directed t
)))
725 ((and (eq (caar dir
) 'mequal
)
726 (eq (cadr dir
) '$directed
)
729 (unless (or (integerp v_list
) ($listp v_list
))
730 ($error
"Argument 1 to create_graph is not a list."))
731 (unless ($listp e_list
)
732 ($error
"Argument 2 to create_graph is not a list."))
733 (let ((gr (if directed
(make-digraph) (make-graph))))
734 (if (integerp v_list
)
737 (dolist (v (reverse (cdr v_list
)))
740 ($add_vertex
($first v
) gr
)
741 ($set_vertex_label
($first v
) ($second v
) gr
))
742 ($add_vertex v gr
))))
743 (dolist (e (cdr e_list
))
744 (if ($listp
($first e
))
746 ($add_edge
($first e
) gr
)
747 ($set_edge_weight
($first e
) ($second e
) gr
))
751 (defmfun $cycle_graph
(n)
752 (let ((g ($empty_graph n
)) pos
)
754 (add-edge (list i
(1+ i
)) g
))
755 (add-edge (list 0 (1- n
)) g
)
757 (setq pos
(cons `((mlist simp
) ,i
758 ((mlist simp
) ,($cos
(* i
2 pi
(/ n
))) ,($sin
(* i
2 pi
(/ n
)))))
760 ($set_positions
(cons '(mlist simp
) pos
) g
)
763 (defmfun $cycle_digraph
(n)
764 (let ((g ($empty_digraph n
)))
766 (add-edge (list i
(1+ i
)) g
))
767 (add-edge (list (1- n
) 0) g
)
770 (defmfun $path_graph
(n)
771 (let ((g ($empty_graph n
)) pos
)
773 (add-edge (list i
(1+ i
)) g
))
775 (setq pos
(cons `((mlist simp
) ,i
778 ($set_positions
(cons '(mlist simp
) pos
) g
)
781 (defmfun $path_digraph
(n)
782 (let ((g ($empty_digraph n
)))
784 (add-edge (list i
(1+ i
)) g
))
787 (defmfun $petersen_graph
(&optional n d
)
790 (unless (and (integerp n
) (integerp d
))
791 ($error
"Arguments to petersen_graph are not integers!")))
792 (let ((g ($empty_graph
(* 2 n
)))
795 (add-edge `(,i
,(+ n i
)) g
)
796 (when (or (/= n
(* 2 d
))
798 (let* ((u (+ i n
)) (v (+ (mod (+ i d
) n
) n
))
799 (e1 (min v u
)) (e2 (max v u
)))
800 (add-edge `(,e1
,e2
) g
)))
801 (let* ((u (mod (1+ i
) n
)) (e1 (min u i
)) (e2 (max u i
)))
802 (add-edge `(,e1
,e2
) g
)))
804 (push `((mlist simp
) ,i
((mlist simp
)
805 ,($sin
(/ (* 2 i pi
) n
))
806 ,($cos
(/ (* 2 i pi
) n
))))
808 (push `((mlist simp
) ,(+ n i
) ((mlist simp
)
809 ,(* 0.66 ($sin
(/ (* 2 i pi
) n
)))
810 ,(* 0.66 ($cos
(/ (* 2 i pi
) n
)))))
812 (setf (graph-vertex-positions g
) (cons '(mlist simp
) positions
))
815 (defmfun $complement_graph
(gr)
816 (require-graph 'complement_graph
1 gr
)
824 (when (and (< u v
) (not (is-edge-in-graph `(,u
,v
) gr
)))
825 (add-edge `(,u
,v
) co
))))
826 (setf (graph-vertex-positions co
) (graph-vertex-positions gr
))
829 (defmfun $complete_graph
(n)
830 (if (not (and (integerp n
) (>= n
0)))
831 ($error
"Argument 1 to complete_graph is not a positive integer"))
832 (let ((g ($empty_graph n
))
838 (add-edge `(,i
,j
) g
)))
840 (push `((mlist simp
) ,i
((mlist simp
)
841 ,($cos
(/ (* 2 i pi
) n
))
842 ,($sin
(/ (* 2 i pi
) n
))))
844 (setf (graph-vertex-positions g
) (cons '(mlist simp
) pos
))
847 (defmfun $from_adjacency_matrix
(m)
848 (if (not ($matrixp m
))
849 ($error
"Argument 1 to from_adjacency_matrix is not a matrix"))
850 (if (not (= ($length m
) ($length
($first m
))))
851 ($error
"Argument 1 to from_adjacency_matrix is not a square matrix"))
852 (let* ((n ($length m
)) (g ($empty_graph n
)))
854 (do ((j (1+ i
) (1+ j
)))
856 (if (not (= 0 (nth (1+ i
) (nth (1+ j
) m
))))
857 (add-edge `(,i
,j
) g
))))
860 (defmfun $graph_union
(&rest gr-list
)
862 ((= 0 (length gr-list
))
864 ((= 1 (length gr-list
))
866 ((= 2 (length gr-list
))
867 (graph-union (first gr-list
) (second gr-list
)))
869 (graph-union (first gr-list
) (apply #'$graph_union
(rest gr-list
))))))
871 (defun graph-union (g1 g2
)
872 (require-graph 'graph_union
1 g1
)
873 (require-graph 'graph_union
2 g2
)
874 (let ((g (make-graph)) (n (1+ (apply #'max
(graph-vertices g1
)))))
875 (dolist (v (graph-vertices g1
))
877 (dolist (e (graph-edges g1
))
879 (dolist (v (graph-vertices g2
))
880 (add-vertex (+ n v
) g
))
881 (dolist (e (graph-edges g2
))
882 (add-edge (list (+ n
(first e
)) (+ n
(second e
))) g
))
885 (defmfun $graph_join
(g1 g2
)
886 (require-graph 'graph_join
1 g1
)
887 (require-graph 'graph_join
2 g2
)
888 (let ((g (make-graph)) (n (1+ (apply #'max
(graph-vertices g1
)))))
889 (dolist (v (graph-vertices g1
))
891 (dolist (e (graph-edges g1
))
893 (dolist (v (graph-vertices g2
))
894 (add-vertex (+ n v
) g
))
895 (dolist (e (graph-edges g2
))
896 (add-edge (list (+ n
(first e
)) (+ n
(second e
))) g
))
897 (dolist (v (graph-vertices g1
))
898 (dolist (u (graph-vertices g2
))
899 (add-edge (list v
(+ n u
)) g
)))
902 (defun get-canonical-names (l)
903 (let ((names ()) (i 0))
905 (push `(,v .
,i
) names
)
909 (defmfun $graph_product
(&rest gr-list
)
911 ((= 0 (length gr-list
))
913 ((= 1 (length gr-list
))
915 ((= 2 (length gr-list
))
916 (graph-product (first gr-list
) (second gr-list
)))
918 (graph-product (first gr-list
) (apply #'$graph_product
(rest gr-list
))))))
920 (defun graph-product (g1 g2
)
921 (require-graph 'graph_product
1 g1
)
922 (require-graph 'graph_product
2 g2
)
924 ((names1 (get-canonical-names (graph-vertices g1
)))
925 (names2 (get-canonical-names (graph-vertices g2
)))
926 (size1 (graph-order g1
))
927 (size2 (graph-order g2
))
928 (size (* size1 size2
))
929 (g ($empty_graph size
)))
930 (dolist (e (graph-edges g1
))
931 (dolist (v (graph-vertices g2
))
933 ((v1 (cdr (assoc (first e
) names1
)))
934 (v2 (cdr (assoc (second e
) names1
)))
935 (u (cdr (assoc v names2
)))
936 (f (list (+ (* u size1
) v1
) (+ (* u size1
) v2
)))
937 (f (list (apply #'min f
) (apply #'max f
))))
939 (dolist (e (graph-edges g2
))
940 (dolist (v (graph-vertices g1
))
942 ((v1 (cdr (assoc (first e
) names2
)))
943 (v2 (cdr (assoc (second e
) names2
)))
944 (u (cdr (assoc v names1
)))
945 (f (list (+ (* v1 size1
) u
) (+ (* v2 size1
) u
)))
946 (f (list (apply #'min f
) (apply #'max f
))))
950 (defmfun $line_graph
(gr)
951 (require-graph 'line_graph
1 gr
)
953 (get-canonical-names (graph-edges gr
))) (n (graph-size gr
))
954 (g ($empty_graph n
)))
956 (do ((j (1+ i
) (1+ j
)))
958 (let ((e (car (rassoc i edge-list
))) (f (car (rassoc j edge-list
))))
960 (or (member (first e
) f
) (member (second e
) f
))
961 (add-edge `(,i
,j
) g
)))))
964 (defmfun $random_graph
(n p
)
965 (if (not (integerp n
))
966 ($error
"Argument 1 to random_graph is not an integer"))
967 (if (not (floatp ($float p
)))
968 ($error
"Argument 2 to random_graph is not a float"))
969 (let ((g ($empty_graph n
))
972 (do ((j (1+ i
) (1+ j
)))
974 (if (< (random 1.0) p
)
975 (add-edge `(,i
,j
) g
))))
978 (defmfun $random_graph1
(n m
)
979 #+sbcl
(declare (notinline $random_graph1
))
981 ($error
"Argument 1 to random_graph is not an integer"))
983 ($error
"Argument 2 to random_graph is not an integer"))
984 (when (< (* n
(1- n
)) (* 2 m
))
985 ($error
"random_graph1: no such graph"))
986 (when (< (* n
(1- n
)) (* 4 m
))
987 (return-from $random_graph1
988 ($complement_graph
($random_graph1 n
(- (/ (* n
(1- n
)) 2) m
)))))
989 (let ((g ($empty_graph n
)))
990 (do ((i 0)) ((= i m
))
991 (let ((u (random n
)) (v (random n
)))
993 (let ((e (list (min u v
) (max u v
))))
994 (unless (is-edge-in-graph e g
)
999 (defmfun $random_bipartite_graph
(a b p
)
1000 (unless (integerp a
)
1001 ($error
"Argument 1 to random graph is not an integer"))
1002 (unless (integerp b
)
1003 ($error
"Argument b to random graph is not an integer"))
1004 (let ((g ($empty_graph
(+ a b
))))
1007 (when (< (random 1.0) p
)
1008 (add-edge (list x
(+ a y
)) g
))))
1011 (defmfun $random_digraph
(n p
)
1012 (unless (integerp n
)
1013 ($error
"Argument 1 to random_digraph is not an integer"))
1014 (unless (floatp ($float p
))
1015 ($error
"Argument 2 to random_digraph is not a float"))
1016 (let ((g ($empty_digraph n
))
1020 (when (and (not (= i j
)) (< (random 1.0) p
))
1021 (add-edge `(,i
,j
) g
))))
1024 (defmfun $random_tournament
(n)
1025 (unless (and (integerp n
) (>= n
0))
1026 ($error
"Argument 1 to random_tournament is not a positive integer"))
1027 (let ((g ($empty_digraph n
)))
1029 (do ((j (1+ i
) (1+ j
)))
1031 (if (and (not (= i j
)) (< (random 1.0) 0.5))
1032 (add-edge `(,i
,j
) g
)
1033 (add-edge `(,j
,i
) g
))))
1036 (defmfun $random_tree
(n)
1037 (unless (and (integerp n
) (>= n
0))
1038 ($error
"Argument 1 to random_tree is not a positive integer"))
1040 ((tr ($empty_graph n
))
1041 (vrt (remove 0 (graph-vertices tr
) :count
1))
1045 ((u (nth (random (length vrt
)) vrt
))
1046 (v (nth (random (length tree-vrt
)) tree-vrt
)))
1047 (setq vrt
(remove u vrt
:count
1))
1049 (add-edge (list (min u v
) (max u v
)) tr
)))
1052 (defmfun $underlying_graph
(gr)
1053 (require-digraph 'underlying_graph
1 gr
)
1054 (let ((g (make-graph)))
1055 (dolist (v (vertices gr
))
1057 (dolist (e (digraph-edges gr
))
1058 (let ((u (first e
)) (v (second e
)))
1059 (let ((e1 (list (apply #'min e
) (apply #'max e
))))
1060 (when (not (is-edge-in-graph e1 g
))
1061 (add-edge `(,u
,v
) g
)))))
1064 (defmfun $induced_subgraph
(vl gr
)
1065 (require-graph 2 'induced_subgraph gr
)
1067 ($error
"First argument to induced_subgraph is not a list."))
1072 (when (not (is-vertex-in-graph v gr
))
1074 "induced_subgraph: second argument is not a list of vertices"))
1076 (let ((l (get-vertex-label v gr
)))
1078 (set-vertex-label v l g
))))
1079 (dolist (e (graph-edges gr
))
1080 (let ((u (first e
)) (v (second e
)))
1081 (when (and (member u v_l
) (member v v_l
))
1085 (defmfun $wheel_graph
(n)
1086 (unless (and (integerp n
) (>= n
3))
1087 ($error
"wheel_graph: first argument is no an integer greater than 3"))
1088 (let ((g ($cycle_graph n
))
1092 (add-edge `(,i
,n
) g
))
1094 (push `((mlist simp
) ,i
((mlist simp
)
1095 ,($sin
(/ (* 2 i pi
) n
))
1096 ,($cos
(/ (* 2 i pi
) n
))))
1098 (push `((mlist simp
) ,n
((mlist simp
) 0 0)) positions
)
1099 ($set_positions
(cons '(mlist simp
) positions
) g
)
1102 (defmfun $circulant_graph
(n l
)
1103 (unless (and (integerp n
) (> n
0))
1104 ($error
"Argument 1 to circulant_graph is not a positive integer."))
1106 ($error
"Argument 2 to circulant_graph is not a list."))
1107 (let ((g ($empty_graph n
))
1110 (unless (and (integerp d
) (> d
0))
1112 "Argument 2 to circulant graph is no a list of positive integers"))
1114 (let ((e `(,i
,(mod (+ i d
) n
))))
1115 (setq e
(list (apply #'min e
) (apply #'max e
)))
1118 (push `((mlist simp
) ,i
((mlist simp
)
1119 ,($sin
(m// (m* 2.0 i pi
) n
))
1120 ,($cos
(m// (m* 2.0 i pi
) n
))))
1122 ($set_positions
(cons '(mlist simp
) positions
) g
)
1125 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1127 ;;; graph properties
1129 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1131 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1133 ;;; Connected components
1136 (defmfun $connected_components
(gr)
1137 (require-graph 'connected_components
1 gr
)
1138 (when (= 0 (graph-order gr
))
1139 (return-from $connected_components
'((mlist simp
))))
1140 (let ((components ()) (visited (make-hash-table)))
1141 (loop for v in
(vertices gr
) do
1142 (unless (gethash v visited
)
1143 (let ((c ()) (active ()))
1145 (loop while active do
1146 (let ((x (pop active
)))
1148 (setf (gethash x visited
) t
)
1149 (dolist (u (neighbors x gr
))
1150 (unless (or (gethash u visited
) (member u active
))
1152 (push `((mlist simp
) ,@c
) components
))))
1153 `((mlist simp
) ,@components
)))
1155 (defmfun $is_connected
(gr)
1156 (require-graph 'is_connected
1 gr
)
1157 (<= ($length
($connected_components gr
)) 1))
1159 (defmfun $is_tree
(gr)
1160 (require-graph 'is_tree
1 gr
)
1161 (and ($is_connected gr
) (= (graph-order gr
) (1+ (graph-size gr
)))))
1163 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1165 ;;; Reachable vertices
1169 (defmfun $reachable_vertices
(v gr
)
1170 (require-graph-or-digraph 'reachable_vertices
2 gr
)
1171 (require-vertex 'reachable_vertices
1 v
)
1172 (require-vertex-in-graph 'reachable_vertices v gr
)
1173 (when (= 0 (if (graph-p gr
) (graph-order gr
) (digraph-order gr
)))
1174 (return-from $reachable_vertices
'((mlist simp
))))
1175 (let ((component ()) (visited (make-hash-table)))
1176 (unless (gethash v visited
)
1179 (loop while active do
1180 (let ((x (pop active
)))
1182 (setf (gethash x visited
) t
)
1183 (dolist (u (if (graph-p gr
) (neighbors x gr
) (out-neighbors x gr
)))
1184 (unless (or (gethash u visited
) (member u active
))
1185 (push u active
)))))))
1186 `((mlist simp
) ,@component
)))
1188 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1190 ;;; Adjacency matrix and Laplacian matrix
1193 (defmfun $adjacency_matrix
(gr)
1194 (require-graph-or-digraph 'adjacency_matrix
1 gr
)
1195 (let* ((n (if (graph-p gr
) (graph-order gr
) (digraph-order gr
)))
1196 (m ($zeromatrix n n
))
1197 (names (get-canonical-names (vertices gr
))))
1198 (dolist (e (edges gr
))
1199 (setf (nth (1+ (cdr (assoc (first e
) names
)))
1200 (nth (1+ (cdr (assoc (second e
) names
))) m
)) 1)
1202 (setf (nth (1+ (cdr (assoc (second e
) names
)))
1203 (nth (1+ (cdr (assoc (first e
) names
))) m
)) 1)))
1206 (defmfun $laplacian_matrix
(gr)
1207 (require-graph 'laplacian_matrix
1 gr
)
1208 (let ((m ($zeromatrix
(graph-order gr
) (graph-order gr
)))
1209 (names (get-canonical-names (vertices gr
))))
1210 (dolist (v (graph-vertices gr
))
1211 (setf (nth (1+ (cdr (assoc v names
)))
1212 (nth (1+ (cdr (assoc v names
))) m
))
1213 (length (neighbors v gr
))))
1214 (dolist (e (graph-edges gr
))
1215 (setf (nth (1+ (cdr (assoc (first e
) names
)))
1216 (nth (1+ (cdr (assoc (second e
) names
))) m
)) -
1)
1217 (setf (nth (1+ (cdr (assoc (second e
) names
)))
1218 (nth (1+ (cdr (assoc (first e
) names
))) m
)) -
1))
1221 (defmfun $graph_charpoly
(gr x
)
1222 (require-graph 'graph_charpoly
1 gr
)
1224 ($charpoly
($adjacency_matrix gr
) x
)))
1226 (defmfun $graph_eigenvalues
(gr)
1227 (require-graph 'graph_eigenvalues
1 gr
)
1229 (mfuncall '$eigenvalues
($adjacency_matrix gr
))))
1231 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1233 ;;; girth, odd_girth
1236 (defmfun $girth
(gr)
1237 (require-graph 'girth
1 gr
)
1240 (defmfun $odd_girth
(gr)
1241 (require-graph 'odd_girth
1 gr
)
1244 (defun girth (gr odd
)
1245 (let ((girth (1+ (graph-order gr
))))
1246 (dolist (v (graph-vertices gr
))
1248 ((visited (new-set v
))
1249 (active (new-set v
))
1253 ((or (set-emptyp active
)
1254 (> (* 2 depth
) girth
)
1256 (setq next
(new-set))
1257 (dolist (u (set-elements active
))
1258 (dolist (w (neighbors u gr
))
1259 (if (not (set-member w visited
))
1264 (if (set-member w active
)
1265 (setq girth
(- (* 2 depth
) 1)))
1266 (if (and (not odd
) (set-member w next
))
1267 (setq girth
(min girth
(* 2 depth
))))))))
1269 (setq depth
(1+ depth
)))))
1270 (if (> girth
(graph-order gr
))
1274 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1276 ;;; diameter, radius
1279 (defmfun $vertex_eccentricity
(v gr
)
1280 (require-graph 'vertex_eccentricity
1 gr
)
1281 (require-vertex-in-graph 'vertex_eccentricity v gr
)
1282 (let ((ecc (eccentricity (list v
) gr
)))
1285 (defun eccentricity (v_list gr
)
1286 (unless ($is_connected gr
)
1287 ($error
"eccentricity: graph is not connected."))
1288 (let ((ecc (make-hash-table)))
1291 ((visited (new-set v
))
1292 (active (new-set v
))
1296 ((set-emptyp active
))
1297 (setq next
(new-set))
1298 (dolist (u (set-elements active
))
1299 (dolist (w (neighbors u gr
))
1300 (when (not (set-member w visited
))
1304 (setq depth
(1+ depth
)))
1305 (setf (gethash v ecc
) depth
)))
1308 (defmfun $diameter
(gr)
1309 (require-graph 'diameter
1 gr
)
1310 (let ((ecc (eccentricity (vertices gr
) gr
))
1312 (maphash #'(lambda (key val
)
1313 (declare (ignore key
))
1314 (when (> val diameter
)
1315 (setq diameter val
)))
1319 (defmfun $radius
(gr)
1320 (require-graph 'radius
1 gr
)
1321 (let ((ecc (eccentricity (vertices gr
) gr
))
1322 (radius ($graph_order gr
)))
1323 (maphash #'(lambda (key val
)
1324 (declare (ignore key
))
1325 (when (< val radius
)
1330 (defmfun $graph_center
(gr)
1331 (require-graph 'graph_center
1 gr
)
1332 (let ((ecc (eccentricity (vertices gr
) gr
))
1334 (radius ($graph_order gr
)))
1335 (maphash #'(lambda (key val
)
1336 (declare (ignore key
))
1337 (when (< val radius
)
1340 (maphash #'(lambda (key val
)
1341 (when (= val radius
)
1344 `((mlist simp
) ,@per
)))
1346 (defmfun $graph_periphery
(gr)
1347 (require-graph 'graph_periphery
1 gr
)
1348 (let ((ecc (eccentricity (vertices gr
) gr
))
1351 (maphash #'(lambda (key val
)
1352 (declare (ignore key
))
1353 (when (> val diameter
)
1354 (setq diameter val
)))
1356 (maphash #'(lambda (key val
)
1357 (when (= val diameter
)
1360 `((mlist simp
) ,@center
)))
1362 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1367 (defmfun $bipartition
(gr)
1368 (require-graph 'bipartition
1 gr
)
1369 (when (= (graph-order gr
) 0)
1370 (return-from $bipartition
`((mlist simp
) ((mlist simp
)) ((mlist simp
)))))
1371 (let ((components (cdr ($connected_components gr
))) (A ()) (B ()))
1372 (dolist (c components
)
1373 (let ((partition (bi-partition (first (cdr c
)) gr
)))
1374 (if (null partition
)
1375 (return-from $bipartition
`((mlist simp
)))
1377 (setq A
(append A
(first partition
)))
1378 (setq B
(append B
(second partition
)))))))
1379 `((mlist simp
) ((mlist simp
) ,@A
) ((mlist simp
) ,@B
))))
1381 (defun bi-partition (v gr
)
1387 (colors (make-hash-table)))
1388 (setf (gethash v colors
) 1)
1393 (wc (gethash w colors
)))
1398 (dolist (u (neighbors w gr
))
1399 (if (set-member u visited
)
1400 (when (= (gethash u colors
) wc
)
1401 (return-from bi-partition
()))
1402 (unless (member u active
)
1404 (setf (gethash u colors
) (- 1 wc
)))))))
1407 (defmfun $is_bipartite
(gr)
1408 (require-graph 'is_bipartite
1 gr
)
1409 (> ($length
($bipartition gr
)) 1))
1411 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1416 (defmfun $biconnected_components
(gr)
1417 (require-graph 'biconnected_components
1 gr
)
1418 (if (= 0 (graph-order gr
))
1421 ((bicomp `((mlist simp
)))
1422 (comp (cdr ($connected_components gr
))))
1424 (if (= ($length c
) 1)
1425 (setq bicomp
($append bicomp
`((mlist simp
) ,c
)))
1426 (setq bicomp
($append bicomp
(bicomponents ($first c
) gr
)))))
1429 (defmfun $is_biconnected
(gr)
1430 (require-graph 'is_biconnected
1 gr
)
1431 (eql ($length
($biconnected_components gr
)) 1))
1433 (defvar *dfs-bicomp-depth
* 0)
1434 (defvar *dfs-bicomp-num
* ())
1435 (defvar *dfs-bicomp-low-pt
* ())
1436 (defvar *dfs-bicomp-edges
* ())
1437 (defvar *bicomponents
* ())
1439 (defun bicomponents (v gr
)
1441 (setq *dfs-bicomp-depth
* 0)
1442 (setq *dfs-bicomp-num
* (make-hash-table))
1443 (setq *dfs-bicomp-low-pt
* (make-hash-table))
1444 (setq *dfs-bicomp-edges
* (make-hash-table))
1445 (setq *bicomponents
* ())
1446 (dolist (v (graph-vertices gr
))
1447 (setf (gethash v
*dfs-bicomp-num
*) 0))
1448 (dfs-bicomponents gr v
)
1449 (dolist (c *bicomponents
*)
1450 (let ((curr-comp ()))
1452 (let ((u (first e
)) (v (second e
)))
1453 (unless (member u curr-comp
)
1455 (unless (member v curr-comp
)
1456 (push v curr-comp
))))
1457 (setq bicomp
(cons `((mlist simp
) ,@(sort curr-comp
#'<)) bicomp
))))
1458 `((mlist simp
) ,@bicomp
)))
1460 (defun dfs-bicomponents (gr w
)
1461 (setq *dfs-bicomp-depth
* (1+ *dfs-bicomp-depth
*))
1462 (setf (gethash w
*dfs-bicomp-num
*) *dfs-bicomp-depth
*)
1463 (setf (gethash w
*dfs-bicomp-low-pt
*) *dfs-bicomp-depth
*)
1464 (dolist (u (neighbors w gr
))
1465 (when (< (gethash u
*dfs-bicomp-num
*) (gethash w
*dfs-bicomp-num
*))
1466 (push `(,w
,u
) *dfs-bicomp-edges
*))
1467 (if (= 0 (gethash u
*dfs-bicomp-num
*))
1469 (dfs-bicomponents gr u
)
1470 (if (>= (gethash u
*dfs-bicomp-low-pt
*)
1471 (gethash w
*dfs-bicomp-num
*))
1472 (let ((e 0) (comp ()))
1474 ((equal e
`(,w
,u
)))
1475 (setq e
(pop *dfs-bicomp-edges
*))
1477 (push comp
*bicomponents
*))
1478 (setf (gethash w
*dfs-bicomp-low-pt
*)
1479 (min (gethash w
*dfs-bicomp-low-pt
*)
1480 (gethash u
*dfs-bicomp-low-pt
*)))))
1481 (setf (gethash w
*dfs-bicomp-low-pt
*)
1482 (min (gethash w
*dfs-bicomp-low-pt
*)
1483 (gethash u
*dfs-bicomp-num
*))))))
1485 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1487 ;;; strong connectivity
1490 (defvar *scon-low
* nil
)
1491 (defvar *scon-dfn
* nil
)
1492 (defvar *scon-comp
* nil
)
1493 (defvar *scon-st
* nil
)
1494 (defvar *scon-vrt
* nil
)
1495 (defvar *scon-depth
* 0)
1497 (defmfun $strong_components
(gr)
1498 (require-digraph 'strong_components
1 gr
)
1499 (if (= 0 (digraph-order gr
))
1502 (setq *scon-low
* (make-hash-table))
1503 (setq *scon-dfn
* (make-hash-table))
1504 (setq *scon-comp
* ())
1506 (setq *scon-vrt
* (digraph-vertices gr
))
1507 (loop while
(not (null *scon-vrt
*)) do
1508 (setq *scon-depth
* 0)
1509 (dfs-strong-components gr
(first *scon-vrt
*))
1510 (dolist (c *scon-comp
*)
1512 (setq *scon-comp
* ()))
1513 `((mlist simp
) ,@res
))))
1515 (defmfun $is_sconnected
(gr)
1516 (require-digraph 'strong_components
1 gr
)
1517 (eql ($length
($strong_components gr
)) 1))
1519 (defun dfs-strong-components (gr v
)
1521 (setf (gethash v
*scon-dfn
*) *scon-depth
*)
1522 (setf (gethash v
*scon-low
*) *scon-depth
*)
1523 (setf *scon-vrt
* (remove v
*scon-vrt
* :count
1))
1525 (dolist (u (neighbors v gr
))
1526 (if (gethash u
*scon-dfn
*)
1527 (when (and (< (gethash u
*scon-dfn
*) (gethash v
*scon-dfn
*))
1528 (member u
*scon-st
*))
1529 (setf (gethash v
*scon-low
*)
1530 (min (gethash v
*scon-low
*)
1531 (gethash u
*scon-dfn
*))))
1533 (dfs-strong-components gr u
)
1534 (setf (gethash v
*scon-low
*)
1535 (min (gethash v
*scon-low
*)
1536 (gethash u
*scon-low
*))))))
1537 (when (= (gethash v
*scon-low
*) (gethash v
*scon-dfn
*))
1538 (let ((x (pop *scon-st
*))
1540 (loop while
(not (= x v
)) do
1542 (setq x
(pop *scon-st
*)))
1544 (setq *scon-comp
* (cons `((mlist simp
) ,@comp
) *scon-comp
*)))))
1546 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1548 ;;; topological sorting
1551 (defmfun $topological_sort
(dag)
1552 (require-digraph 'topological_sort
1 dag
)
1553 (let ((in-degrees (make-hash-table))
1555 (n ($graph_size dag
))
1557 (dolist (v (vertices dag
))
1558 (setf (gethash v in-degrees
) 0))
1559 (dolist (e (edges dag
))
1560 (incf (gethash (second e
) in-degrees
)))
1561 (dolist (v (vertices dag
))
1562 (when (= (gethash v in-degrees
) 0)
1564 (loop while
(> (length q
) 0) do
1567 (dolist (u (out-neighbors v dag
))
1568 (decf (gethash u in-degrees
))
1570 (when (= (gethash u in-degrees
) 0)
1573 `((mlist simp
) ,@(reverse s
))
1576 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1578 ;;; max_flow (augmenting paths)
1581 (defmfun $max_flow
(net source sink
)
1582 (require-digraph 'max_flow
1 net
)
1583 (require-vertex 'max_flow
2 source
)
1584 (require-vertex 'max_flow
3 sink
)
1585 (require-vertex-in-graph 'max_flow source net
)
1586 (require-vertex-in-graph 'max_flow sink net
)
1588 ((d (make-hash-table)) (active ()) (lbls (make-hash-table))
1589 (flow (make-hash-table :test
#'equal
)) (val 0)
1591 (dolist (e (digraph-edges net
))
1592 (setf (gethash e flow
) 0))
1593 (dolist (v (digraph-vertices net
))
1594 (setf (gethash v d
) '$inf
))
1595 (setf (gethash source lbls
) `(,source -
1 $inf
))
1596 (push source active
)
1599 (let ((v (pop active
)))
1600 (dolist (w (out-neighbors v net
))
1601 (if (and (null (gethash w lbls
))
1602 (mlsp (gethash `(,v
,w
) flow
)
1603 (or (get-edge-weight `(,v
,w
) net
) 1)))
1607 (m- (or (get-edge-weight `(,v
,w
) net
) 1)
1608 (gethash `(,v
,w
) flow
))
1610 (setf (gethash w lbls
) `(,v
1 ,(gethash w d
)))
1612 (dolist (w (in-neighbors v net
))
1613 (if (and (null (gethash w lbls
))
1614 (mgrp (gethash `(,w
,v
) flow
) 0))
1616 (setf (gethash w d
) (mfuncall '$min
1617 (gethash `(,w
,v
) flow
)
1619 (setf (gethash w lbls
) `(,v -
1 ,(gethash w d
)))
1621 (if (gethash sink lbls
)
1622 (let ((dd (third (gethash sink lbls
))) (w sink
))
1623 (setq val
(m+ dd val
))
1626 (let ((v1 (first (gethash w lbls
)))
1627 (vl (second (gethash w lbls
))))
1629 (setf (gethash `(,v1
,w
) flow
)
1630 (m+ (gethash `(,v1
,w
) flow
) dd
))
1631 (setf (gethash `(,w
,v1
) flow
)
1632 (m- (gethash `(,w
,v1
) flow
) dd
)))
1634 (setq lbls
(make-hash-table))
1635 (setf (gethash source lbls
) `(,source -
1 $inf
))
1636 (dolist (v1 (digraph-vertices net
))
1637 (setf (gethash v1 d
) '$inf
))
1638 (setq active
`(,source
))))))
1639 (let ((max-flow ()))
1640 (dolist (e (digraph-edges net
))
1641 (push `((mlist simp
) ((mlist simp
) ,@e
)
1642 ,(gethash e flow
)) max-flow
))
1643 `((mlist simp
) ,val
((mlist simp
) ,@max-flow
)))))
1645 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1650 (defmfun $shortest_path
(u v g
)
1651 (require-graph-or-digraph 'shortest_path
3 g
)
1652 (require-vertex 'shortest_path
1 u
)
1653 (require-vertex 'shortest_path
2 v
)
1654 (require-vertex-in-graph 'shortest_path v g
)
1655 (require-vertex-in-graph 'shortest_path u g
)
1656 (let ((active (make-hash-table)) (visited (make-hash-table)) (previous (make-hash-table)))
1657 (setf (gethash u active
) t
)
1659 ((or (= 0 (hash-table-count active
)) (gethash v visited
)))
1660 (let ((next (make-hash-table)))
1661 (loop for w being the hash-keys of active do
1662 (setf (gethash w visited
) t
)
1663 (dolist (x (neighbors w g
))
1664 (unless (or (gethash x active
) (gethash x visited
) (gethash x next
))
1665 (setf (gethash x previous
) w
)
1666 (setf (gethash x next
) t
))))
1667 (setq active next
)))
1668 (if (gethash v visited
)
1669 (let ((path (list v
)))
1672 (setq x
(gethash x previous
))
1674 `((mlist simp
) ,@path
))
1677 (defmfun $vertex_distance
(u v g
)
1678 (require-graph-or-digraph 'shortest_path
3 g
)
1679 (require-vertex 'shortest_path
1 u
)
1680 (require-vertex 'shortest_path
2 v
)
1681 (require-vertex-in-graph 'shortest_path v g
)
1682 (require-vertex-in-graph 'shortest_path u g
)
1683 (let ((d ($length
($shortest_path u v g
))))
1688 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1690 ;;; minimum spanning tree
1693 (defun edge-weight-1 (e gr
)
1694 (cond ((gethash e
(graph-edge-weights gr
)))
1697 (defun graph-edges-with-weights (gr)
1698 (let ((edges (graph-edges gr
)) (edges-with-weights ()))
1700 (push `(,e
,(edge-weight-1 e gr
)) edges-with-weights
))
1701 edges-with-weights
))
1703 (defun edges-by-weights (gr)
1704 (let ((edges (graph-edges-with-weights gr
)))
1705 (sort edges
#'(lambda (u v
) (mlsp (second u
) (second v
))))))
1707 (defun in-same-part (u v p
)
1708 (let ((up u
) (vp v
))
1710 ((= up
(gethash up p
)))
1711 (let ((up1 (gethash up p
)))
1712 (setf (gethash up p
) (gethash up1 p
)))
1713 (setq up
(gethash up p
)))
1715 ((= vp
(gethash vp p
)))
1716 (let ((vp1 (gethash vp p
)))
1717 (setf (gethash vp p
) (gethash vp1 p
)))
1718 (setq vp
(gethash vp p
)))
1721 (defun join-parts (u v p
)
1722 (let ((up u
) (vp v
))
1724 ((= up
(gethash up p
)))
1725 (setq up
(gethash up p
)))
1727 ((= vp
(gethash vp p
)))
1728 (setq vp
(gethash vp p
)))
1729 (setf (gethash up p
) (gethash vp p
))))
1731 (defmfun $minimum_spanning_tree
(gr)
1732 (require-graph 'minimum_spanning_tree
1 gr
)
1733 (let ((edges (edges-by-weights gr
)) (tr (make-graph))
1734 (part (make-hash-table)))
1735 (dolist (v (graph-vertices gr
))
1737 (setf (gethash v part
) v
))
1739 (let ((u (caar e
)) (v (cadar e
)))
1740 (if (not (in-same-part u v part
))
1742 (add-edge `(,u
,v
) tr
)
1743 (join-parts u v part
)))))
1746 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1751 (defvar *hamilton-cycle
* ())
1753 (defmfun $hamilton_cycle
(gr)
1754 (require-graph 'hamilton_cycle
1 gr
)
1755 (let (*hamilton-cycle
* (*v0
* ($first_vertex gr
)))
1756 (declare (special *v0
*))
1757 (unless ($is_biconnected gr
)
1758 (return-from $hamilton_cycle
`((mlist simp
))))
1759 (hamilton-cycle (list *v0
*) gr
)
1760 `((mlist simp
) ,@(reverse *hamilton-cycle
*))))
1762 (defun hamilton-cycle (part gr
)
1763 (declare (special *v0
*))
1764 (unless *hamilton-cycle
*
1765 (if (= (length part
) (if (graph-p gr
)
1767 (digraph-order gr
)))
1768 (if (member (car (last part
)) (neighbors (first part
) gr
))
1769 (setq *hamilton-cycle
* (append (last part
) part
))))
1770 (dolist (v (neighbors (car part
) gr
))
1771 (when (null (member v part
))
1772 (if (< (length part
) 3)
1773 (hamilton-cycle (cons v part
) gr
)
1774 (let ((gr1 ($copy_graph gr
))
1775 (in-part (rest (reverse part
))))
1776 ($remove_vertices
(cons '(mlist simp
) in-part
) gr1
)
1777 (unless (member v
(neighbors *v0
* gr
))
1778 ($add_edge
`((mlist simp
) ,v
,*v0
*) gr1
))
1779 (when ($is_biconnected gr1
)
1780 (hamilton-cycle (cons v part
) gr
))))))))
1782 (defmfun $hamilton_path
(gr)
1783 (require-graph 'hamilton_path
1 gr
)
1784 ;; first check if there exists a HC
1785 (let ((hc ($hamilton_cycle gr
)))
1787 (return-from $hamilton_path
($rest hc
))))
1788 ;; check with all non-edges
1789 (let ((grc ($complement_graph gr
)))
1790 (dolist (v (vertices gr
))
1791 (dolist (u (neighbors v grc
))
1796 (declare (special *v0
*))
1797 (hamilton-cycle part gr
)
1798 (when *hamilton-cycle
*
1799 (return-from $hamilton_path
(cons '(mlist simp
) (rest (reverse *hamilton-cycle
*))))))))))
1802 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1807 (defvar *maximum-clique
* ())
1809 (defmfun $vertices_by_degree
(gr)
1810 (require-graph 'vertices_by_degrees
1 gr
)
1811 (cons '(mlist simp
) (vertices-by-degrees gr
)))
1813 (defun vertices-by-degrees (gr)
1815 (dolist (v (vertices gr
))
1816 (push `(,v
,(length (neighbors v gr
))) vrt
))
1817 (setq vrt
(sort vrt
#'(lambda (u v
) (> (second u
) (second v
)))))
1818 (mapcar #'first vrt
)))
1820 (defun greedy-color (gr)
1821 (let ((coloring (make-hash-table))
1822 (available-colors (make-hash-table)) (tmp ()))
1823 (dotimes (i (graph-order gr
))
1825 (setq tmp
(reverse tmp
))
1826 (dolist (v (graph-vertices gr
))
1827 (setf (gethash v available-colors
) (copy-tree tmp
)))
1828 (dolist (v (vertices-by-degrees gr
))
1829 (let ((c (car (gethash v available-colors
))))
1830 (setf (gethash v coloring
) c
)
1831 (dolist (u (neighbors v gr
))
1832 (setf (gethash u available-colors
)
1833 (remove c
(gethash u available-colors
) :count
1)))))
1836 (defmfun $max_clique
(gr)
1837 (require-graph 'max_clique
1 gr
)
1838 (setq *maximum-clique
* ())
1839 (let ((v) (coloring) (h ($copy_graph gr
)))
1840 (do () ((or (>= (length *maximum-clique
*) (graph-order h
))
1841 (> (length *maximum-clique
*) ($first
($max_degree h
)))))
1842 ; (print *maximum-clique*)
1843 ; (print ($max_degree h))
1844 (setq coloring
(greedy-color h
))
1845 (setq v
($second
($max_degree h
)))
1846 (extend-clique `(,v
) (neighbors v h
) coloring h
)
1847 (remove-vertex v h
)))
1848 `((mlist simp
) ,@(sort *maximum-clique
* #'<)))
1850 (defmfun $min_vertex_cover
(gr)
1851 (require-graph 'min_vertex_cover
1 gr
)
1852 (let ((bipart ($bipartition gr
)))
1853 (if (null (cdr bipart
))
1855 (mc (cdr ($max_clique
($complement_graph gr
)))))
1856 (loop for v in
(vertices gr
) do
1857 (unless (member v mc
)
1858 (setq vc
(cons v vc
))))
1859 `((mlist simp
) ,@vc
))
1860 (maximum-matching-bipartite gr
(cadr bipart
) (caddr bipart
) t
))))
1862 (defmfun $max_independent_set
(gr)
1863 (require-graph 'max_independent_set
1 gr
)
1864 (if ($is_bipartite gr
)
1866 (vc (cdr ($min_vertex_cover gr
))))
1867 (loop for v in
(vertices gr
) do
1868 (unless (member v vc
)
1869 (setq mis
(cons v mis
))))
1870 `((mlist simp
) ,@mis
))
1871 ($max_clique
($complement_graph gr
))))
1873 (defun extend-clique (clique neigh coloring gr
)
1874 (if (= (length neigh
) 0)
1875 ;; did we get to a maximal clique
1876 (if (> (length clique
) (length *maximum-clique
*))
1878 (setq *maximum-clique
* clique
)
1879 (return-from extend-clique
)))
1880 ;; can we do better?
1883 (if (not (member (gethash x coloring
) colors
))
1884 (push (gethash x coloring
) colors
)))
1885 (if (> (+ (length clique
) (length colors
)) (length *maximum-clique
*))
1887 (do () ((= (length neigh
) 0))
1888 (let* ((x (first neigh
)) (new-clique (cons x clique
))
1891 (if (is-edge-in-graph `(,(min x y
) ,(max x y
)) gr
)
1892 (push y new-neigh
)))
1893 (extend-clique new-clique new-neigh coloring gr
)
1894 (setq neigh
(remove x neigh
))))))))
1896 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1901 (defmfun $vertex_coloring
(g)
1902 (require-graph 'vertex_coloring
1 g
)
1903 (let ((col (dsatur g
)) (res ()) (chnumber 0))
1904 (dolist (v (vertices g
))
1905 (push `((mlist simp
) ,v
,(gethash v col
)) res
)
1906 (setq chnumber
(max chnumber
(gethash v col
))))
1907 `((mlist simp
) ,chnumber
((mlist simp
) ,@res
))))
1909 (defmfun $chromatic_number
(g)
1910 (require-graph 'chromatic_number
1 g
)
1911 ($first
($vertex_coloring g
)))
1913 (defmfun $edge_coloring
(gr)
1914 (require-graph 'edge_coloring
1 gr
)
1915 (let* ((edge-list (get-canonical-names (graph-edges gr
)))
1917 (g ($empty_graph n
)))
1922 (let ((e (car (rassoc i edge-list
))) (f (car (rassoc j edge-list
))))
1924 (or (member (first e
) f
) (member (second e
) f
))
1925 (add-edge `(,i
,j
) g
)))))
1926 (let ((coloring (dsatur g
))
1930 (push `((mlist simp
) ((mlist simp
) ,@(car (rassoc i edge-list
)))
1931 ,(gethash i coloring
)) res
)
1932 (setq ch-index
(max ch-index
(gethash i coloring
))))
1933 `((mlist simp
) ,ch-index
((mlist simp
) ,@res
)))))
1935 (defmfun $chromatic_index
(g)
1936 (require-graph 'chromatic_index
1 g
)
1937 ($first
($vertex_coloring
($line_graph g
))))
1940 (when (< (length (vertices g
)) 2)
1941 (let ((col (make-hash-table)))
1942 (dolist (v (vertices g
))
1943 (setf (gethash v col
) 1))
1944 (return-from dsatur col
)))
1946 (vsize (length (vertices g
)))
1947 (opt-chnumber (1+ vsize
)) (back nil
)
1952 (clique (greedy-clique g
))
1953 (clique-size (length clique
))
1955 (A (make-array vsize
))
1956 (F (make-hash-table))
1957 (f-opt (make-hash-table))
1958 (number-of-used-colors (make-hash-table :test
#'equal
))
1959 (dsat (make-hash-table))
1960 (uncolored (make-hash-table)))
1963 ;(format t "~%Preparing data")
1966 (setf (gethash v F
) (1+ i
))
1968 (dolist (v (vertices g
))
1969 (setf (gethash v dsat
) 0)
1970 (setf (gethash v uncolored
) (length (neighbors v g
)))
1971 (if (not (member v clique
))
1975 (setf (gethash v F
) 0))))
1977 (dolist (u (neighbors v g
))
1978 (decf (gethash u uncolored
))
1979 (setf (gethash `(,u
,(gethash v F
)) number-of-used-colors
) 1)
1980 (incf (gethash u dsat
))))
1982 ;(format t "~%Clique size: ~d" (length clique))
1983 ;(format t "~%Clique: ~d" clique)
1985 ;(format t "~%Starting with: ~d (~d)" start (aref A start))
1986 (do ((i start
(1+ i
))) ((or (= i vsize
) stop
))
1988 ;; Choose new vertex x
1992 (setq x
(aref A xindex
)))
1993 (let ((mdsat -
1) (munc -
1))
1994 (do ((j i
(1+ j
))) ((= j vsize
))
1995 (if (or (> (gethash (aref A j
) dsat
) mdsat
)
1996 (and (= (gethash (aref A j
) dsat
) mdsat
)
1997 (> (gethash (aref A j
) uncolored
) munc
)))
2001 (setq mdsat
(gethash x dsat
))
2002 (setq munc
(gethash x uncolored
)))))))
2003 ;(format t "~%New vertex: ~d" x)
2005 ;; Choose free color
2010 (setq k
(1+ (gethash x F
))))
2012 (do ((j k
(1+ j
))) ((or (>= j opt-chnumber
) (> free-color
0)))
2013 (if (= 0 (gethash `(,x
,j
) number-of-used-colors
0))
2014 (setq free-color j
)))
2015 ;(format t "~%New color: ~d" free-color)
2017 (if (> free-color
0)
2020 (setf (gethash x F
) free-color
)
2021 ;; Update dsat index
2022 (dolist (u (neighbors x g
))
2023 (incf (gethash `(,u
,free-color
) number-of-used-colors
0))
2024 (if (= 1 (gethash `(,u
,free-color
) number-of-used-colors
0))
2025 (incf (gethash u dsat
)))
2026 (decf (gethash u uncolored
)))
2028 (rotatef (aref A i
) (aref A xindex
)))
2029 ;; Unable to extend coloring - backtrack
2037 ;; We have a backtrack step
2039 (if (< start clique-size
)
2040 (return-from dsatur f-opt
))
2041 (setq x
(aref A start
))
2042 (setq k
(gethash x F
))
2043 ;; Delete the color of x
2044 (dolist (v (neighbors x g
))
2045 (decf (gethash `(,v
,k
) number-of-used-colors
))
2046 (incf (gethash v uncolored
))
2047 (if (= 0 (gethash `(,v
,k
) number-of-used-colors
))
2048 (decf (gethash v dsat
)))))
2049 ;; We have a coloring!
2051 ;; Save new optimal coloring
2052 (setq opt-chnumber
0)
2053 (dolist (v (vertices g
))
2054 (setf (gethash v f-opt
) (gethash v F
))
2055 (setq opt-chnumber
(max opt-chnumber
(gethash v F
))))
2056 ;(format t "~%Found new coloring: ~d" opt-chnumber)
2059 (do ((i 0 (1+ i
))) ((> start -
1))
2060 (if (= opt-chnumber
(gethash (aref A i
) f-opt
))
2062 (setq start
(1- i
)))))
2064 (if (or (< start clique-size
)
2065 (= opt-chnumber clique-size
))
2066 (return-from dsatur f-opt
))
2067 ;; Delete colors from start
2068 (do ((i start
(1+ i
))) ((= i vsize
))
2069 (dolist (v (neighbors (aref A i
) g
))
2070 (decf (gethash `(,v
,(gethash (aref A i
) F
))
2071 number-of-used-colors
))
2072 (incf (gethash v uncolored
))
2073 (if (= 0 (gethash `(,v
,(gethash (aref A i
) F
))
2074 number-of-used-colors
))
2075 (decf (gethash v dsat
)))))
2078 (defun greedy-clique (g)
2080 (dolist (v (vertices g
))
2081 (let ((tmp-clique (extend-greedy-clique `(,v
) (neighbors v g
) g
)))
2082 (if (> (length tmp-clique
) (length clique
))
2083 (setq clique tmp-clique
))))
2086 (defun extend-greedy-clique (clique neigh g
)
2087 (if (= 0 (length neigh
))
2088 (return-from extend-greedy-clique clique
))
2089 (if (= 1 (length neigh
))
2090 (return-from extend-greedy-clique
(cons (car neigh
) clique
)))
2091 (let ((u nil
) (new-neigh ()))
2093 (let ((tmp-neigh (copy-tree neigh
)))
2095 (if (and (not (member w
(neighbors v g
))))
2096 (setq tmp-neigh
(remove w tmp-neigh
))))
2097 (if (>= (length tmp-neigh
) (length new-neigh
))
2100 (setq new-neigh tmp-neigh
)))))
2102 (extend-greedy-clique (cons u clique
) new-neigh g
)
2107 ;; Expose lisp hashtable
2111 (defmfun $hash_table
()
2112 (make-hash-table :test
#'equal
))
2114 (defmfun $get_hash
(elt ht
&optional default
)
2115 (unless (hash-table-p ht
)
2116 ($error
"Second argument to `get_hash' is not a hash table!"))
2117 (gethash elt ht default
))
2119 (defmfun $set_hash
(elt ht value
)
2120 (unless (hash-table-p ht
)
2121 ($error
"Second argument to `set_hash' is not a hash table!"))
2122 (setf (gethash elt ht
) value
)
2125 (defmfun $hash_table_data
(ht)
2126 (unless (hash-table-p ht
)
2127 ($error
"First argument to `hash_table_info' is not a hash table!"))
2131 (setq res
(cons `((marrow simp
) ,key
,val
) res
)))
2133 (cons '(mlist simp
) res
)))
2135 ;;;;;;;;;;;;;;;;;;;;;;;;;
2137 ;; This function is needed for draw_graph (get the temporary file to write in)
2139 ;;;;;;;;;;;;;;;;;;;;;;;;;
2141 (defmfun $temp_filename
(file)
2142 (unless (stringp file
)
2143 ($error
"Argument to `temp_filename' is not a string"))
2144 (plot-temp-file file
))
2146 (defmfun $read_string
(str)
2147 (unless (stringp str
)
2148 ($error
"Argument to `read_string' is not a string"))
2149 (let ((num (read-from-string str
)))
2150 (if (numberp num
) num str
)))