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 $clear_vertex_label
(v gr
)
380 (require-vertex 'clear_vertex_label
1 v
)
381 (require-graph-or-digraph 'clear_vertex_label
2 gr
)
382 (require-vertex-in-graph 'clear_label v gr
)
383 (clear-vertex-label v gr
))
385 (defun clear-vertex-label (v gr
)
386 (remhash v
(if (graph-p gr
)
387 (graph-vertex-labels gr
)
388 (digraph-vertex-labels gr
)))
391 (defmfun $set_vertex_label
(v l gr
)
392 (require-vertex 'set_vertex_label
1 v
)
393 (require-graph-or-digraph 'set_vertex_label
3 gr
)
394 (require-vertex-in-graph 'set_label v gr
)
395 (set-vertex-label v l gr
))
397 (defun set-vertex-label (v l gr
)
398 (setf (gethash v
(if (graph-p gr
)
399 (graph-vertex-labels gr
)
400 (digraph-vertex-labels gr
)))
404 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
408 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
410 (defun require-medge (m ar e
)
412 ((not (and ($listp e
) (eql 2 ($length e
))))
413 ($error
"Argument" ar
"to" m
"is not an edge (0)."))
414 (t (let ((u ($first e
)) (v ($second e
)))
415 (unless (and (integerp u
) (integerp v
))
416 ($error
"Argument" ar
"to" m
"is not an edge (1)."))
418 ($error
"Argument" ar
"to" m
"is not an edge (2)."))))))
420 (defun require-edge-in-graph (m e gr
)
421 (unless (is-edge-in-graph e gr
)
422 ($error m
": edge not in graph.")))
424 (defun m-edge-to-l-edge (e)
426 (list (apply #'min uv
) (apply #'max uv
))))
428 (defun m-edge-to-l-dedge (e)
430 (list (first uv
) (second uv
))))
432 (defun l-edge-to-m-edge (e)
435 (defmfun $is_edge_in_graph
(e gr
)
436 (require-medge 'is_edge_in_graph
1 e
)
437 (require-graph-or-digraph 'is_edge_in_graph
2 gr
)
439 (is-edge-in-graph (m-edge-to-l-edge e
) gr
)
440 (is-edge-in-graph (m-edge-to-l-dedge e
) gr
)))
442 (defun is-edge-in-graph (e gr
)
444 (not (null (member (second e
) (neighbors (first e
) gr
))))
445 (not (null (member (second e
) (out-neighbors (first e
) gr
)))) ))
447 (defmfun $add_edge
(e gr
)
448 (require-medge 'add_edge
1 e
)
449 (require-graph-or-digraph 'add_edge
2 gr
)
450 (let* ((e1 (if (graph-p gr
)
452 (m-edge-to-l-dedge e
)))
453 (u (first e1
)) (v (second e1
)))
455 ((not (and (is-vertex-in-graph u gr
) (is-vertex-in-graph v gr
)))
456 ($error
"add_edge: end vertices are not in graph!"))
458 ($error
"add_edge: end vertices are equal!"))
459 ((is-edge-in-graph e1 gr
)
460 ($error
"add_edge: edge already in graph!")))
463 (defmfun $add_edges
(el gr
)
464 (require-graph-or-digraph 'add_edges
2 gr
)
465 (if (not ($listp el
))
466 ($error
"Argument 1 to add_edges is not a list!")
468 (require-medge 'add_edges
1 e
)
472 (defun add-edge (e gr
)
473 (let ((u (first e
)) (v (second e
)))
476 (push v
(gethash u
(graph-neighbors gr
)))
477 (push u
(gethash v
(graph-neighbors gr
)))
478 (push e
(graph-edges gr
))
479 (incf (graph-size gr
)))
481 (push v
(gethash u
(digraph-out-neighbors gr
)))
482 (push u
(gethash v
(digraph-in-neighbors gr
)))
483 (push e
(digraph-edges gr
))
484 (incf (digraph-size gr
))))
487 (defun add-edges (elist gr
)
492 (require-graph-or-digraph 'edges
1 gr
)
493 (let ((e (mapcar #'(lambda (u) `((mlist simp
) ,@(copy-list u
)))
495 `((mlist simp
) ,@e
)))
502 (defmfun $remove_edge
(e gr
)
503 (require-medge 'remove_edge
1 e
)
504 (require-graph-or-digraph 'remove_edge
2 gr
)
505 (unless ($is_edge_in_graph e gr
)
506 ($error
"remove_edge: edge" e
"is not in graph."))
507 (remove-edge (if (graph-p gr
)
509 (m-edge-to-l-dedge e
))
512 (defmfun $remove_edges
(el gr
)
513 (require-graph-or-digraph 'remove_edges
2 gr
)
515 ($error
"Argument 1 to remove_edges is not a list."))
520 (defun remove-edge (e gr
)
521 (let ((u (first e
)) (v (second e
)))
524 (setf (gethash u
(graph-neighbors gr
))
525 (remove v
(gethash u
(graph-neighbors gr
)) :count
1))
526 (setf (gethash v
(graph-neighbors gr
))
527 (remove u
(gethash v
(graph-neighbors gr
)) :count
1))
528 (clear-edge-weight e gr
)
529 (decf (graph-size gr
))
530 (setf (graph-edges gr
)
531 (remove `(,u
,v
) (graph-edges gr
) :test
#'equal
:count
1)))
533 (setf (gethash u
(digraph-out-neighbors gr
))
534 (remove v
(gethash u
(digraph-out-neighbors gr
)) :count
1))
535 (setf (gethash v
(digraph-in-neighbors gr
))
536 (remove u
(gethash v
(digraph-in-neighbors gr
)) :count
1))
537 (clear-edge-weight e gr
)
538 (decf (digraph-size gr
))
539 (setf (digraph-edges gr
)
540 (remove `(,u
,v
) (digraph-edges gr
) :test
#'equal
:count
1))))
543 (defmfun $contract_edge
(e gr
)
544 (require-medge 'contract_edge
1 e
)
545 (require-graph 'contract_edge
2 gr
)
546 (let* ((e1 (m-edge-to-l-edge e
)) (u (first e1
)) (v (second e1
)))
547 (dolist (x (neighbors v gr
))
549 (let ((e2 (list (min x u
) (max x u
))))
550 (unless (is-edge-in-graph e2 gr
)
552 (remove-vertex v gr
))
555 (defmfun $contract_edges
(el gr
)
556 (require-graph-or-digraph 'contract_edges
2 gr
)
558 ($error
"Argument 1 to contract_edges is not a list."))
560 ($contract_edge e gr
))
563 (defmfun $get_edge_weight
(e gr
&optional default not-present
)
564 (require-medge 'get_edge_weight
1 e
)
565 (require-graph-or-digraph 'get_edge_weight
2 gr
)
566 (unless ($is_edge_in_graph e gr
)
567 (if (null not-present
)
568 ($error
"get_edge_weight: edge not in graph")
569 (return-from $get_edge_weight not-present
)))
570 (let ((w (if (graph-p gr
)
571 (get-edge-weight (m-edge-to-l-edge e
) gr
)
572 (get-edge-weight (m-edge-to-l-dedge e
) gr
))))
575 (defun get-edge-weight (e gr
)
578 (graph-edge-weights gr
)
579 (digraph-edge-weights gr
))))
580 (gethash e edge-weights
)))
582 (defmfun $clear_edge_weight
(e gr
)
583 (require-medge 'clear_edge_weight
1 e
)
584 (require-graph-or-digraph 'clear_edge_weight
2 gr
)
585 (unless ($is_edge_in_graph e gr
)
586 ($error
"clear_edge_weight: edge not in graph"))
588 (clear-edge-weight (m-edge-to-l-edge e
) gr
)
589 (clear-edge-weight (m-edge-to-l-dedge e
) gr
)))
591 (defun clear-edge-weight (e gr
)
595 (graph-edge-weights gr
)
596 (digraph-edge-weights gr
))))
597 (remhash e edge-weights
)
600 (defmfun $set_edge_weight
(e w gr
)
601 (require-medge 'set_edge_weight
1 e
)
602 (require-graph-or-digraph 'set_edge_weight
3 gr
)
603 (unless ($is_edge_in_graph e gr
)
604 ($error
"set_edge_weight: edge not in graph"))
606 (set-edge-weight (m-edge-to-l-edge e
) w gr
)
607 (set-edge-weight (m-edge-to-l-dedge e
) w gr
)))
609 (defun set-edge-weight (e w gr
)
613 (graph-edge-weights gr
)
614 (digraph-edge-weights gr
))))
615 (setf (gethash e edge-weights
) w
)
618 (defmfun $connect_vertices
(sources sinks gr
)
619 (require-graph 'connect_vertices
3 gr
)
621 (setq sources
(cdr sources
))
622 (setq sources
`(,sources
)))
624 (setq sinks
(cdr sinks
))
625 (setq sinks
`(,sinks
)))
628 ($add_edge
`((mlist simp
) ,u
,v
) gr
)))
631 (defmfun $subdivide_edge
(e gr
)
632 (require-graph 'subdivide_edge
2 gr
)
633 (require-edge-in-graph 'subdivide_edge
(m-edge-to-l-edge e
) gr
)
634 (let ((new-vertex (1+ (apply #'max
(vertices gr
))))
637 ($remove_edge
(cons '(mlist simp
) (list x y
)) gr
)
638 ($add_vertex new-vertex gr
)
639 ($add_edge
(cons '(mlist simp
) (list x new-vertex
)) gr
)
640 ($add_edge
(cons '(mlist simp
) (list y new-vertex
)) gr
))
643 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
645 ;; implementation of a set using hash tables
647 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
650 (content (make-hash-table)))
652 (defun new-set (&rest initial-content
)
653 (let ((set (make-ht-set)))
654 (dolist (obj initial-content
)
658 (defun set-member (obj set
)
659 (gethash obj
(ht-set-content set
)))
661 (defun set-add (obj set
)
662 (setf (gethash obj
(ht-set-content set
)) t
))
664 (defun set-remove (obj set
)
665 (remhash obj
(ht-set-content set
)))
667 (defun set-emptyp (set)
668 (= 0 (hash-table-count (ht-set-content set
))))
670 (defun set-elements (set)
672 (maphash #'(lambda (key val
)
673 (declare (ignore val
))
675 (ht-set-content set
))
679 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
681 ;;; graph definitions
683 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
685 (defmfun $empty_graph
(n)
686 (let ((gr (make-graph)))
691 (defmfun $empty_digraph
(n)
692 (let ((gr (make-digraph)))
697 (defmfun $create_graph
(v_list e_list
&optional dir
)
698 (let ((directed nil
))
699 ;; check if the graph is a directed graph
701 (when dir
(setq directed t
)))
702 ((and (eq (caar dir
) 'mequal
)
703 (eq (cadr dir
) '$directed
)
706 (unless (or (integerp v_list
) ($listp v_list
))
707 ($error
"Argument 1 to create_graph is not a list."))
708 (unless ($listp e_list
)
709 ($error
"Argument 2 to create_graph is not a list."))
710 (let ((gr (if directed
(make-digraph) (make-graph))))
711 (if (integerp v_list
)
714 (dolist (v (reverse (cdr v_list
)))
717 ($add_vertex
($first v
) gr
)
718 ($set_vertex_label
($first v
) ($second v
) gr
))
719 ($add_vertex v gr
))))
720 (dolist (e (cdr e_list
))
721 (if ($listp
($first e
))
723 ($add_edge
($first e
) gr
)
724 ($set_edge_weight
($first e
) ($second e
) gr
))
728 (defmfun $cycle_graph
(n)
729 (let ((g ($empty_graph n
)) pos
)
731 (add-edge (list i
(1+ i
)) g
))
732 (add-edge (list 0 (1- n
)) g
)
734 (setq pos
(cons `((mlist simp
) ,i
735 ((mlist simp
) ,(cos (* i
2 pi
(/ n
))) ,(sin (* i
2 pi
(/ n
)))))
737 ($set_positions
(cons '(mlist simp
) pos
) g
)
740 (defmfun $cycle_digraph
(n)
741 (let ((g ($empty_digraph n
)))
743 (add-edge (list i
(1+ i
)) g
))
744 (add-edge (list (1- n
) 0) g
)
747 (defmfun $path_graph
(n)
748 (let ((g ($empty_graph n
)) pos
)
750 (add-edge (list i
(1+ i
)) g
))
752 (setq pos
(cons `((mlist simp
) ,i
755 ($set_positions
(cons '(mlist simp
) pos
) g
)
758 (defmfun $path_digraph
(n)
759 (let ((g ($empty_digraph n
)))
761 (add-edge (list i
(1+ i
)) g
))
764 (defmfun $petersen_graph
(&optional n d
)
767 (unless (and (integerp n
) (integerp d
))
768 ($error
"Arguments to petersen_graph are not integers!")))
769 (let ((g ($empty_graph
(* 2 n
)))
772 (add-edge `(,i
,(+ n i
)) g
)
773 (when (or (/= n
(* 2 d
))
775 (let* ((u (+ i n
)) (v (+ (mod (+ i d
) n
) n
))
776 (e1 (min v u
)) (e2 (max v u
)))
777 (add-edge `(,e1
,e2
) g
)))
778 (let* ((u (mod (1+ i
) n
)) (e1 (min u i
)) (e2 (max u i
)))
779 (add-edge `(,e1
,e2
) g
)))
781 (push `((mlist simp
) ,i
((mlist simp
)
782 ,(sin (/ (* 2 i pi
) n
))
783 ,(cos (/ (* 2 i pi
) n
))))
785 (push `((mlist simp
) ,(+ n i
) ((mlist simp
)
786 ,(* 0.66 (sin (/ (* 2 i pi
) n
)))
787 ,(* 0.66 (cos (/ (* 2 i pi
) n
)))))
789 (setf (graph-vertex-positions g
) (cons '(mlist simp
) positions
))
792 (defmfun $complement_graph
(gr)
793 (require-graph 'complement_graph
1 gr
)
801 (when (and (< u v
) (not (is-edge-in-graph `(,u
,v
) gr
)))
802 (add-edge `(,u
,v
) co
))))
803 (setf (graph-vertex-positions co
) (graph-vertex-positions gr
))
806 (defmfun $complete_graph
(n)
807 (if (not (and (integerp n
) (>= n
0)))
808 ($error
"Argument 1 to complete_graph is not a positive integer"))
809 (let ((g ($empty_graph n
))
815 (add-edge `(,i
,j
) g
)))
817 (push `((mlist simp
) ,i
((mlist simp
)
818 ,(cos (/ (* 2 i pi
) n
))
819 ,(sin (/ (* 2 i pi
) n
))))
821 (setf (graph-vertex-positions g
) (cons '(mlist simp
) pos
))
824 (defmfun $from_adjacency_matrix
(m)
825 (if (not ($matrixp m
))
826 ($error
"Argument 1 to from_adjacency_matrix is not a matrix"))
827 (if (not (= ($length m
) ($length
($first m
))))
828 ($error
"Argument 1 to from_adjacency_matrix is not a square matrix"))
829 (let* ((n ($length m
)) (g ($empty_graph n
)))
831 (do ((j (1+ i
) (1+ j
)))
833 (if (not (= 0 (nth (1+ i
) (nth (1+ j
) m
))))
834 (add-edge `(,i
,j
) g
))))
837 (defmfun $graph_union
(&rest gr-list
)
839 ((= 0 (length gr-list
))
841 ((= 1 (length gr-list
))
843 ((= 2 (length gr-list
))
844 (graph-union (first gr-list
) (second gr-list
)))
846 (graph-union (first gr-list
) (apply #'$graph_union
(rest gr-list
))))))
848 (defun graph-union (g1 g2
)
849 (require-graph 'graph_union
1 g1
)
850 (require-graph 'graph_union
2 g2
)
851 (let ((g (make-graph)) (n (1+ (apply #'max
(graph-vertices g1
)))))
852 (dolist (v (graph-vertices g1
))
854 (dolist (e (graph-edges g1
))
856 (dolist (v (graph-vertices g2
))
857 (add-vertex (+ n v
) g
))
858 (dolist (e (graph-edges g2
))
859 (add-edge (list (+ n
(first e
)) (+ n
(second e
))) g
))
862 (defmfun $graph_join
(g1 g2
)
863 (require-graph 'graph_join
1 g1
)
864 (require-graph 'graph_join
2 g2
)
865 (let ((g (make-graph)) (n (1+ (apply #'max
(graph-vertices g1
)))))
866 (dolist (v (graph-vertices g1
))
868 (dolist (e (graph-edges g1
))
870 (dolist (v (graph-vertices g2
))
871 (add-vertex (+ n v
) g
))
872 (dolist (e (graph-edges g2
))
873 (add-edge (list (+ n
(first e
)) (+ n
(second e
))) g
))
874 (dolist (v (graph-vertices g1
))
875 (dolist (u (graph-vertices g2
))
876 (add-edge (list v
(+ n u
)) g
)))
879 (defun get-canonical-names (l)
880 (let ((names ()) (i 0))
882 (push `(,v .
,i
) names
)
886 (defmfun $graph_product
(&rest gr-list
)
888 ((= 0 (length gr-list
))
890 ((= 1 (length gr-list
))
892 ((= 2 (length gr-list
))
893 (graph-product (first gr-list
) (second gr-list
)))
895 (graph-product (first gr-list
) (apply #'$graph_product
(rest gr-list
))))))
897 (defun graph-product (g1 g2
)
898 (require-graph 'graph_product
1 g1
)
899 (require-graph 'graph_product
2 g2
)
901 ((names1 (get-canonical-names (graph-vertices g1
)))
902 (names2 (get-canonical-names (graph-vertices g2
)))
903 (size1 (graph-order g1
))
904 (size2 (graph-order g2
))
905 (size (* size1 size2
))
906 (g ($empty_graph size
)))
907 (dolist (e (graph-edges g1
))
908 (dolist (v (graph-vertices g2
))
910 ((v1 (cdr (assoc (first e
) names1
)))
911 (v2 (cdr (assoc (second e
) names1
)))
912 (u (cdr (assoc v names2
)))
913 (f (list (+ (* u size1
) v1
) (+ (* u size1
) v2
)))
914 (f (list (apply #'min f
) (apply #'max f
))))
916 (dolist (e (graph-edges g2
))
917 (dolist (v (graph-vertices g1
))
919 ((v1 (cdr (assoc (first e
) names2
)))
920 (v2 (cdr (assoc (second e
) names2
)))
921 (u (cdr (assoc v names1
)))
922 (f (list (+ (* v1 size1
) u
) (+ (* v2 size1
) u
)))
923 (f (list (apply #'min f
) (apply #'max f
))))
927 (defmfun $line_graph
(gr)
928 (require-graph 'line_graph
1 gr
)
930 (get-canonical-names (graph-edges gr
))) (n (graph-size gr
))
931 (g ($empty_graph n
)))
933 (do ((j (1+ i
) (1+ j
)))
935 (let ((e (car (rassoc i edge-list
))) (f (car (rassoc j edge-list
))))
937 (or (member (first e
) f
) (member (second e
) f
))
938 (add-edge `(,i
,j
) g
)))))
941 (defmfun $random_graph
(n p
)
942 (if (not (integerp n
))
943 ($error
"Argument 1 to random_graph is not an integer"))
944 (if (not (floatp ($float p
)))
945 ($error
"Argument 2 to random_graph is not a float"))
946 (let ((g ($empty_graph n
))
949 (do ((j (1+ i
) (1+ j
)))
951 (if (< (random 1.0) p
)
952 (add-edge `(,i
,j
) g
))))
955 (defmfun $random_graph1
(n m
)
956 #+sbcl
(declare (notinline $random_graph1
))
958 ($error
"Argument 1 to random_graph is not an integer"))
960 ($error
"Argument 2 to random_graph is not an integer"))
961 (when (< (* n
(1- n
)) (* 2 m
))
962 ($error
"random_graph1: no such graph"))
963 (when (< (* n
(1- n
)) (* 4 m
))
964 (return-from $random_graph1
965 ($complement_graph
($random_graph1 n
(- (/ (* n
(1- n
)) 2) m
)))))
966 (let ((g ($empty_graph n
)))
967 (do ((i 0)) ((= i m
))
968 (let ((u (random n
)) (v (random n
)))
970 (let ((e (list (min u v
) (max u v
))))
971 (unless (is-edge-in-graph e g
)
976 (defmfun $random_bipartite_graph
(a b p
)
978 ($error
"Argument 1 to random graph is not an integer"))
980 ($error
"Argument b to random graph is not an integer"))
981 (let ((g ($empty_graph
(+ a b
))))
984 (when (< (random 1.0) p
)
985 (add-edge (list x
(+ a y
)) g
))))
988 (defmfun $random_digraph
(n p
)
990 ($error
"Argument 1 to random_digraph is not an integer"))
991 (unless (floatp ($float p
))
992 ($error
"Argument 2 to random_digraph is not a float"))
993 (let ((g ($empty_digraph n
))
997 (when (and (not (= i j
)) (< (random 1.0) p
))
998 (add-edge `(,i
,j
) g
))))
1001 (defmfun $random_tournament
(n)
1002 (unless (and (integerp n
) (>= n
0))
1003 ($error
"Argument 1 to random_tournament is not a positive integer"))
1004 (let ((g ($empty_digraph n
)))
1006 (do ((j (1+ i
) (1+ j
)))
1008 (if (and (not (= i j
)) (< (random 1.0) 0.5))
1009 (add-edge `(,i
,j
) g
)
1010 (add-edge `(,j
,i
) g
))))
1013 (defmfun $random_tree
(n)
1014 (unless (and (integerp n
) (>= n
0))
1015 ($error
"Argument 1 to random_tree is not a positive integer"))
1017 ((tr ($empty_graph n
))
1018 (vrt (remove 0 (graph-vertices tr
) :count
1))
1022 ((u (nth (random (length vrt
)) vrt
))
1023 (v (nth (random (length tree-vrt
)) tree-vrt
)))
1024 (setq vrt
(remove u vrt
:count
1))
1026 (add-edge (list (min u v
) (max u v
)) tr
)))
1029 (defmfun $underlying_graph
(gr)
1030 (require-digraph 'underlying_graph
1 gr
)
1031 (let ((g (make-graph)))
1032 (dolist (v (vertices gr
))
1034 (dolist (e (digraph-edges gr
))
1035 (let ((u (first e
)) (v (second e
)))
1036 (let ((e1 (list (apply #'min e
) (apply #'max e
))))
1037 (when (not (is-edge-in-graph e1 g
))
1038 (add-edge `(,u
,v
) g
)))))
1041 (defmfun $induced_subgraph
(vl gr
)
1042 (require-graph 2 'induced_subgraph gr
)
1044 ($error
"First argument to induced_subgraph is not a list."))
1049 (when (not (is-vertex-in-graph v gr
))
1051 "induced_subgraph: second argument is not a list of vertices"))
1053 (let ((l (get-vertex-label v gr
)))
1055 (set-vertex-label v l g
))))
1056 (dolist (e (graph-edges gr
))
1057 (let ((u (first e
)) (v (second e
)))
1058 (when (and (member u v_l
) (member v v_l
))
1062 (defmfun $wheel_graph
(n)
1063 (unless (and (integerp n
) (>= n
3))
1064 ($error
"wheel_graph: first argument is no an integer greater than 3"))
1065 (let ((g ($cycle_graph n
))
1069 (add-edge `(,i
,n
) g
))
1071 (push `((mlist simp
) ,i
((mlist simp
)
1072 ,($sin
(/ (* 2 i pi
) n
))
1073 ,($cos
(/ (* 2 i pi
) n
))))
1075 (push `((mlist simp
) ,n
((mlist simp
) 0 0)) positions
)
1076 ($set_positions
(cons '(mlist simp
) positions
) g
)
1079 (defmfun $circulant_graph
(n l
)
1080 (unless (and (integerp n
) (> n
0))
1081 ($error
"Argument 1 to circulant_graph is not a positive integer."))
1083 ($error
"Argument 2 to circulant_graph is not a list."))
1084 (let ((g ($empty_graph n
))
1087 (unless (and (integerp d
) (> d
0))
1089 "Argument 2 to circulant graph is no a list of positive integers"))
1091 (let ((e `(,i
,(mod (+ i d
) n
))))
1092 (setq e
(list (apply #'min e
) (apply #'max e
)))
1095 (push `((mlist simp
) ,i
((mlist simp
)
1096 ,($sin
(m// (m* 2.0 i pi
) n
))
1097 ,($cos
(m// (m* 2.0 i pi
) n
))))
1099 ($set_positions
(cons '(mlist simp
) positions
) g
)
1102 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1104 ;;; graph properties
1106 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1108 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1110 ;;; Connected components
1113 (defmfun $connected_components
(gr)
1114 (require-graph 'connected_components
1 gr
)
1115 (when (= 0 (graph-order gr
))
1116 (return-from $connected_components
'((mlist simp
))))
1117 (let ((components ()) (visited (make-hash-table)))
1118 (loop for v in
(vertices gr
) do
1119 (unless (gethash v visited
)
1120 (let ((c ()) (active ()))
1122 (loop while active do
1123 (let ((x (pop active
)))
1125 (setf (gethash x visited
) t
)
1126 (dolist (u (neighbors x gr
))
1127 (unless (or (gethash u visited
) (member u active
))
1129 (push `((mlist simp
) ,@c
) components
))))
1130 `((mlist simp
) ,@components
)))
1132 (defmfun $is_connected
(gr)
1133 (require-graph 'is_connected
1 gr
)
1134 (<= ($length
($connected_components gr
)) 1))
1136 (defmfun $is_tree
(gr)
1137 (require-graph 'is_tree
1 gr
)
1138 (and ($is_connected gr
) (= (graph-order gr
) (1+ (graph-size gr
)))))
1140 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1142 ;;; Reachable vertices
1146 (defmfun $reachable_vertices
(v gr
)
1147 (require-graph-or-digraph 'reachable_vertices
2 gr
)
1148 (require-vertex 'reachable_vertices
1 v
)
1149 (require-vertex-in-graph 'reachable_vertices v gr
)
1150 (when (= 0 (if (graph-p gr
) (graph-order gr
) (digraph-order gr
)))
1151 (return-from $reachable_vertices
'((mlist simp
))))
1152 (let ((component ()) (visited (make-hash-table)))
1153 (unless (gethash v visited
)
1156 (loop while active do
1157 (let ((x (pop active
)))
1159 (setf (gethash x visited
) t
)
1160 (dolist (u (if (graph-p gr
) (neighbors x gr
) (out-neighbors x gr
)))
1161 (unless (or (gethash u visited
) (member u active
))
1162 (push u active
)))))))
1163 `((mlist simp
) ,@component
)))
1165 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1167 ;;; Adjacency matrix and Laplacian matrix
1170 (defmfun $adjacency_matrix
(gr)
1171 (require-graph-or-digraph 'adjacency_matrix
1 gr
)
1172 (let* ((n (if (graph-p gr
) (graph-order gr
) (digraph-order gr
)))
1173 (m ($zeromatrix n n
))
1174 (names (get-canonical-names (vertices gr
))))
1175 (dolist (e (edges gr
))
1176 (setf (nth (1+ (cdr (assoc (first e
) names
)))
1177 (nth (1+ (cdr (assoc (second e
) names
))) m
)) 1)
1179 (setf (nth (1+ (cdr (assoc (second e
) names
)))
1180 (nth (1+ (cdr (assoc (first e
) names
))) m
)) 1)))
1183 (defmfun $laplacian_matrix
(gr)
1184 (require-graph 'laplacian_matrix
1 gr
)
1185 (let ((m ($zeromatrix
(graph-order gr
) (graph-order gr
)))
1186 (names (get-canonical-names (vertices gr
))))
1187 (dolist (v (graph-vertices gr
))
1188 (setf (nth (1+ (cdr (assoc v names
)))
1189 (nth (1+ (cdr (assoc v names
))) m
))
1190 (length (neighbors v gr
))))
1191 (dolist (e (graph-edges gr
))
1192 (setf (nth (1+ (cdr (assoc (first e
) names
)))
1193 (nth (1+ (cdr (assoc (second e
) names
))) m
)) -
1)
1194 (setf (nth (1+ (cdr (assoc (second e
) names
)))
1195 (nth (1+ (cdr (assoc (first e
) names
))) m
)) -
1))
1198 (defmfun $graph_charpoly
(gr x
)
1199 (require-graph 'graph_charpoly
1 gr
)
1201 ($charpoly
($adjacency_matrix gr
) x
)))
1203 (defmfun $graph_eigenvalues
(gr)
1204 (require-graph 'graph_eigenvalues
1 gr
)
1206 (mfuncall '$eigenvalues
($adjacency_matrix gr
))))
1208 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1210 ;;; girth, odd_girth
1213 (defmfun $girth
(gr)
1214 (require-graph 'girth
1 gr
)
1217 (defmfun $odd_girth
(gr)
1218 (require-graph 'odd_girth
1 gr
)
1221 (defun girth (gr odd
)
1222 (let ((girth (1+ (graph-order gr
))))
1223 (dolist (v (graph-vertices gr
))
1225 ((visited (new-set v
))
1226 (active (new-set v
))
1230 ((or (set-emptyp active
)
1231 (> (* 2 depth
) girth
)
1233 (setq next
(new-set))
1234 (dolist (u (set-elements active
))
1235 (dolist (w (neighbors u gr
))
1236 (if (not (set-member w visited
))
1241 (if (set-member w active
)
1242 (setq girth
(- (* 2 depth
) 1)))
1243 (if (and (not odd
) (set-member w next
))
1244 (setq girth
(min girth
(* 2 depth
))))))))
1246 (setq depth
(1+ depth
)))))
1247 (if (> girth
(graph-order gr
))
1251 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1253 ;;; diameter, radius
1256 (defmfun $vertex_eccentricity
(v gr
)
1257 (require-graph 'vertex_eccentricity
1 gr
)
1258 (require-vertex-in-graph 'vertex_eccentricity v gr
)
1259 (let ((ecc (eccentricity (list v
) gr
)))
1262 (defun eccentricity (v_list gr
)
1263 (unless ($is_connected gr
)
1264 ($error
"eccentricity: graph is not connected."))
1265 (let ((ecc (make-hash-table)))
1268 ((visited (new-set v
))
1269 (active (new-set v
))
1273 ((set-emptyp active
))
1274 (setq next
(new-set))
1275 (dolist (u (set-elements active
))
1276 (dolist (w (neighbors u gr
))
1277 (when (not (set-member w visited
))
1281 (setq depth
(1+ depth
)))
1282 (setf (gethash v ecc
) depth
)))
1285 (defmfun $diameter
(gr)
1286 (require-graph 'diameter
1 gr
)
1287 (let ((ecc (eccentricity (vertices gr
) gr
))
1289 (maphash #'(lambda (key val
)
1290 (declare (ignore key
))
1291 (when (> val diameter
)
1292 (setq diameter val
)))
1296 (defmfun $radius
(gr)
1297 (require-graph 'radius
1 gr
)
1298 (let ((ecc (eccentricity (vertices gr
) gr
))
1299 (radius ($graph_order gr
)))
1300 (maphash #'(lambda (key val
)
1301 (declare (ignore key
))
1302 (when (< val radius
)
1307 (defmfun $graph_center
(gr)
1308 (require-graph 'graph_center
1 gr
)
1309 (let ((ecc (eccentricity (vertices gr
) gr
))
1311 (radius ($graph_order gr
)))
1312 (maphash #'(lambda (key val
)
1313 (declare (ignore key
))
1314 (when (< val radius
)
1317 (maphash #'(lambda (key val
)
1318 (when (= val radius
)
1321 `((mlist simp
) ,@per
)))
1323 (defmfun $graph_periphery
(gr)
1324 (require-graph 'graph_periphery
1 gr
)
1325 (let ((ecc (eccentricity (vertices gr
) gr
))
1328 (maphash #'(lambda (key val
)
1329 (declare (ignore key
))
1330 (when (> val diameter
)
1331 (setq diameter val
)))
1333 (maphash #'(lambda (key val
)
1334 (when (= val diameter
)
1337 `((mlist simp
) ,@center
)))
1339 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1344 (defmfun $bipartition
(gr)
1345 (require-graph 'bipartition
1 gr
)
1346 (when (= (graph-order gr
) 0)
1347 (return-from $bipartition
`((mlist simp
) ((mlist simp
)) ((mlist simp
)))))
1348 (let ((components (cdr ($connected_components gr
))) (A ()) (B ()))
1349 (dolist (c components
)
1350 (let ((partition (bi-partition (first (cdr c
)) gr
)))
1351 (if (null partition
)
1352 (return-from $bipartition
`((mlist simp
)))
1354 (setq A
(append A
(first partition
)))
1355 (setq B
(append B
(second partition
)))))))
1356 `((mlist simp
) ((mlist simp
) ,@A
) ((mlist simp
) ,@B
))))
1358 (defun bi-partition (v gr
)
1364 (colors (make-hash-table)))
1365 (setf (gethash v colors
) 1)
1370 (wc (gethash w colors
)))
1375 (dolist (u (neighbors w gr
))
1376 (if (set-member u visited
)
1377 (when (= (gethash u colors
) wc
)
1378 (return-from bi-partition
()))
1379 (unless (member u active
)
1381 (setf (gethash u colors
) (- 1 wc
)))))))
1384 (defmfun $is_bipartite
(gr)
1385 (require-graph 'is_bipartite
1 gr
)
1386 (> ($length
($bipartition gr
)) 1))
1388 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1393 (defmfun $biconnected_components
(gr)
1394 (require-graph 'biconnected_components
1 gr
)
1395 (if (= 0 (graph-order gr
))
1398 ((bicomp `((mlist simp
)))
1399 (comp (cdr ($connected_components gr
))))
1401 (if (= ($length c
) 1)
1402 (setq bicomp
($append bicomp
`((mlist simp
) ,c
)))
1403 (setq bicomp
($append bicomp
(bicomponents ($first c
) gr
)))))
1406 (defmfun $is_biconnected
(gr)
1407 (require-graph 'is_biconnected
1 gr
)
1408 (eql ($length
($biconnected_components gr
)) 1))
1410 (defvar *dfs-bicomp-depth
* 0)
1411 (defvar *dfs-bicomp-num
* ())
1412 (defvar *dfs-bicomp-low-pt
* ())
1413 (defvar *dfs-bicomp-edges
* ())
1414 (defvar *bicomponents
* ())
1416 (defun bicomponents (v gr
)
1418 (setq *dfs-bicomp-depth
* 0)
1419 (setq *dfs-bicomp-num
* (make-hash-table))
1420 (setq *dfs-bicomp-low-pt
* (make-hash-table))
1421 (setq *dfs-bicomp-edges
* (make-hash-table))
1422 (setq *bicomponents
* ())
1423 (dolist (v (graph-vertices gr
))
1424 (setf (gethash v
*dfs-bicomp-num
*) 0))
1425 (dfs-bicomponents gr v
)
1426 (dolist (c *bicomponents
*)
1427 (let ((curr-comp ()))
1429 (let ((u (first e
)) (v (second e
)))
1430 (unless (member u curr-comp
)
1432 (unless (member v curr-comp
)
1433 (push v curr-comp
))))
1434 (setq bicomp
(cons `((mlist simp
) ,@(sort curr-comp
#'<)) bicomp
))))
1435 `((mlist simp
) ,@bicomp
)))
1437 (defun dfs-bicomponents (gr w
)
1438 (setq *dfs-bicomp-depth
* (1+ *dfs-bicomp-depth
*))
1439 (setf (gethash w
*dfs-bicomp-num
*) *dfs-bicomp-depth
*)
1440 (setf (gethash w
*dfs-bicomp-low-pt
*) *dfs-bicomp-depth
*)
1441 (dolist (u (neighbors w gr
))
1442 (when (< (gethash u
*dfs-bicomp-num
*) (gethash w
*dfs-bicomp-num
*))
1443 (push `(,w
,u
) *dfs-bicomp-edges
*))
1444 (if (= 0 (gethash u
*dfs-bicomp-num
*))
1446 (dfs-bicomponents gr u
)
1447 (if (>= (gethash u
*dfs-bicomp-low-pt
*)
1448 (gethash w
*dfs-bicomp-num
*))
1449 (let ((e 0) (comp ()))
1451 ((equal e
`(,w
,u
)))
1452 (setq e
(pop *dfs-bicomp-edges
*))
1454 (push comp
*bicomponents
*))
1455 (setf (gethash w
*dfs-bicomp-low-pt
*)
1456 (min (gethash w
*dfs-bicomp-low-pt
*)
1457 (gethash u
*dfs-bicomp-low-pt
*)))))
1458 (setf (gethash w
*dfs-bicomp-low-pt
*)
1459 (min (gethash w
*dfs-bicomp-low-pt
*)
1460 (gethash u
*dfs-bicomp-num
*))))))
1462 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1464 ;;; strong connectivity
1467 (defvar *scon-low
* nil
)
1468 (defvar *scon-dfn
* nil
)
1469 (defvar *scon-comp
* nil
)
1470 (defvar *scon-st
* nil
)
1471 (defvar *scon-vrt
* nil
)
1472 (defvar *scon-depth
* 0)
1474 (defmfun $strong_components
(gr)
1475 (require-digraph 'strong_components
1 gr
)
1476 (if (= 0 (digraph-order gr
))
1479 (setq *scon-low
* (make-hash-table))
1480 (setq *scon-dfn
* (make-hash-table))
1481 (setq *scon-comp
* ())
1483 (setq *scon-vrt
* (digraph-vertices gr
))
1484 (loop while
(not (null *scon-vrt
*)) do
1485 (setq *scon-depth
* 0)
1486 (dfs-strong-components gr
(first *scon-vrt
*))
1487 (dolist (c *scon-comp
*)
1489 (setq *scon-comp
* ()))
1490 `((mlist simp
) ,@res
))))
1492 (defmfun $is_sconnected
(gr)
1493 (require-digraph 'strong_components
1 gr
)
1494 (eql ($length
($strong_components gr
)) 1))
1496 (defun dfs-strong-components (gr v
)
1498 (setf (gethash v
*scon-dfn
*) *scon-depth
*)
1499 (setf (gethash v
*scon-low
*) *scon-depth
*)
1500 (setf *scon-vrt
* (remove v
*scon-vrt
* :count
1))
1502 (dolist (u (neighbors v gr
))
1503 (if (gethash u
*scon-dfn
*)
1504 (when (and (< (gethash u
*scon-dfn
*) (gethash v
*scon-dfn
*))
1505 (member u
*scon-st
*))
1506 (setf (gethash v
*scon-low
*)
1507 (min (gethash v
*scon-low
*)
1508 (gethash u
*scon-dfn
*))))
1510 (dfs-strong-components gr u
)
1511 (setf (gethash v
*scon-low
*)
1512 (min (gethash v
*scon-low
*)
1513 (gethash u
*scon-low
*))))))
1514 (when (= (gethash v
*scon-low
*) (gethash v
*scon-dfn
*))
1515 (let ((x (pop *scon-st
*))
1517 (loop while
(not (= x v
)) do
1519 (setq x
(pop *scon-st
*)))
1521 (setq *scon-comp
* (cons `((mlist simp
) ,@comp
) *scon-comp
*)))))
1523 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1525 ;;; topological sorting
1528 (defmfun $topological_sort
(dag)
1529 (require-digraph 'topological_sort
1 dag
)
1530 (let ((in-degrees (make-hash-table))
1532 (n ($graph_size dag
))
1534 (dolist (v (vertices dag
))
1535 (setf (gethash v in-degrees
) 0))
1536 (dolist (e (edges dag
))
1537 (incf (gethash (second e
) in-degrees
)))
1538 (dolist (v (vertices dag
))
1539 (when (= (gethash v in-degrees
) 0)
1541 (loop while
(> (length q
) 0) do
1544 (dolist (u (out-neighbors v dag
))
1545 (decf (gethash u in-degrees
))
1547 (when (= (gethash u in-degrees
) 0)
1550 `((mlist simp
) ,@(reverse s
))
1553 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1555 ;;; max_flow (augmenting paths)
1558 (defmfun $max_flow
(net source sink
)
1559 (require-digraph 'max_flow
1 net
)
1560 (require-vertex 'max_flow
2 source
)
1561 (require-vertex 'max_flow
3 sink
)
1562 (require-vertex-in-graph 'max_flow source net
)
1563 (require-vertex-in-graph 'max_flow sink net
)
1565 ((d (make-hash-table)) (active ()) (lbls (make-hash-table))
1566 (flow (make-hash-table :test
#'equal
)) (val 0)
1568 (dolist (e (digraph-edges net
))
1569 (setf (gethash e flow
) 0))
1570 (dolist (v (digraph-vertices net
))
1571 (setf (gethash v d
) '$inf
))
1572 (setf (gethash source lbls
) `(,source -
1 $inf
))
1573 (push source active
)
1576 (let ((v (pop active
)))
1577 (dolist (w (out-neighbors v net
))
1578 (if (and (null (gethash w lbls
))
1579 (mlsp (gethash `(,v
,w
) flow
)
1580 (or (get-edge-weight `(,v
,w
) net
) 1)))
1584 (m- (or (get-edge-weight `(,v
,w
) net
) 1)
1585 (gethash `(,v
,w
) flow
))
1587 (setf (gethash w lbls
) `(,v
1 ,(gethash w d
)))
1589 (dolist (w (in-neighbors v net
))
1590 (if (and (null (gethash w lbls
))
1591 (mgrp (gethash `(,w
,v
) flow
) 0))
1593 (setf (gethash w d
) (mfuncall '$min
1594 (gethash `(,w
,v
) flow
)
1596 (setf (gethash w lbls
) `(,v -
1 ,(gethash w d
)))
1598 (if (gethash sink lbls
)
1599 (let ((dd (third (gethash sink lbls
))) (w sink
))
1600 (setq val
(m+ dd val
))
1603 (let ((v1 (first (gethash w lbls
)))
1604 (vl (second (gethash w lbls
))))
1606 (setf (gethash `(,v1
,w
) flow
)
1607 (m+ (gethash `(,v1
,w
) flow
) dd
))
1608 (setf (gethash `(,w
,v1
) flow
)
1609 (m- (gethash `(,w
,v1
) flow
) dd
)))
1611 (setq lbls
(make-hash-table))
1612 (setf (gethash source lbls
) `(,source -
1 $inf
))
1613 (dolist (v1 (digraph-vertices net
))
1614 (setf (gethash v1 d
) '$inf
))
1615 (setq active
`(,source
))))))
1616 (let ((max-flow ()))
1617 (dolist (e (digraph-edges net
))
1618 (push `((mlist simp
) ((mlist simp
) ,@e
)
1619 ,(gethash e flow
)) max-flow
))
1620 `((mlist simp
) ,val
((mlist simp
) ,@max-flow
)))))
1622 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1627 (defmfun $shortest_path
(u v g
)
1628 (require-graph-or-digraph 'shortest_path
3 g
)
1629 (require-vertex 'shortest_path
1 u
)
1630 (require-vertex 'shortest_path
2 v
)
1631 (require-vertex-in-graph 'shortest_path v g
)
1632 (require-vertex-in-graph 'shortest_path u g
)
1633 (let ((active (make-hash-table)) (visited (make-hash-table)) (previous (make-hash-table)))
1634 (setf (gethash u active
) t
)
1636 ((or (= 0 (hash-table-count active
)) (gethash v visited
)))
1637 (let ((next (make-hash-table)))
1638 (loop for w being the hash-keys of active do
1639 (setf (gethash w visited
) t
)
1640 (dolist (x (neighbors w g
))
1641 (unless (or (gethash x active
) (gethash x visited
) (gethash x next
))
1642 (setf (gethash x previous
) w
)
1643 (setf (gethash x next
) t
))))
1644 (setq active next
)))
1645 (if (gethash v visited
)
1646 (let ((path (list v
)))
1649 (setq x
(gethash x previous
))
1651 `((mlist simp
) ,@path
))
1654 (defmfun $vertex_distance
(u v g
)
1655 (require-graph-or-digraph 'shortest_path
3 g
)
1656 (require-vertex 'shortest_path
1 u
)
1657 (require-vertex 'shortest_path
2 v
)
1658 (require-vertex-in-graph 'shortest_path v g
)
1659 (require-vertex-in-graph 'shortest_path u g
)
1660 (let ((d ($length
($shortest_path u v g
))))
1665 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1667 ;;; minimum spanning tree
1670 (defun edge-weight-1 (e gr
)
1671 (cond ((gethash e
(graph-edge-weights gr
)))
1674 (defun graph-edges-with-weights (gr)
1675 (let ((edges (graph-edges gr
)) (edges-with-weights ()))
1677 (push `(,e
,(edge-weight-1 e gr
)) edges-with-weights
))
1678 edges-with-weights
))
1680 (defun edges-by-weights (gr)
1681 (let ((edges (graph-edges-with-weights gr
)))
1682 (sort edges
#'(lambda (u v
) (mlsp (second u
) (second v
))))))
1684 (defun in-same-part (u v p
)
1685 (let ((up u
) (vp v
))
1687 ((= up
(gethash up p
)))
1688 (let ((up1 (gethash up p
)))
1689 (setf (gethash up p
) (gethash up1 p
)))
1690 (setq up
(gethash up p
)))
1692 ((= vp
(gethash vp p
)))
1693 (let ((vp1 (gethash vp p
)))
1694 (setf (gethash vp p
) (gethash vp1 p
)))
1695 (setq vp
(gethash vp p
)))
1698 (defun join-parts (u v p
)
1699 (let ((up u
) (vp v
))
1701 ((= up
(gethash up p
)))
1702 (setq up
(gethash up p
)))
1704 ((= vp
(gethash vp p
)))
1705 (setq vp
(gethash vp p
)))
1706 (setf (gethash up p
) (gethash vp p
))))
1708 (defmfun $minimum_spanning_tree
(gr)
1709 (require-graph 'minimum_spanning_tree
1 gr
)
1710 (let ((edges (edges-by-weights gr
)) (tr (make-graph))
1711 (part (make-hash-table)))
1712 (dolist (v (graph-vertices gr
))
1714 (setf (gethash v part
) v
))
1716 (let ((u (caar e
)) (v (cadar e
)))
1717 (if (not (in-same-part u v part
))
1719 (add-edge `(,u
,v
) tr
)
1720 (join-parts u v part
)))))
1723 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1728 (defvar *hamilton-cycle
* ())
1730 (defmfun $hamilton_cycle
(gr)
1731 (require-graph 'hamilton_cycle
1 gr
)
1732 (let (*hamilton-cycle
* (*v0
* ($first_vertex gr
)))
1733 (declare (special *v0
*))
1734 (unless ($is_biconnected gr
)
1735 (return-from $hamilton_cycle
`((mlist simp
))))
1736 (hamilton-cycle (list *v0
*) gr
)
1737 `((mlist simp
) ,@(reverse *hamilton-cycle
*))))
1739 (defun hamilton-cycle (part gr
)
1740 (declare (special *v0
*))
1741 (unless *hamilton-cycle
*
1742 (if (= (length part
) (if (graph-p gr
)
1744 (digraph-order gr
)))
1745 (if (member (car (last part
)) (neighbors (first part
) gr
))
1746 (setq *hamilton-cycle
* (append (last part
) part
))))
1747 (dolist (v (neighbors (car part
) gr
))
1748 (when (null (member v part
))
1749 (if (< (length part
) 3)
1750 (hamilton-cycle (cons v part
) gr
)
1751 (let ((gr1 ($copy_graph gr
))
1752 (in-part (rest (reverse part
))))
1753 ($remove_vertices
(cons '(mlist simp
) in-part
) gr1
)
1754 (unless (member v
(neighbors *v0
* gr
))
1755 ($add_edge
`((mlist simp
) ,v
,*v0
*) gr1
))
1756 (when ($is_biconnected gr1
)
1757 (hamilton-cycle (cons v part
) gr
))))))))
1759 (defmfun $hamilton_path
(gr)
1760 (require-graph 'hamilton_path
1 gr
)
1761 ;; first check if there exists a HC
1762 (let ((hc ($hamilton_cycle gr
)))
1764 (return-from $hamilton_path
($rest hc
))))
1765 ;; check with all non-edges
1766 (let ((grc ($complement_graph gr
)))
1767 (dolist (v (vertices gr
))
1768 (dolist (u (neighbors v grc
))
1773 (declare (special *v0
*))
1774 (hamilton-cycle part gr
)
1775 (when *hamilton-cycle
*
1776 (return-from $hamilton_path
(cons '(mlist simp
) (rest (reverse *hamilton-cycle
*))))))))))
1779 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1784 (defvar *maximum-clique
* ())
1786 (defmfun $vertices_by_degree
(gr)
1787 (require-graph 'vertices_by_degrees
1 gr
)
1788 (cons '(mlist simp
) (vertices-by-degrees gr
)))
1790 (defun vertices-by-degrees (gr)
1792 (dolist (v (vertices gr
))
1793 (push `(,v
,(length (neighbors v gr
))) vrt
))
1794 (setq vrt
(sort vrt
#'(lambda (u v
) (> (second u
) (second v
)))))
1795 (mapcar #'first vrt
)))
1797 (defun greedy-color (gr)
1798 (let ((coloring (make-hash-table))
1799 (available-colors (make-hash-table)) (tmp ()))
1800 (dotimes (i (graph-order gr
))
1802 (setq tmp
(reverse tmp
))
1803 (dolist (v (graph-vertices gr
))
1804 (setf (gethash v available-colors
) (copy-tree tmp
)))
1805 (dolist (v (vertices-by-degrees gr
))
1806 (let ((c (car (gethash v available-colors
))))
1807 (setf (gethash v coloring
) c
)
1808 (dolist (u (neighbors v gr
))
1809 (setf (gethash u available-colors
)
1810 (remove c
(gethash u available-colors
) :count
1)))))
1813 (defmfun $max_clique
(gr)
1814 (require-graph 'max_clique
1 gr
)
1815 (setq *maximum-clique
* ())
1816 (let ((v) (coloring) (h ($copy_graph gr
)))
1817 (do () ((or (>= (length *maximum-clique
*) (graph-order h
))
1818 (> (length *maximum-clique
*) ($first
($max_degree h
)))))
1819 ; (print *maximum-clique*)
1820 ; (print ($max_degree h))
1821 (setq coloring
(greedy-color h
))
1822 (setq v
($second
($max_degree h
)))
1823 (extend-clique `(,v
) (neighbors v h
) coloring h
)
1824 (remove-vertex v h
)))
1825 `((mlist simp
) ,@(sort *maximum-clique
* #'<)))
1827 (defmfun $min_vertex_cover
(gr)
1828 (require-graph 'min_vertex_cover
1 gr
)
1829 (let ((bipart ($bipartition gr
)))
1830 (if (null (cdr bipart
))
1832 (mc (cdr ($max_clique
($complement_graph gr
)))))
1833 (loop for v in
(vertices gr
) do
1834 (unless (member v mc
)
1835 (setq vc
(cons v vc
))))
1836 `((mlist simp
) ,@vc
))
1837 (maximum-matching-bipartite gr
(cadr bipart
) (caddr bipart
) t
))))
1839 (defmfun $max_independent_set
(gr)
1840 (require-graph 'max_independent_set
1 gr
)
1841 (if ($is_bipartite gr
)
1843 (vc (cdr ($min_vertex_cover gr
))))
1844 (loop for v in
(vertices gr
) do
1845 (unless (member v vc
)
1846 (setq mis
(cons v mis
))))
1847 `((mlist simp
) ,@mis
))
1848 ($max_clique
($complement_graph gr
))))
1850 (defun extend-clique (clique neigh coloring gr
)
1851 (if (= (length neigh
) 0)
1852 ;; did we get to a maximal clique
1853 (if (> (length clique
) (length *maximum-clique
*))
1855 (setq *maximum-clique
* clique
)
1856 (return-from extend-clique
)))
1857 ;; can we do better?
1860 (if (not (member (gethash x coloring
) colors
))
1861 (push (gethash x coloring
) colors
)))
1862 (if (> (+ (length clique
) (length colors
)) (length *maximum-clique
*))
1864 (do () ((= (length neigh
) 0))
1865 (let* ((x (first neigh
)) (new-clique (cons x clique
))
1868 (if (is-edge-in-graph `(,(min x y
) ,(max x y
)) gr
)
1869 (push y new-neigh
)))
1870 (extend-clique new-clique new-neigh coloring gr
)
1871 (setq neigh
(remove x neigh
))))))))
1873 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1878 (defmfun $vertex_coloring
(g)
1879 (require-graph 'vertex_coloring
1 g
)
1880 (let ((col (dsatur g
)) (res ()) (chnumber 0))
1881 (dolist (v (vertices g
))
1882 (push `((mlist simp
) ,v
,(gethash v col
)) res
)
1883 (setq chnumber
(max chnumber
(gethash v col
))))
1884 `((mlist simp
) ,chnumber
((mlist simp
) ,@res
))))
1886 (defmfun $chromatic_number
(g)
1887 (require-graph 'chromatic_number
1 g
)
1888 ($first
($vertex_coloring g
)))
1890 (defmfun $edge_coloring
(gr)
1891 (require-graph 'edge_coloring
1 gr
)
1892 (let* ((edge-list (get-canonical-names (graph-edges gr
)))
1894 (g ($empty_graph n
)))
1899 (let ((e (car (rassoc i edge-list
))) (f (car (rassoc j edge-list
))))
1901 (or (member (first e
) f
) (member (second e
) f
))
1902 (add-edge `(,i
,j
) g
)))))
1903 (let ((coloring (dsatur g
))
1907 (push `((mlist simp
) ((mlist simp
) ,@(car (rassoc i edge-list
)))
1908 ,(gethash i coloring
)) res
)
1909 (setq ch-index
(max ch-index
(gethash i coloring
))))
1910 `((mlist simp
) ,ch-index
((mlist simp
) ,@res
)))))
1912 (defmfun $chromatic_index
(g)
1913 (require-graph 'chromatic_index
1 g
)
1914 ($first
($vertex_coloring
($line_graph g
))))
1917 (when (< (length (vertices g
)) 2)
1918 (let ((col (make-hash-table)))
1919 (dolist (v (vertices g
))
1920 (setf (gethash v col
) 1))
1921 (return-from dsatur col
)))
1923 (vsize (length (vertices g
)))
1924 (opt-chnumber (1+ vsize
)) (back nil
)
1929 (clique (greedy-clique g
))
1930 (clique-size (length clique
))
1932 (A (make-array vsize
))
1933 (F (make-hash-table))
1934 (f-opt (make-hash-table))
1935 (number-of-used-colors (make-hash-table :test
#'equal
))
1936 (dsat (make-hash-table))
1937 (uncolored (make-hash-table)))
1940 ;(format t "~%Preparing data")
1943 (setf (gethash v F
) (1+ i
))
1945 (dolist (v (vertices g
))
1946 (setf (gethash v dsat
) 0)
1947 (setf (gethash v uncolored
) (length (neighbors v g
)))
1948 (if (not (member v clique
))
1952 (setf (gethash v F
) 0))))
1954 (dolist (u (neighbors v g
))
1955 (decf (gethash u uncolored
))
1956 (setf (gethash `(,u
,(gethash v F
)) number-of-used-colors
) 1)
1957 (incf (gethash u dsat
))))
1959 ;(format t "~%Clique size: ~d" (length clique))
1960 ;(format t "~%Clique: ~d" clique)
1962 ;(format t "~%Starting with: ~d (~d)" start (aref A start))
1963 (do ((i start
(1+ i
))) ((or (= i vsize
) stop
))
1965 ;; Choose new vertex x
1969 (setq x
(aref A xindex
)))
1970 (let ((mdsat -
1) (munc -
1))
1971 (do ((j i
(1+ j
))) ((= j vsize
))
1972 (if (or (> (gethash (aref A j
) dsat
) mdsat
)
1973 (and (= (gethash (aref A j
) dsat
) mdsat
)
1974 (> (gethash (aref A j
) uncolored
) munc
)))
1978 (setq mdsat
(gethash x dsat
))
1979 (setq munc
(gethash x uncolored
)))))))
1980 ;(format t "~%New vertex: ~d" x)
1982 ;; Choose free color
1987 (setq k
(1+ (gethash x F
))))
1989 (do ((j k
(1+ j
))) ((or (>= j opt-chnumber
) (> free-color
0)))
1990 (if (= 0 (gethash `(,x
,j
) number-of-used-colors
0))
1991 (setq free-color j
)))
1992 ;(format t "~%New color: ~d" free-color)
1994 (if (> free-color
0)
1997 (setf (gethash x F
) free-color
)
1998 ;; Update dsat index
1999 (dolist (u (neighbors x g
))
2000 (incf (gethash `(,u
,free-color
) number-of-used-colors
0))
2001 (if (= 1 (gethash `(,u
,free-color
) number-of-used-colors
0))
2002 (incf (gethash u dsat
)))
2003 (decf (gethash u uncolored
)))
2005 (rotatef (aref A i
) (aref A xindex
)))
2006 ;; Unable to extend coloring - backtrack
2014 ;; We have a backtrack step
2016 (if (< start clique-size
)
2017 (return-from dsatur f-opt
))
2018 (setq x
(aref A start
))
2019 (setq k
(gethash x F
))
2020 ;; Delete the color of x
2021 (dolist (v (neighbors x g
))
2022 (decf (gethash `(,v
,k
) number-of-used-colors
))
2023 (incf (gethash v uncolored
))
2024 (if (= 0 (gethash `(,v
,k
) number-of-used-colors
))
2025 (decf (gethash v dsat
)))))
2026 ;; We have a coloring!
2028 ;; Save new optimal coloring
2029 (setq opt-chnumber
0)
2030 (dolist (v (vertices g
))
2031 (setf (gethash v f-opt
) (gethash v F
))
2032 (setq opt-chnumber
(max opt-chnumber
(gethash v F
))))
2033 ;(format t "~%Found new coloring: ~d" opt-chnumber)
2036 (do ((i 0 (1+ i
))) ((> start -
1))
2037 (if (= opt-chnumber
(gethash (aref A i
) f-opt
))
2039 (setq start
(1- i
)))))
2041 (if (or (< start clique-size
)
2042 (= opt-chnumber clique-size
))
2043 (return-from dsatur f-opt
))
2044 ;; Delete colors from start
2045 (do ((i start
(1+ i
))) ((= i vsize
))
2046 (dolist (v (neighbors (aref A i
) g
))
2047 (decf (gethash `(,v
,(gethash (aref A i
) F
))
2048 number-of-used-colors
))
2049 (incf (gethash v uncolored
))
2050 (if (= 0 (gethash `(,v
,(gethash (aref A i
) F
))
2051 number-of-used-colors
))
2052 (decf (gethash v dsat
)))))
2055 (defun greedy-clique (g)
2057 (dolist (v (vertices g
))
2058 (let ((tmp-clique (extend-greedy-clique `(,v
) (neighbors v g
) g
)))
2059 (if (> (length tmp-clique
) (length clique
))
2060 (setq clique tmp-clique
))))
2063 (defun extend-greedy-clique (clique neigh g
)
2064 (if (= 0 (length neigh
))
2065 (return-from extend-greedy-clique clique
))
2066 (if (= 1 (length neigh
))
2067 (return-from extend-greedy-clique
(cons (car neigh
) clique
)))
2068 (let ((u nil
) (new-neigh ()))
2070 (let ((tmp-neigh (copy-tree neigh
)))
2072 (if (and (not (member w
(neighbors v g
))))
2073 (setq tmp-neigh
(remove w tmp-neigh
))))
2074 (if (>= (length tmp-neigh
) (length new-neigh
))
2077 (setq new-neigh tmp-neigh
)))))
2079 (extend-greedy-clique (cons u clique
) new-neigh g
)
2084 ;; Expose lisp hashtable
2088 (defmfun $hash_table
()
2089 (make-hash-table :test
#'equal
))
2091 (defmfun $get_hash
(elt ht
&optional default
)
2092 (unless (hash-table-p ht
)
2093 ($error
"Second argument to `get_hash' is not a hash table!"))
2094 (gethash elt ht default
))
2096 (defmfun $set_hash
(elt ht value
)
2097 (unless (hash-table-p ht
)
2098 ($error
"Second argument to `set_hash' is not a hash table!"))
2099 (setf (gethash elt ht
) value
)
2102 (defmfun $hash_table_data
(ht)
2103 (unless (hash-table-p ht
)
2104 ($error
"First argument to `hash_table_info' is not a hash table!"))
2108 (setq res
(cons `((marrow simp
) ,key
,val
) res
)))
2110 (cons '(mlist simp
) res
)))
2112 ;;;;;;;;;;;;;;;;;;;;;;;;;
2114 ;; This function is needed for draw_graph (get the temporary file to write in)
2116 ;;;;;;;;;;;;;;;;;;;;;;;;;
2118 (defmfun $temp_filename
(file)
2119 (unless (stringp file
)
2120 ($error
"Argument to `temp_filename' is not a string"))
2121 (plot-temp-file file
))
2123 (defmfun $read_string
(str)
2124 (unless (stringp str
)
2125 ($error
"Argument to `read_string' is not a string"))
2126 (let ((num (read-from-string str
)))
2127 (if (numberp num
) num str
)))