{"id":280,"date":"2016-12-05T16:26:10","date_gmt":"2016-12-05T16:26:10","guid":{"rendered":"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/?p=280"},"modified":"2017-11-16T10:56:26","modified_gmt":"2017-11-16T10:56:26","slug":"an-algebra-of-graphs","status":"publish","type":"post","link":"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/an-algebra-of-graphs\/","title":{"rendered":"An algebra of graphs"},"content":{"rendered":"<p><a href=\"https:\/\/en.wikipedia.org\/wiki\/Graph_theory\">Graph theory<\/a> is my favourite topic in mathematics and computing science and in this blog post I&#8217;ll introduce <em>an algebra of graphs<\/em>\u00a0that I&#8217;ve been working on for a while. The algebra has become my go-to tool\u00a0for manipulating graphs and I hope you will find it useful too.<\/p>\n<p>The roots of this work\u00a0can be traced back to my CONCUR&#8217;09 conference submission\u00a0that was rightly rejected. I subsequently published a few application-specific papers gradually improving my understanding of the algebra. The most comprehensive description can be found\u00a0in <a href=\"http:\/\/dl.acm.org\/citation.cfm?id=2601432.2627351\">ACM TECS<\/a> (a preprint is available <a href=\"https:\/\/www.staff.ncl.ac.uk\/andrey.mokhov\/algebra.pdf\">here<\/a>). Here I&#8217;ll give a general introduction to the simplest version of the algebra of graphs and show how it can be implemented in Haskell.<\/p>\n<p><strong>Update:<\/strong>\u00a0This series of blog posts was published as a <a href=\"https:\/\/github.com\/snowleopard\/alga-paper\">functional pearl<\/a> at the Haskell Symposium 2017.<\/p>\n<p><!--more--><\/p>\n<h3>Constructing\u00a0graphs<\/h3>\n<p>Let <strong>G<\/strong> be a set of graphs whose vertices come from a fixed universe. As an example, we can think of graphs whose vertices are\u00a0positive integers.\u00a0A graph g \u2208 G can be represented by a pair <strong>(V, E)<\/strong> where V is the set of its\u00a0vertices and E\u00a0\u2286 V \u00d7 V is the set of its edges.<\/p>\n<p>The simplest possible graph is the <em>empty<\/em> graph. I\u00a0will be denoting it by\u00a0<strong>\u03b5<\/strong> in formulas and by <strong><code>empty<\/code><\/strong> in Haskell code. Hence, \u03b5 = (\u2205, \u2205) and \u03b5\u00a0\u2208 G.<\/p>\n<p>A graph with <em>a single vertex v<\/em> will be\u00a0denoted simply by <strong>v<\/strong>. For example, 1\u00a0\u2208 G is a graph with a single vertex 1, that is ({1}, \u2205). In Haskell I&#8217;ll use\u00a0<strong><code>vertex<\/code><\/strong>\u00a0to lift a given vertex to the type of graphs.<\/p>\n<p>To construct bigger\u00a0graphs from the above primitives I&#8217;ll use two binary operators\u00a0<em>overlay<\/em> and <em>connect<\/em>, denoted by\u00a0+ and\u00a0\u2192, respectively.\u00a0The overlay + of two graphs is\u00a0defined as:<\/p>\n<p style=\"text-align: center\">(V<sub>1<\/sub>, E<sub>1<\/sub>) + (V<sub>2<\/sub>, E<sub>2<\/sub>) = (V<sub>1<\/sub> \u222a V<sub>2<\/sub>, E<sub>1<\/sub> \u222a E<sub>2<\/sub>)<\/p>\n<p>In words, the overlay of two graphs is simply the union of their vertices and edges.\u00a0The definition of connect \u2192\u00a0is similar:<\/p>\n<p style=\"text-align: center\">(V<sub>1<\/sub>, E<sub>1<\/sub>) \u2192 (V<sub>2<\/sub>, E<sub>2<\/sub>) = (V<sub>1<\/sub> \u222a V<sub>2<\/sub>, E<sub>1<\/sub> \u222a E<sub>2<\/sub>\u00a0\u222a V<sub>1<\/sub> \u00d7 V<sub>2<\/sub>)<\/p>\n<p>The difference is that when we connect two graphs, we add an edge from each vertex in the left argument\u00a0to each vertex in the right argument. Here are a few examples:<\/p>\n<ul>\n<li>1 + 2 is the graph with two isolated vertices 1 and 2.<\/li>\n<li>1\u00a0\u2192 2 is the graph with a directed edge between\u00a0vertices 1 and 2.<\/li>\n<li>1\u00a0\u2192 (2 + 3) is the graph with three vertices {1, 2, 3} and two directed edges (1, 2) and (1, 3). In Haskell we can write <strong><code>connect 1 (overlay 2 3)<\/code><\/strong>.<\/li>\n<li>1\u00a0\u2192 1 is the graph\u00a0with\u00a0vertex 1 and\u00a0a <em>self-loop<\/em> (an edge going from a vertex to itself).<\/li>\n<\/ul>\n<p>The following type class expresses the above in Haskell:<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #794938\">class<\/span> <span style=\"color: #bf4f24\">Graph<\/span> <span style=\"color: #234a97\">g<\/span> <span style=\"color: #794938\">where<\/span>\r\n    <span style=\"color: #794938\">type<\/span> <span style=\"color: #811f24;font-weight: bold\">Vertex<\/span> g\r\n    <span style=\"color: #bf4f24\">empty<\/span>   <span style=\"color: #794938\">::<\/span> <span style=\"color: #234a97\">g<\/span>\r\n    <span style=\"color: #bf4f24\">vertex<\/span>  <span style=\"color: #794938\">::<\/span> <span style=\"color: #a71d5d;font-style: italic\">Vertex<\/span> <span style=\"color: #234a97\">g<\/span> <span style=\"color: #794938\">-&gt;<\/span> <span style=\"color: #234a97\">g<\/span>\r\n    <span style=\"color: #bf4f24\">overlay<\/span> <span style=\"color: #794938\">::<\/span> <span style=\"color: #234a97\">g<\/span> <span style=\"color: #794938\">-&gt;<\/span> <span style=\"color: #234a97\">g<\/span> <span style=\"color: #794938\">-&gt;<\/span> <span style=\"color: #234a97\">g<\/span>\r\n    <span style=\"color: #bf4f24\">connect<\/span> <span style=\"color: #794938\">::<\/span> <span style=\"color: #234a97\">g<\/span> <span style=\"color: #794938\">-&gt;<\/span> <span style=\"color: #234a97\">g<\/span> <span style=\"color: #794938\">-&gt;<\/span> <span style=\"color: #234a97\">g<\/span>\r\n<\/pre>\n<p>Let&#8217;s construct some graphs! A graph\u00a0that contains a given list of unconnected vertices can be constructed\u00a0as follows:<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #bf4f24\">vertices<\/span> <span style=\"color: #794938\">::<\/span> <span style=\"color: #a71d5d;font-style: italic\">Graph<\/span> <span style=\"color: #234a97\">g<\/span> <span style=\"color: #794938\">=&gt;<\/span> [<span style=\"color: #a71d5d;font-style: italic\">Vertex<\/span> <span style=\"color: #234a97\">g<\/span>] <span style=\"color: #794938\">-&gt;<\/span> <span style=\"color: #234a97\">g<\/span>\r\nvertices <span style=\"color: #794938\">=<\/span> <span style=\"color: #693a17\">foldr<\/span> overlay empty <span style=\"color: #794938\">.<\/span> <span style=\"color: #693a17\">map<\/span> vertex<\/pre>\n<p>And here is a <em>clique<\/em>\u00a0(a fully connected graph) on a given list\u00a0of vertices:<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #bf4f24\">clique<\/span> <span style=\"color: #794938\">::<\/span> <span style=\"color: #a71d5d;font-style: italic\">Graph<\/span> <span style=\"color: #234a97\">g<\/span> <span style=\"color: #794938\">=&gt;<\/span> [<span style=\"color: #a71d5d;font-style: italic\">Vertex<\/span> <span style=\"color: #234a97\">g<\/span>] <span style=\"color: #794938\">-&gt;<\/span> <span style=\"color: #234a97\">g<\/span>\r\nclique <span style=\"color: #794938\">=<\/span> <span style=\"color: #693a17\">foldr<\/span> connect empty <span style=\"color: #794938\">.<\/span> <span style=\"color: #693a17\">map<\/span> vertex<\/pre>\n<p>For example, <strong><code>clique [1..]<\/code><\/strong> is the infinite clique on all positive integers; we will call\u00a0such cliques covering the whole universe\u00a0<em>complete graphs<\/em>. We can also construct any graph given its\u00a0<em>edgelist<\/em>:<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #bf4f24\">fromEdgeList<\/span> <span style=\"color: #794938\">::<\/span> <span style=\"color: #a71d5d;font-style: italic\">Graph<\/span> <span style=\"color: #234a97\">g<\/span> <span style=\"color: #794938\">=&gt;<\/span> [(<span style=\"color: #a71d5d;font-style: italic\">Vertex<\/span> <span style=\"color: #234a97\">g<\/span>, <span style=\"color: #a71d5d;font-style: italic\">Vertex<\/span> <span style=\"color: #234a97\">g<\/span>)] <span style=\"color: #794938\">-&gt;<\/span> <span style=\"color: #234a97\">g<\/span>\r\nfromEdgeList <span style=\"color: #794938\">=<\/span> <span style=\"color: #693a17\">foldr<\/span> overlay empty <span style=\"color: #794938\">.<\/span> <span style=\"color: #693a17\">map<\/span> edge\r\n  <span style=\"color: #794938\">where<\/span>\r\n    edge (x<span style=\"color: #794938\">,<\/span> y) <span style=\"color: #794938\">=<\/span> vertex x <span style=\"color: #794938\">`connect`<\/span> vertex y<\/pre>\n<p>As we will see in the next section, graphs\u00a0satisfy a few\u00a0laws and form an algebraic structure that is very similar to a <a href=\"https:\/\/en.wikipedia.org\/wiki\/Semiring\"><em>semiring<\/em><\/a>.<\/p>\n<h3><a name=\"algebra\"><\/a>Algebraic structure<\/h3>\n<p>The structure (G, +,\u00a0\u2192,\u00a0\u03b5) introduced above satisfies many usual laws:<\/p>\n<ul>\n<li>(G, +,\u00a0\u03b5) is an idempotent commutative <a href=\"https:\/\/en.wikipedia.org\/wiki\/Monoid\">monoid<\/a><\/li>\n<li>(G, \u2192,\u00a0\u03b5) is a monoid<\/li>\n<li>\u2192 distributes over +, e.g. 1\u00a0\u2192 (2 + 3) = 1\u00a0\u2192 2 + 1\u00a0\u2192 3<\/li>\n<\/ul>\n<p>The following <em>decomposition axiom<\/em>, is the only law that makes the algebra of graphs different from a semiring:<\/p>\n<p style=\"text-align: center\">x\u00a0\u2192 y \u2192\u00a0z = x\u00a0\u2192 y + x\u00a0\u2192 z + y\u00a0\u2192 z<\/p>\n<p>Indeed, in a semiring the two operators have different\u00a0identity elements, let&#8217;s denote them \u03b5<sub>+<\/sub> and \u03b5<sub>\u2192<\/sub>, respectively. By using the decomposition axiom we can prove that they coincide:<\/p>\n<table>\n<tbody style=\"font-size: 16px\">\n<tr>\n<td style=\"text-align: right\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u03b5<sub>+ \u00a0<\/sub><\/td>\n<td>=<\/td>\n<td>\u03b5<sub>+<\/sub> \u2192 \u03b5<sub>\u2192<\/sub> \u2192 \u03b5<sub>\u2192<\/sub><\/td>\n<td>(identity of \u2192)<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>=<\/td>\n<td>\u03b5<sub>+<\/sub> \u2192 \u03b5<sub>\u2192<\/sub>\u00a0+ \u03b5<sub>+<\/sub> \u2192 \u03b5<sub>\u2192<\/sub>\u00a0+ \u03b5<sub>\u2192<\/sub> \u2192 \u03b5<sub>\u2192<\/sub><\/td>\n<td>(decomposition)<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>=<\/td>\n<td>\u03b5<sub>+<\/sub>\u00a0+ \u03b5<sub>+<\/sub>\u00a0+ \u03b5<sub>\u2192<\/sub><\/td>\n<td>(identity of \u2192)<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>=<\/td>\n<td>\u03b5<sub>\u2192<\/sub><\/td>\n<td>(identity of +)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The idempotence of + also follows from the decomposition axiom.<\/p>\n<p>The following is a minimal set of axioms that describes the graph algebra:<\/p>\n<ul>\n<li>+ is commutative and associative<\/li>\n<li>(G, \u2192,\u00a0\u03b5) is a monoid, i.e.\u00a0\u2192 is\u00a0associative and \u03b5 is the\u00a0identity element<\/li>\n<li>\u2192 distributes over +<\/li>\n<li>\u2192 can be decomposed:\u00a0x\u00a0\u2192 y \u2192\u00a0z = x\u00a0\u2192 y + x\u00a0\u2192 z + y\u00a0\u2192 z<\/li>\n<\/ul>\n<p>An exercise for the reader: prove that\u00a0\u03b5 is the identity of + from the minimal set of axioms above. This\u00a0is not entirely trivial! Also prove that + is idempotent.<\/p>\n<p>Note, to switch from directed to undirected\u00a0graphs it is sufficient to add the axiom of commutativity of\u00a0\u2192. We will explore this in <a href=\"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/graphs-a-la-carte\/\">a future blog post<\/a>.<\/p>\n<h3><del><\/del>Examples<\/h3>\n<p>Let&#8217;s look at two basic instances of the <em>Graph<\/em> type class that satisfy the laws from the previous section. The first one, called <em>Relation<\/em>, adopts\u00a0our set-based definitions for the overlay and connect operators and is therefore a <em>free<\/em> instance (i.e. it doesn&#8217;t satisfy any other laws):<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #794938\">data<\/span> <span style=\"color: #811f24;font-weight: bold\">Relation<\/span> a <span style=\"color: #794938\">=<\/span> <span style=\"color: #811f24;font-weight: bold\">Relation<\/span> { domain <span style=\"color: #794938\">::<\/span> <span style=\"color: #811f24;font-weight: bold\">Set<\/span> a<span style=\"color: #794938\">,<\/span> relation <span style=\"color: #794938\">::<\/span> <span style=\"color: #811f24;font-weight: bold\">Set<\/span> (a<span style=\"color: #794938\">,<\/span> a) }\r\n    <span style=\"color: #794938\">deriving<\/span> (<span style=\"color: #bf4f24\">Eq<\/span>, <span style=\"color: #bf4f24\">Show<\/span>)\r\n\r\n<span style=\"color: #794938\">instance<\/span> <span style=\"color: #a71d5d;font-style: italic\">Ord<\/span> <span style=\"color: #234a97\">a<\/span> <span style=\"color: #794938\">=&gt;<\/span> <span style=\"color: #a71d5d;font-style: italic\">Graph<\/span> (<span style=\"color: #a71d5d;font-style: italic\">Relation<\/span> <span style=\"color: #234a97\">a<\/span>) <span style=\"color: #794938\">where<\/span>\r\n    <span style=\"color: #794938\">type<\/span> <span style=\"color: #811f24;font-weight: bold\">Vertex<\/span> (<span style=\"color: #811f24;font-weight: bold\">Relation<\/span> a) <span style=\"color: #794938\">=<\/span> a\r\n    empty       <span style=\"color: #794938\">=<\/span> <span style=\"color: #811f24;font-weight: bold\">Relation<\/span> <span style=\"color: #811f24;font-weight: bold\">Set<\/span><span style=\"color: #794938\">.<\/span>empty <span style=\"color: #811f24;font-weight: bold\">Set<\/span><span style=\"color: #794938\">.<\/span>empty\r\n    vertex  x   <span style=\"color: #794938\">=<\/span> <span style=\"color: #811f24;font-weight: bold\">Relation<\/span> (<span style=\"color: #811f24;font-weight: bold\">Set<\/span><span style=\"color: #794938\">.<\/span>singleton x) <span style=\"color: #811f24;font-weight: bold\">Set<\/span><span style=\"color: #794938\">.<\/span>empty\r\n    overlay x y <span style=\"color: #794938\">=<\/span> <span style=\"color: #811f24;font-weight: bold\">Relation<\/span> (domain   x `<span style=\"color: #811f24;font-weight: bold\">Set<\/span><span style=\"color: #794938\">.<\/span>union` domain   y)\r\n                           (relation x `<span style=\"color: #811f24;font-weight: bold\">Set<\/span><span style=\"color: #794938\">.<\/span>union` relation y)\r\n    connect x y <span style=\"color: #794938\">=<\/span> <span style=\"color: #811f24;font-weight: bold\">Relation<\/span> (domain   x `<span style=\"color: #811f24;font-weight: bold\">Set<\/span><span style=\"color: #794938\">.<\/span>union` domain   y)\r\n                           (relation x `<span style=\"color: #811f24;font-weight: bold\">Set<\/span><span style=\"color: #794938\">.<\/span>union` relation y\r\n                            `<span style=\"color: #811f24;font-weight: bold\">Set<\/span><span style=\"color: #794938\">.<\/span>union` <span style=\"color: #811f24;font-weight: bold\">Set<\/span><span style=\"color: #794938\">.<\/span>fromDistinctAscList\r\n                            [ (a<span style=\"color: #794938\">,<\/span> b) <span style=\"color: #794938\">|<\/span> a <span style=\"color: #794938\">&lt;-<\/span> <span style=\"color: #811f24;font-weight: bold\">Set<\/span><span style=\"color: #794938\">.<\/span>elems (domain x)\r\n                                     <span style=\"color: #794938\">,<\/span> b <span style=\"color: #794938\">&lt;-<\/span> <span style=\"color: #811f24;font-weight: bold\">Set<\/span><span style=\"color: #794938\">.<\/span>elems (domain y) ])<\/pre>\n<p>Let&#8217;s also make <em>Relation<\/em> an instance of <em>Num<\/em>\u00a0type class so we can use + and * operators for convenience.<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #794938\">instance<\/span> (<span style=\"color: #a71d5d;font-style: italic\">Ord<\/span> <span style=\"color: #234a97\">a<\/span>, <span style=\"color: #a71d5d;font-style: italic\">Num<\/span> <span style=\"color: #234a97\">a<\/span>) <span style=\"color: #794938\">=&gt;<\/span> <span style=\"color: #a71d5d;font-style: italic\">Num<\/span> (<span style=\"color: #a71d5d;font-style: italic\">Relation<\/span> <span style=\"color: #234a97\">a<\/span>) <span style=\"color: #794938\">where<\/span>\r\n    <span style=\"color: #693a17\">fromInteger<\/span> <span style=\"color: #794938\">=<\/span> vertex <span style=\"color: #794938\">.<\/span> <span style=\"color: #693a17\">fromInteger<\/span>\r\n    <span style=\"color: #bf4f24\">(+)<\/span>         <span style=\"color: #794938\">=<\/span> overlay\r\n    (*)         <span style=\"color: #794938\">=<\/span> connect\r\n    <span style=\"color: #693a17\">signum<\/span>      <span style=\"color: #794938\">=<\/span> <span style=\"color: #693a17\">const<\/span> empty\r\n    <span style=\"color: #693a17\">abs<\/span>         <span style=\"color: #794938\">=<\/span> <span style=\"color: #693a17\">id<\/span>\r\n    <span style=\"color: #693a17\">negate<\/span>      <span style=\"color: #794938\">=<\/span> <span style=\"color: #693a17\">id<\/span><\/pre>\n<p>Note: the <em>Num<\/em> law\u00a0<strong><code>abs x * signum x == x<\/code><\/strong> is satisfied since x \u2192 \u03b5 = x. In fact, any <em>Graph<\/em> instance can be made a\u00a0<em>Num<\/em> instance if need be. We can now play with graphs using\u00a0interactive GHC:<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #794938\">\u03bb&gt;<\/span> <span style=\"color: #811f24;font-weight: bold\">1<\/span> * (<span style=\"color: #811f24;font-weight: bold\">2<\/span> <span style=\"color: #794938\">+<\/span> <span style=\"color: #811f24;font-weight: bold\">3<\/span>) <span style=\"color: #794938\">::<\/span> <span style=\"color: #811f24;font-weight: bold\">Relation<\/span> <span style=\"color: #811f24;font-weight: bold\">Int<\/span>\r\n<span style=\"color: #811f24;font-weight: bold\">Relation<\/span> {domain <span style=\"color: #794938\">=<\/span> fromList [<span style=\"color: #811f24;font-weight: bold\">1<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #811f24;font-weight: bold\">2<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #811f24;font-weight: bold\">3<\/span>]<span style=\"color: #794938\">,<\/span> relation <span style=\"color: #794938\">=<\/span> fromList [(<span style=\"color: #811f24;font-weight: bold\">1<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #811f24;font-weight: bold\">2<\/span>)<span style=\"color: #794938\">,<\/span>(<span style=\"color: #811f24;font-weight: bold\">1<\/span><span style=\"color: #794938\">,<\/span><span style=\"color: #811f24;font-weight: bold\">3<\/span>)]}\r\n<span style=\"color: #794938\">\u03bb&gt;<\/span> <span style=\"color: #811f24;font-weight: bold\">1<\/span> * (<span style=\"color: #811f24;font-weight: bold\">2<\/span> <span style=\"color: #794938\">+<\/span> <span style=\"color: #811f24;font-weight: bold\">3<\/span>) <span style=\"color: #794938\">+<\/span> <span style=\"color: #811f24;font-weight: bold\">2<\/span> * <span style=\"color: #811f24;font-weight: bold\">3<\/span> <span style=\"color: #794938\">==<\/span> (clique [<span style=\"color: #811f24;font-weight: bold\">1<\/span><span style=\"color: #794938\">..<\/span><span style=\"color: #811f24;font-weight: bold\">3<\/span>] <span style=\"color: #794938\">::<\/span> <span style=\"color: #811f24;font-weight: bold\">Relation<\/span> <span style=\"color: #811f24;font-weight: bold\">Int<\/span>)\r\n<span style=\"color: #b4371f\">True<\/span><\/pre>\n<p>Another simple instance can be obtained by embedding\u00a0all graph constructors into a basic algebraic datatype:<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #794938\">data<\/span> <span style=\"color: #811f24;font-weight: bold\">Basic<\/span> a <span style=\"color: #794938\">=<\/span> <span style=\"color: #811f24;font-weight: bold\">Empty<\/span>\r\n             <span style=\"color: #794938\">|<\/span> <span style=\"color: #811f24;font-weight: bold\">Vertex<\/span> a\r\n             <span style=\"color: #794938\">|<\/span> <span style=\"color: #811f24;font-weight: bold\">Overlay<\/span> (<span style=\"color: #811f24;font-weight: bold\">Basic<\/span> a) (<span style=\"color: #811f24;font-weight: bold\">Basic<\/span> a)\r\n             <span style=\"color: #794938\">|<\/span> <span style=\"color: #811f24;font-weight: bold\">Connect<\/span> (<span style=\"color: #811f24;font-weight: bold\">Basic<\/span> a) (<span style=\"color: #811f24;font-weight: bold\">Basic<\/span> a)\r\n             <span style=\"color: #794938\">deriving<\/span> <span style=\"color: #811f24;font-weight: bold\">Show<\/span>\r\n\r\n<span style=\"color: #794938\">instance<\/span> <span style=\"color: #a71d5d;font-style: italic\">Graph<\/span> (<span style=\"color: #a71d5d;font-style: italic\">Basic<\/span> <span style=\"color: #234a97\">a<\/span>) <span style=\"color: #794938\">where<\/span>\r\n    <span style=\"color: #794938\">type<\/span> <span style=\"color: #811f24;font-weight: bold\">Vertex<\/span> (<span style=\"color: #811f24;font-weight: bold\">Basic<\/span> a) <span style=\"color: #794938\">=<\/span> a\r\n    empty   <span style=\"color: #794938\">=<\/span> <span style=\"color: #811f24;font-weight: bold\">Empty<\/span>\r\n    vertex  <span style=\"color: #794938\">=<\/span> <span style=\"color: #811f24;font-weight: bold\">Vertex<\/span>\r\n    overlay <span style=\"color: #794938\">=<\/span> <span style=\"color: #811f24;font-weight: bold\">Overlay<\/span>\r\n    connect <span style=\"color: #794938\">=<\/span> <span style=\"color: #811f24;font-weight: bold\">Connect<\/span>\r\n<\/pre>\n<p>We cannot use the derived <em>Eq<\/em> instance here, because it would clearly violate the laws of the algebra, e.g. <strong><code>Overlay Empty Empty<\/code><\/strong> is structurally different from\u00a0<strong><code>Empty<\/code><\/strong>. However, we can implement\u00a0a custom <em>Eq<\/em> instance\u00a0as follows:<\/p>\n<pre style=\"background: #f9f9f9;color: #080808\"><span style=\"color: #794938\">instance<\/span> <span style=\"color: #a71d5d;font-style: italic\">Ord<\/span> <span style=\"color: #234a97\">a<\/span> <span style=\"color: #794938\">=&gt;<\/span> <span style=\"color: #a71d5d;font-style: italic\">Eq<\/span> (<span style=\"color: #a71d5d;font-style: italic\">Basic<\/span> <span style=\"color: #234a97\">a<\/span>) <span style=\"color: #794938\">where<\/span>\r\n    x <span style=\"color: #794938\">==<\/span> y <span style=\"color: #794938\">=<\/span> toRelation x <span style=\"color: #794938\">==<\/span> toRelation y\r\n      <span style=\"color: #794938\">where<\/span>\r\n        <span style=\"color: #bf4f24\">toRelation<\/span> <span style=\"color: #794938\">::<\/span> <span style=\"color: #a71d5d;font-style: italic\">Ord<\/span> <span style=\"color: #234a97\">a<\/span> <span style=\"color: #794938\">=&gt;<\/span> <span style=\"color: #a71d5d;font-style: italic\">Basic<\/span> <span style=\"color: #234a97\">a<\/span> <span style=\"color: #794938\">-&gt;<\/span> <span style=\"color: #a71d5d;font-style: italic\">Relation<\/span> <span style=\"color: #234a97\">a<\/span>\r\n        toRelation <span style=\"color: #794938\">=<\/span> foldBasic\r\n\r\n<span style=\"color: #bf4f24\">foldBasic<\/span> <span style=\"color: #794938\">::<\/span> (<span style=\"color: #a71d5d;font-style: italic\">Vertex<\/span> <span style=\"color: #234a97\">g<\/span> ~ <span style=\"color: #234a97\">a<\/span>, <span style=\"color: #a71d5d;font-style: italic\">Graph<\/span> <span style=\"color: #234a97\">g<\/span>) <span style=\"color: #794938\">=&gt;<\/span> <span style=\"color: #a71d5d;font-style: italic\">Basic<\/span> <span style=\"color: #234a97\">a<\/span> <span style=\"color: #794938\">-&gt;<\/span> <span style=\"color: #234a97\">g<\/span>\r\nfoldBasic <span style=\"color: #811f24;font-weight: bold\">Empty<\/span>         <span style=\"color: #794938\">=<\/span> empty\r\nfoldBasic (<span style=\"color: #811f24;font-weight: bold\">Vertex<\/span>  x  ) <span style=\"color: #794938\">=<\/span> vertex x\r\nfoldBasic (<span style=\"color: #811f24;font-weight: bold\">Overlay<\/span> x y) <span style=\"color: #794938\">=<\/span> overlay (foldBasic x) (foldBasic y)\r\nfoldBasic (<span style=\"color: #811f24;font-weight: bold\">Connect<\/span> x y) <span style=\"color: #794938\">=<\/span> connect (foldBasic x) (foldBasic y)<\/pre>\n<p>The <em>Basic<\/em> instance is useful because it allows to represent densely connected graphs more compactly. For example, <strong><code>clique [1..n] :: Basic Int<\/code><\/strong> has linear-size representation in memory, while\u00a0<strong><code>clique [1..n] :: Relation\u00a0Int<\/code><\/strong>\u00a0stores each edge separately and therefore takes\u00a0<em>O(n<sup>2<\/sup>)<\/em> memory. As\u00a0I will demonstrate in future blog posts, we can exploit compact graph representations for deriving algorithms that are asymptotically faster on dense graphs compared to existing graph\u00a0algorithms operating on edgelists.<\/p>\n<h3>Summary<\/h3>\n<p>I&#8217;ve been using the algebra of graphs presented above for several years in a number of different projects and found it very\u00a0useful. There are a few flavours of the algebra that I will introduce in <a href=\"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/tag\/algebra\/\">follow-up blog posts<\/a>\u00a0that allow to work with undirected graphs, transitively closed graphs (also known as <em>partial orders<\/em> or <em>dependency graphs<\/em>), graph\u00a0families, and their various combinations. All these flavours of the algebra can be obtained by extending the set of axioms.<\/p>\n<p>I am working on\u00a0a Haskell library <a href=\"https:\/\/github.com\/snowleopard\/alga\">alga<\/a> implementing the algebra of graphs and intend to release it\u00a0soon. Let me know if you have any suggestions on how to improve the above code snippets.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Graph theory is my favourite topic in mathematics and computing science and in this blog post I&#8217;ll introduce an algebra of graphs\u00a0that I&#8217;ve been working on for a while. The algebra has become my go-to tool\u00a0for manipulating graphs and I hope you will find it useful too. The roots of this work\u00a0can be traced back &hellip; <a href=\"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/an-algebra-of-graphs\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">An algebra of graphs<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1174,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,10],"tags":[13,4],"class_list":["post-280","post","type-post","status-publish","format-standard","hentry","category-coding","category-math","tag-algebra","tag-haskell"],"_links":{"self":[{"href":"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/wp-json\/wp\/v2\/posts\/280","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/wp-json\/wp\/v2\/users\/1174"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/wp-json\/wp\/v2\/comments?post=280"}],"version-history":[{"count":116,"href":"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/wp-json\/wp\/v2\/posts\/280\/revisions"}],"predecessor-version":[{"id":389,"href":"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/wp-json\/wp\/v2\/posts\/280\/revisions\/389"}],"wp:attachment":[{"href":"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/wp-json\/wp\/v2\/media?parent=280"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/wp-json\/wp\/v2\/categories?post=280"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.ncl.ac.uk\/andreymokhov\/wp-json\/wp\/v2\/tags?post=280"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}