| (in-package #:metabang.graph) |
|
|
| |
|
|
| (defstruct (vertex-datum (:conc-name node-) (:type list)) |
| (color nil) |
| (depth most-positive-fixnum) |
| (parent nil)) |
|
|
|
|
| (defmethod initialize-vertex-data ((graph basic-graph)) |
| (let ((vertex-data (make-container 'simple-associative-container))) |
| (iterate-vertexes graph (lambda (v) |
| (setf (item-at vertex-data v) |
| (make-vertex-datum :color :white)))) |
| (values vertex-data))) |
|
|
| |
|
|
| (defmethod breadth-first-visitor ((graph basic-graph) (source t) fn) |
| (breadth-first-visitor graph (find-vertex graph source) fn)) |
|
|
|
|
| (defmethod breadth-first-visitor ((graph basic-graph) (source basic-vertex) fn) |
| |
| (let ((vertex-data (initialize-vertex-data graph)) |
| (queue (make-container 'basic-queue))) |
|
|
| (let ((source-datum (item-at vertex-data source))) |
| (setf (node-color source-datum) :grey |
| (node-depth source-datum) 0) |
| (enqueue queue source) |
|
|
| (loop until (empty-p queue) do |
| (let* ((current-vertex (first-item queue)) |
| (current (item-at vertex-data current-vertex))) |
| |
| (iterate-children current-vertex |
| (lambda (child-vertex) |
| |
| (let ((child (item-at vertex-data child-vertex))) |
| (when (eq (node-color child) :white) |
| (setf (node-color child) :grey |
| (node-depth child) (1+ (node-depth current)) |
| (node-parent child) current-vertex) |
| (enqueue queue child-vertex))))) |
|
|
| (dequeue queue) |
| (setf (node-color current) :black) |
| (funcall fn current-vertex))) |
|
|
| vertex-data))) |
|
|
|
|
| (defmethod breadth-first-search-graph ((graph basic-graph) (source t)) |
| (breadth-first-search-graph graph (find-vertex graph source))) |
|
|
|
|
| (defmethod breadth-first-search-graph ((graph basic-graph) (source basic-vertex)) |
| |
| (let ((vertex-data (initialize-vertex-data graph)) |
| (queue (make-container 'basic-queue))) |
|
|
| (let ((source-datum (item-at vertex-data source))) |
| (setf (node-color source-datum) :grey |
| (node-depth source-datum) 0) |
| (enqueue queue source) |
|
|
| (loop until (empty-p queue) do |
| (let* ((current-vertex (first-item queue)) |
| (current (item-at vertex-data current-vertex))) |
| |
| (iterate-children current-vertex |
| (lambda (child-vertex) |
| |
| (let ((child (item-at vertex-data child-vertex))) |
| (when (eq (node-color child) :white) |
| (setf (node-color child) :grey |
| (node-depth child) (1+ (node-depth current)) |
| (node-parent child) current-vertex) |
| (enqueue queue child-vertex))))) |
|
|
| (dequeue queue) |
| (setf (node-color current) :black))) |
|
|
| vertex-data))) |
|
|
| |
|
|
| #+NotYet |
| (defmethod single-source-shortest-paths ((graph basic-graph)) |
| (let ((vertex-data (initialize-vertex-data graph)) |
| (queue (make-container 'priority-queue-on-container 'binary-search-tree))) |
| (let ((source-datum (item-at vertex-data source))) |
| (setf (node-depth source-datum) 0)) |
| )) |
|
|
| |
|
|
| (defmethod connected-components ((graph basic-graph)) |
| (let ((union (make-container 'union-find-container))) |
| (iterate-vertexes |
| graph |
| (lambda (v) (insert-item union v))) |
| (iterate-edges |
| graph |
| (lambda (e) |
| (let ((node-1 (representative-node union (vertex-1 e))) |
| (node-2 (representative-node union (vertex-2 e)))) |
| (unless (eq (find-set node-1) (find-set node-2)) |
| (graft-nodes node-1 node-2))))) |
| (iterate-elements union 'find-set) |
| union)) |
|
|
|
|
| (defmethod connected-component-count ((graph basic-graph)) |
| |
| (size |
| (remove-duplicates |
| (collect-elements |
| (connected-components graph) |
| :transform #'parent))) |
|
|
| #+Fails |
| |
| |
| (size |
| (collect-elements |
| (make-iterator (connected-components graph) :unique t :transform #'parent)))) |
|
|
| (defmethod find-connected-components ((graph basic-graph)) |
| (collect-elements |
| (make-iterator (connected-components graph) :unique t :transform #'parent) |
| :transform |
| (lambda (component) |
| (subgraph-containing graph (element component) |
| :depth most-positive-fixnum)))) |
|
|
| #+Alternate |
| (defmethod find-connected-components ((graph basic-graph)) |
| (let ((result nil) |
| (found-elements (make-container 'simple-associative-container))) |
| (iterate-elements |
| (connected-components graph) |
| (lambda (component) |
| (let ((element (element (parent component)))) |
| (unless (item-at found-elements element) |
| (setf (item-at found-elements element) t) |
| (push (subgraph-containing graph (element component) |
| most-positive-fixnum) |
| result))))) |
|
|
| result)) |
|
|
|
|
|
|
| |
|
|
| (defmethod mst-find-set ((vertex basic-vertex)) |
| #+ignore |
| (unless (previous-node vertex) |
| (return-from mst-find-set nil)) |
| (unless (eq vertex (previous-node vertex)) |
| (setf (previous-node vertex) (mst-find-set (previous-node vertex)))) |
| (previous-node vertex)) |
|
|
|
|
| (defmethod mst-make-set ((vertex basic-vertex)) |
| (setf (previous-node vertex) vertex |
| (rank vertex) 0)) |
|
|
|
|
| (defmethod mst-tree-union ((v1 basic-vertex) (v2 basic-vertex)) |
| (mst-link (mst-find-set v1) (mst-find-set v2))) |
|
|
|
|
| (defmethod mst-link ((v1 basic-vertex) (v2 basic-vertex)) |
| (cond ((> (rank v1) (rank v2)) |
| (setf (previous-node v2) v1)) |
| (t (setf (previous-node v1) v2) |
| (when (= (rank v1) (rank v2)) |
| (incf (rank v2)))))) |
|
|
| |
| |
| |
|
|
| (defmethod add-edges-to-graph ((graph basic-graph) (edges list) |
| &key (if-duplicate-do :ignore)) |
| (iterate-elements |
| edges |
| (lambda (edge) |
| (let ((v1 (element (source-vertex edge))) |
| (v2 (element (target-vertex edge)))) |
| (add-edge-between-vertexes |
| graph v1 v2 :edge-class (type-of edge) |
| :edge-type (if (directed-edge-p edge) |
| :directed |
| :undirected) |
| :value (value edge) |
| :edge-id (edge-id edge) |
| :element (element edge) |
| :tag (tag edge) |
| :graph graph |
| :color (color edge) |
| :if-duplicate-do if-duplicate-do)))) |
| graph) |
|
|
|
|
| (defmethod edge-lessp-by-weight ((e1 basic-edge) (e2 basic-edge)) |
| (< (weight e1) (weight e2))) |
|
|
| |
|
|
|
|
| (defmethod minimum-spanning-tree ((graph basic-graph) |
| &key |
| (edge-sorter #'edge-lessp-by-weight)) |
| (let ((result nil)) |
| (iterate-vertexes |
| graph |
| (lambda (v) |
| (mst-make-set v))) |
|
|
| (loop for edge in (sort (edges graph) edge-sorter) do |
| (let ((v1 (source-vertex edge)) |
| (v2 (target-vertex edge))) |
|
|
| (unless (eq (mst-find-set v1) |
| (mst-find-set v2)) |
| (push edge result) |
| (mst-tree-union v1 v2))) |
| finally |
| (return |
| (cond ((= (length result) (- (length (vertexes graph)) 1)) |
| (values t result)) |
| (t (values nil result))))))) |
|
|
|
|
| #+ignore |
| (defmethod minimum-spanning-tree ((vertex-list list) |
| &key |
| (edge-sorter #'edge-lessp-by-weight)) |
| (let ((result nil) |
| (v-edges (remove-duplicates |
| (flatten (mapcar #'edges vertex-list)) :test #'eq))) |
|
|
| (iterate-container |
| vertex-list |
| (lambda (v) |
| (mst-make-set v))) |
|
|
| (loop for edge in (sort v-edges edge-sorter) do |
| (let ((v1 (source-vertex edge)) |
| (v2 (target-vertex edge)) |
| (v1-set (mst-find-set v1)) |
| (v2-set (mst-find-set v2))) |
|
|
| (when (or (not v1-set) |
| (not v2-set)) |
| (return-from minimum-spanning-tree nil)) |
|
|
|
|
| (unless (eq (mst-find-set v1) |
| (mst-find-set v2)) |
| (push edge result) |
| (mst-tree-union v1 v2))) |
| finally |
| (return |
| (cond ((= (length result) (- (length vertex-list) 1)) |
| (values t result)) |
| (t (values nil result))))))) |
|
|
| |
|
|
| (defmethod connected-graph-p ((graph basic-graph) &key |
| (edge-sorter 'edge-lessp-by-weight)) |
| (minimum-spanning-tree graph :edge-sorter edge-sorter)) |
|
|
|
|
|
|
| #+test |
| (let ((g (make-container 'graph-container))) |
| (add-edge-between-vertexes g :v :y :edge-type :directed) |
| (add-edge-between-vertexes g :u :x :edge-type :directed) |
| (add-edge-between-vertexes g :x :v :edge-type :directed) |
| (add-edge-between-vertexes g :u :v :edge-type :directed) |
| (add-edge-between-vertexes g :y :x :edge-type :directed) |
| (add-edge-between-vertexes g :w :y :edge-type :directed) |
| (add-edge-between-vertexes g :w :z :edge-type :directed) |
| (add-edge-between-vertexes g :z :z :edge-type :directed |
| :if-duplicate-do :force) |
| (minimum-spanning-tree g)) |
|
|
| |
| |
| |
|
|
| #+not-yet |
| (defmethod minimum-spanning-tree ((graph basic-graph) &key (weight 'weight)) |
| (let ((a nil) |
| (union (make-container 'union-find-container)) |
| (edges (sort (edges graph) #'< :key weight))) |
| (iterate-vertexes |
| graph (lambda (v) (insert-item union v))) |
| (dolist (edge edges) |
| (let ((node-1 (representative-node union (vertex-1 edge))) |
| (node-2 (representative-node union (vertex-2 edge)))) |
| (unless (eq (find-set node-1) (find-set node-2)) |
| (graft-nodes node-1 node-2) |
| (push edge a)))) |
|
|
| (values a))) |
|
|
|
|
| #+test |
| (loop for f in '(mst-kruskal minimum-spanning-tree-kruskal) do |
| (fluid-bind (((random-seed *random-generator*) 1)) |
| (bind ((g (generate-undirected-graph-via-vertex-probabilities |
| *random-generator* (make-instance 'graph-container :default-edge-type :directed) |
| 100 |
| #(0.8 0.2) |
| #2A((0.2 0.1) (nil 0.2)) |
| (lambda (kind count) |
| (form-keyword "H" (format nil "~2,'0D~4,'0D" kind count)))) |
| )) |
| (timeit (:report :values) |
| (loop for n from 1 to 100 do |
| (funcall f g (lambda (a b) |
| (declare (ignore a b)) |
| 0))))))) |
|
|
| |
|
|
|
|
| |
| |
| |
|
|
| |
|
|
| (defparameter *depth-first-search-timer* -1) |
|
|
| |
|
|
| #+ignore |
| (defmethod edge-lessp-by-direction ((e1 basic-edge) (e2 basic-edge)) |
| (cond ((or (every #'directed-edge-p (list e1 e2)) |
| (every #'undirected-edge-p (list e1 e2))) |
| t) |
| ((and (undirected-edge-p e1) (directed-edge-p e2)) |
| t) |
| (t nil))) |
|
|
| (defmethod edge-lessp-by-direction ((e1 basic-edge) (e2 basic-edge)) |
| (and (undirected-edge-p e1) (directed-edge-p e2))) |
|
|
|
|
| (defmethod out-edge-for-vertex-p ((edge basic-edge) (vertex basic-vertex)) |
| (cond ((and (directed-edge-p edge) |
| (eq vertex (source-vertex edge))) |
| t) |
| ((and (undirected-edge-p edge) |
| (or (eq vertex (source-vertex edge)) |
| (eq vertex (target-vertex edge)))) |
| t) |
| (t nil))) |
|
|
| |
|
|
| (defmethod dfs ((graph basic-graph) (root t) fn &key |
| (out-edge-sorter #'edge-lessp-by-direction)) |
| (dfs graph (find-vertex graph root) fn :out-edge-sorter out-edge-sorter)) |
|
|
|
|
| (defmethod dfs ((graph basic-graph) (root basic-vertex) fn &key |
| (out-edge-sorter #'edge-lessp-by-direction)) |
| (setf *depth-first-search-timer* -1) |
|
|
| (iterate-vertexes |
| graph |
| (lambda (v) |
| (setf (color v) :white |
| (previous-node v) nil |
| (discovery-time v) -1 |
| (finish-time v) -1))) |
|
|
| (iterate-edges |
| graph |
| (lambda (e) |
| (setf (color e) nil))) |
|
|
| (loop for v in (cons root (remove root (vertexes graph) :test #'eql)) |
| when (eql (color v) :white) |
| do (dfs-visit graph v fn out-edge-sorter)) |
|
|
| (values |
| (sort (copy-list (vertexes graph)) #'< :key #'finish-time) |
| graph)) |
|
|
| (defgeneric rooted-dfs (graph root fn &key out-edge-sorter) |
| (:documentation "A variant of DFS that does not visit nodes that are |
| unreachable from the ROOT.") |
| (:method ((graph basic-graph) (root t) fn &key |
| (out-edge-sorter #'edge-lessp-by-direction)) |
| (rooted-dfs graph (find-vertex graph root) fn :out-edge-sorter out-edge-sorter)) |
| (:method ((graph basic-graph) (root basic-vertex) fn &key |
| (out-edge-sorter #'edge-lessp-by-direction)) |
| (setf *depth-first-search-timer* -1) |
|
|
| (iterate-vertexes |
| graph |
| (lambda (v) |
| (setf (color v) :white |
| (previous-node v) nil |
| (discovery-time v) -1 |
| (finish-time v) -1))) |
|
|
| (iterate-edges |
| graph |
| (lambda (e) |
| (setf (color e) nil))) |
|
|
| (dfs-visit graph root fn out-edge-sorter) |
|
|
| (values |
| (sort (remove-if #'(lambda (v) (eq (color v) :white)) |
| (vertexes graph)) |
| #'< :key #'finish-time) |
| graph))) |
|
|
|
|
| (defmethod dfs-visit ((graph graph-container) (u basic-vertex) |
| fn sorter) |
|
|
|
|
| (incf *depth-first-search-timer*) |
| |
| (unless (eq (color u) :white) |
| (error "precondition for DFS-VISIT violated.")) |
| (setf (color u) :gray |
| (discovery-time u) *depth-first-search-timer*) |
| |
| |
| (funcall fn u) |
|
|
| (loop for edge in (sort (collect-elements |
| (edges u) |
| :filter (lambda (e) |
| (out-edge-for-vertex-p e u))) sorter) |
| as v = (other-vertex edge u) |
| unless (color edge) |
| do (setf (color edge) (color v)) |
| when (eql (color v) :white) |
| do |
| (setf (previous-node v) u) |
| (dfs-visit graph v fn sorter)) |
|
|
| (incf *depth-first-search-timer*) |
|
|
| (setf (color u) :black |
| (finish-time u) *depth-first-search-timer*)) |
|
|
| |
|
|
| #+test |
| (let ((g (make-container 'graph-container))) |
| (add-edge-between-vertexes g :v :y :edge-type :directed) |
| (add-edge-between-vertexes g :u :x :edge-type :directed) |
| (add-edge-between-vertexes g :x :v :edge-type :directed) |
| (add-edge-between-vertexes g :u :v :edge-type :directed) |
| (add-edge-between-vertexes g :y :x :edge-type :directed) |
| (add-edge-between-vertexes g :w :y :edge-type :directed) |
| (add-edge-between-vertexes g :w :z :edge-type :directed) |
| (add-edge-between-vertexes g :z :z :edge-type :directed |
| :if-duplicate-do :force) |
| (assert (equal '(:X :Y :V :U :Z :W) |
| (mapcar #'element (dfs g :u #'identity))))) |
|
|
|
|
| (defmethod dfs-tree-edge-p ((edge graph-container-edge)) |
| (eql (color edge) :white)) |
|
|
|
|
| (defmethod dfs-back-edge-p ((edge graph-container-edge)) |
| (eql (color edge) :gray)) |
|
|
| |
|
|
| (defmethod dfs-forward-edge-p ((edge graph-container-edge)) |
| (warn "implementation is not correct.") |
| (unless (and (dfs-tree-edge-p edge) |
| (dfs-back-edge-p edge)) |
| (< (discovery-time (source-vertex edge)) |
| (discovery-time (target-vertex edge))))) |
|
|
| |
|
|
| (defmethod dfs-cross-edge-p ((edge graph-container-edge)) |
| (warn "implementation is not correct.") |
| (unless (and (dfs-tree-edge-p edge) |
| (dfs-back-edge-p edge)) |
| (> (discovery-time (source-vertex edge)) |
| (discovery-time (target-vertex edge))))) |
|
|
|
|
| (defmethod dfs-edge-type ((edge graph-container-edge)) |
| (cond ((dfs-tree-edge-p edge) |
| :tree) |
| ((dfs-back-edge-p edge) |
| :back) |
| ((dfs-forward-edge-p edge) |
| :forward) |
| ((dfs-cross-edge-p edge) |
| :cross) |
| (t nil))) |
|
|
| |
|
|
| |
|
|
| |
|
|
| (defmethod map-over-all-combinations-of-k-vertexes ((graph basic-graph) k fn) |
| (let* ((vertex-count (size graph)) |
| (symbols (make-list k :initial-element vertex-count)) |
| (vertexes (vertexes graph))) |
| (iterate-over-indexes |
| symbols |
| (lambda (vertex-indexes) |
| (when (apply #'< vertex-indexes) |
| (funcall fn (mapcar (lambda (vertex-index) |
| (nth-element vertexes vertex-index)) |
| vertex-indexes))))))) |
|
|
|
|
| #+test |
| (let ((result nil) |
| (g (make-container 'graph-container))) |
| (add-edge-between-vertexes g :u :v :edge-type :directed) |
| (add-edge-between-vertexes g :u :x :edge-type :directed) |
| (add-edge-between-vertexes g :x :v :edge-type :directed) |
| (add-edge-between-vertexes g :v :y :edge-type :directed) |
| (add-edge-between-vertexes g :y :x :edge-type :directed) |
| (add-edge-between-vertexes g :w :y :edge-type :directed) |
| (add-edge-between-vertexes g :w :z :edge-type :directed) |
|
|
| (map-over-all-combinations-of-k-vertexes |
| g |
| 4 |
| (lambda (vertex-list) |
| (let ((graph-from-vertexes (make-graph-from-vertexes vertex-list))) |
| (when (mst-kruskal graph-from-vertexes #'identity-sorter) |
| (push graph-from-vertexes result))))) |
| result) |
|
|
| |
| |
|
|
| (defmethod map-over-all-combinations-of-k-edges ((graph basic-graph) k fn) |
| (let* ((edge-count (edge-count graph)) |
| (symbols (make-list k :initial-element edge-count)) |
| (edges (edges graph))) |
| (print symbols) |
| (iterate-over-indexes |
| symbols |
| (lambda (edge-indexes) |
| (when (apply #'< edge-indexes) |
| (funcall fn (mapcar (lambda (edge-index) |
| (nth-element edges edge-index)) |
| edge-indexes))))))) |
|
|
|
|
| (defmethod map-over-all-combinations-of-k-edges ((vertex basic-vertex) k fn) |
| (let* ((edge-count (edge-count vertex)) |
| (symbols (make-list k :initial-element edge-count)) |
| (edges (edges vertex))) |
| |
| (iterate-over-indexes |
| symbols |
| (lambda (edge-indexes) |
| (when (apply #'< edge-indexes) |
| (funcall fn (mapcar (lambda (edge-index) |
| (nth-element edges edge-index)) |
| edge-indexes))))))) |
|
|
| #+test |
| (map-over-all-combinations-of-k-edges |
| (generate-undirected-graph-via-verex-probabilities |
| *random-generator* 'graph-container |
| 10 |
| #(0.8 0.2) |
| #2A((0.2 0.1) (nil 0.2)) |
| (lambda (kind count) |
| (form-keyword "H" (format nil "~2,'0D~4,'0D" kind count)))) |
| 2 |
| (lambda (es) |
| (format t "~%") |
| (mapc (lambda (e) |
| (format t "~A -- ~A " (element (vertex-1 e)) (element (vertex-2 e)))) |
| es))) |
|
|
|
|
|
|
|
|
|
|
| |
| |
| |