fb5ec068dd
This should cover most of the remaining linting errors. After this, I expect fewer than ten linting errors.
95 lines
2.9 KiB
EmacsLisp
95 lines
2.9 KiB
EmacsLisp
;;; graph.el --- Working with in-memory graphs -*- lexical-binding: t -*-
|
|
|
|
;; Author: William Carroll <wpcarro@gmail.com>
|
|
;; Version: 0.0.1
|
|
;; URL: https://git.wpcarro.dev/wpcarro/briefcase
|
|
;; Package-Requires: ((emacs "24.3"))
|
|
|
|
;;; Commentary:
|
|
;;
|
|
;; Remember that there are optimal three ways to model a graph:
|
|
;; 1. Edge List
|
|
;; 2. Vertex Table (a.k.a. Neighbors Table)
|
|
;; 3. Adjacency Matrix
|
|
;;
|
|
;; I may call these "Edges", "Neighbors", "Adjacencies" to avoid verbose naming.
|
|
;; For now, I'm avoiding dealing with Adjacency Matrices as I don't have an
|
|
;; immediate use-case for them. This is subject to change.
|
|
;;
|
|
;; There are also hybrid representations of graphs that combine the three
|
|
;; aforementioned models. I believe Erlang's digraph module models graphs in
|
|
;; Erlang Term Storage (i.e. ETS) this way.
|
|
;; TODO: Verify this claim.
|
|
;;
|
|
;; Graphs can be weighted or unweighted. They can also be directed or
|
|
;; undirected.
|
|
;; TODO: Create a table explaining all graph variants.
|
|
;;
|
|
;; TODO: Figure out the relationship of this module and tree.el, which should in
|
|
;; principle overlap.
|
|
|
|
;;; Code:
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; Dependencies
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(require 'prelude)
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; Library
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; For now, I'll support storing *either* neighbors or edges in the graph struct
|
|
;; as long as both aren't set, since that introduces consistency issues. I may
|
|
;; want to handle that use-case in the future, but not now.
|
|
(cl-defstruct graph neighbors edges)
|
|
|
|
;; TODO: How do you find the starting point for a topo sort?
|
|
(defun graph-sort (xs)
|
|
"Return a topological sort of XS.")
|
|
|
|
(defun graph-from-edges (xs)
|
|
"Create a graph struct from the Edge List, XS.
|
|
The user must pass in a valid Edge List since asserting on the shape of XS might
|
|
be expensive."
|
|
(make-graph :edges xs))
|
|
|
|
(defun graph-from-neighbors (xs)
|
|
"Create a graph struct from a Neighbors Table, XS.
|
|
The user must pass in a valid Neighbors Table since asserting on the shape of
|
|
XS might be expensive."
|
|
(make-graph :neighbors xs))
|
|
|
|
(defun graph-instance? (xs)
|
|
"Return t if XS is a graph struct."
|
|
(graph-p xs))
|
|
|
|
;; TODO: Model each of the mapping functions into an isomorphism.
|
|
(defun graph-edges->neighbors (xs)
|
|
"Map Edge List, XS, into a Neighbors Table."
|
|
(prelude-assert (graph-instance? xs)))
|
|
|
|
(defun graph-neighbors->edges (xs)
|
|
"Map Neighbors Table, XS, into an Edge List."
|
|
(prelude-assert (graph-instance? xs)))
|
|
|
|
;; Below are three different models of the same unweighted, directed graph.
|
|
|
|
(defvar graph-edges
|
|
'((a . b) (a . c) (a . e)
|
|
(b . c) (b . d)
|
|
(c . e)
|
|
(d . f)
|
|
(e . d) (e . f)))
|
|
|
|
(defvar graph-neighbors
|
|
((a b c e)
|
|
(b c d)
|
|
(c e)
|
|
(d f)
|
|
(e d g)
|
|
(f)))
|
|
|
|
(provide 'graph)
|
|
;;; graph.el ends here
|