<?xml version="1.0" encoding="UTF-8"?>
<rss  xmlns:atom="http://www.w3.org/2005/Atom" 
      xmlns:media="http://search.yahoo.com/mrss/" 
      xmlns:content="http://purl.org/rss/1.0/modules/content/" 
      xmlns:dc="http://purl.org/dc/elements/1.1/" 
      version="2.0">
<channel>
<title>AlgebraicJulia blog</title>
<link>https://blog.algebraicjulia.org/</link>
<atom:link href="https://blog.algebraicjulia.org/index.xml" rel="self" type="application/rss+xml"/>
<description>The AlgebraicJulia blog</description>
<generator>quarto-1.7.31</generator>
<lastBuildDate>Fri, 16 May 2025 00:00:00 GMT</lastBuildDate>
<item>
  <title>Catlab Refactor III: General categorical plumbing</title>
  <dc:creator>Kris Brown</dc:creator>
  <link>https://blog.algebraicjulia.org/post/2025/05/refactor3/</link>
  <description><![CDATA[ 





<blockquote class="blockquote">
<p>This is a sequel post to <a href="../../../../post/2025/02/refactor1/index.html">Catlab refactor I</a> and <a href="../../../../post/2025/02/refactor2/index.html">Catlab refactor II</a>. Check those out first!</p>
</blockquote>
<p>In this series, we are taking the major code refactor of Catlab, from <code>v0.16</code> and <code>v0.17</code>, as an opportunity to highlight some core concepts in Catlab. I also will be mentioning some places where the structure of Catlab has changed, but readers who are just concerned with the present and future of Catlab can ignore these remarks.</p>
<p>This post discusses the <code>Cats</code> module, which is intended to support working with categories in general (in contrast to specific categories, such as <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSet%7D">). This corresponds to the files <code>Categories.jl</code>, <code>FinCats.jl</code>, <code>FreeDiagrams.jl</code>, <code>Limits.jl</code>, <code>Diagrams.jl</code>, <code>CommutativeDiagrams.jl</code>, and <code>Subobjects.jl</code> in old Catlab’s <code>CategoricalAlgebra</code> module.</p>
<p>A common theme of the refactor is that interfaces (which are <em>implicit</em> in idiomatic Julia code) are being made <em>explicit</em>: in doing so, we are forced to think more clearly about what we mean when representing some mathematical concept as a data structure or operation in software. While sometimes making the interface explicit requires no substantial change to the underlying codebase beyond reorganization, at other times it leads us to additions and refinements to Catlab’s design.</p>
<section id="thcategory-versus-thcategoryexplicitsets" class="level2">
<h2 class="anchored" data-anchor-id="thcategory-versus-thcategoryexplicitsets">ThCategory versus ThCategoryExplicitSets</h2>
<p>Old Catlab had an abstract type <code>Category{Ob,Hom,Size&lt;:CatSize}</code>, where the third type parameter allowed for type dispatch to treat finite categories differently. This previous design has some odd features. Although one always has access to the Julia types of a <code>Category</code>’s objects and morphisms, one couldn’t get specific set of objects or morphisms. Consistent with this, the <em>only</em> way to build a infinite <code>Category{Ob,Hom}</code> from scratch was to construct a <code>TypeCat{Ob,Hom}</code>, but we obviously want to be able to work in categories where, e.g., the objects aren’t <em>all</em> of the terms of a particular type. This is improved upon by making a new theory:</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb1-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@theory</span> ThCategoryExplicitSets <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> ThCategory </span><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb1-2">  Set′<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE{AbsSet}</span></span>
<span id="cb1-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ob_set</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Set′</span></span>
<span id="cb1-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">hom_set</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Set′</span></span>
<span id="cb1-5"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb1-6"></span>
<span id="cb1-7">ThCategoryExplicitSets.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Meta</span>.<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@wrapper</span> Category</span></code></pre></div>
<p>Thus the new Catlab <code>Category</code> is a wrapper type for models of the theory of categories (as shown in our <a href="../../../../post/2025/02/refactor1/index.html">first post</a>) which <em>also</em> provide an explicit set for their obs and homs. Although Julia requires us, when implementing methods like <code>id</code>, to define the method for the entire input <code>Ob</code> type, we will regard such methods as only defined on elements of the <code>Ob</code> type which are elements of <code>ob_set()</code>.</p>
<p>Beyond <code>TypeCat</code> and <code>OppositeCat</code>, Catlab now has many different ways to construct a <code>Category</code>. For example, <code>CoproductCat</code> interprets a vector of categories as its coproduct:</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb2-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> CoproductCat{O,H}</span>
<span id="cb2-2">  cats<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Vector{Category}</span></span>
<span id="cb2-3">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">CoproductCat</span>(cats<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Vector{Category}</span>)</span>
<span id="cb2-4">    ΣOb, ΣHom <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SumSet</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ob_set</span>.(cats)), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SumSet</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">hom_set</span>.(cats))</span>
<span id="cb2-5">    ΣObType, ΣHomType <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> eltype[ΣOb](), eltype[ΣHom]()   </span>
<span id="cb2-6">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">new</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{ΣObType, ΣHomType}</span>(cats)</span>
<span id="cb2-7">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb2-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb2-9"></span>
<span id="cb2-10"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Base</span>.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getindex</span>(x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">CoproductCat</span>, i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> x.cats[i]</span></code></pre></div>
<p>Note above that <code>SumSet</code> is an implementation of <code>ThSet</code> which has elements of type <code>TaggedElem{I&lt;:Val,V}</code>, where <code>I</code> is a <a href="https://docs.julialang.org/en/v1/manual/types/#%22Value-types%22">type-level</a> tag and <code>V</code> is the type of the wrapped value. By default, these tags are just integers, e.g.&nbsp;the type of <code>SumSet([SetOb(Int), SetOb(String)])</code> is <code>Union{TaggedElem{Val{1}, Int}, TaggedElem{Val{2}, String}}</code>. Because <code>SumSet</code> is a model for <code>ThSet</code>, which provides a nullary method <code>eltype</code>, we can get the type of any particular <code>s::SumSet</code> via <code>eltype[s]()</code>.</p>
<p>We can see how the each operation of the implementation untags values, does a computation in one of its component categories, and then retags the result.</p>
<div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb3-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@instance</span> ThCategoryExplicitSets{O,H} [model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">CoproductCat{O,H}</span>] <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> {O,H} begin </span>
<span id="cb3-2"></span>
<span id="cb3-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">id</span>(x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">O</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">H </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span></span>
<span id="cb3-4">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">TaggedElem</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">id</span>(model[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gettag</span>(x)], <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getvalue</span>(x)), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gettag</span>(x))</span>
<span id="cb3-5"></span>
<span id="cb3-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dom</span>(x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">H</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">O </span></span>
<span id="cb3-7">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">TaggedElem</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dom</span>(model[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gettag</span>(x)], <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getvalue</span>(x)), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gettag</span>(x))</span>
<span id="cb3-8"></span>
<span id="cb3-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">codom</span>(x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">H</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">O </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span></span>
<span id="cb3-10">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">TaggedElem</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">codom</span>(model[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gettag</span>(x)], <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getvalue</span>(x)), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gettag</span>(x))</span>
<span id="cb3-11"></span>
<span id="cb3-12">  function <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compose</span>(x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">H</span>,y<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">H</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">H</span></span>
<span id="cb3-13">    tx, ty <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gettag</span>(x), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gettag</span>(y)</span>
<span id="cb3-14">    tx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> ty <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">||</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">error</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Cannot compose </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>x<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;"> </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>y<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb3-15">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">TaggedElem</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compose</span>(model[tx], <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getvalue</span>(x), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getvalue</span>(y)), tx)</span>
<span id="cb3-16">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb3-17">  </span>
<span id="cb3-18">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ob_set</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AbsSet </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SetOb</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SumSet</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ob_set</span>.(model.cats)))</span>
<span id="cb3-19"></span>
<span id="cb3-20">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">hom_set</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AbsSet </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SetOb</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SumSet</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">hom_set</span>.(model.cats)))</span>
<span id="cb3-21"></span>
<span id="cb3-22"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
</section>
<section id="finitely-generated-categories" class="level2">
<h2 class="anchored" data-anchor-id="finitely-generated-categories">Finitely-generated categories</h2>
<p>To give a <code>FinCat</code> requires us to additionally provide a finite number of morphism generators and a means of interpreting each generator as a <code>Hom</code>.<sup>1</sup></p>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb4-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@theory</span> ThFinCat <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> ThCategoryExplicitSets </span><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb4-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Gen</span>(src<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span>,tgt<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE</span>; </span>
<span id="cb4-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to_hom</span>(f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Gen</span>(a,b))<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(a,b) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">⊣</span> [(a,b)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span>]</span>
<span id="cb4-4">  FSet′<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE{FinSet}</span></span>
<span id="cb4-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gen_set</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">FSet′</span></span>
<span id="cb4-6"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb4-7">  </span>
<span id="cb4-8">ThFinCat.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Meta</span>.<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@wrapper</span> FinCat</span></code></pre></div>
<p>This theory was designed to unify the interface for <code>FinCatPresentation</code>, <code>FinCatGraph</code>, and symbolic models in old Catlab. The code surface of these constructs was not very uniform: little code was written for FinCats generically because implementations could not be switched interchangeably without breaking things.</p>
<p>Old Catlab defined <code>FinCat{Ob,Hom}</code> to be <code>Category{Ob,Hom,FinCatSize}</code>, which had the property of forcing every <code>FinCat</code> to be a <code>Category</code> implicitly. As discussed in the <a href="../02/refactor2/#set-implementations">last post</a>, while this is sometimes convenient, other times it is important to be capable of making the distinction. In our new approach, <code>FinCats</code> and <code>Categories</code> have different interfaces, though we can trivially implement the <code>Category</code> interface given any implementation of the <code>FinCat</code> interface by forgetting about <code>gen_set</code> and <code>to_hom</code>.<sup>2</sup></p>
<p>Models for <code>ThFinCat</code> which come from old Catlab include <code>DiscreteFinCat</code>, <code>FinCatGraph</code>, <code>FinCatPresentation</code>, and <code>OpFinCat</code>. We add to this <code>PathCat</code> (a model of a <code>ThFinCat</code>-like theory except we assume <code>Path=Hom</code>) and <code>PreorderCat</code>. <code>PreorderCat</code> is an interesting edge case because it has <code>Gen = Hom</code>, as both generators and homs are just pairs of objects. This revealed major ambiguities in old Catlab’s design which needed to be fixed because they use <em>type dispatch</em> to do different things depending on whether one is working with a generator, a hom, or a hom given as a path of generators.</p>
</section>
<section id="finfunctors" class="level2">
<h2 class="anchored" data-anchor-id="finfunctors">FinFunctors</h2>
<p>One of the largest breaking changes in the refactor is how <code>FinFunctor</code> and <code>FinDomFunctor</code> are handled. This is a consequence of the additional structure that <code>FinCat</code> has, as described above. In old Catlab, certain Julia types were assumed to be either generators, objects, or homs, such that type dispatch could determine what to do when a <code>FinFunctor</code> received arbitrary data (whether in the process of defining the <code>FinFunctor</code> or applying an existing one to some data). So calling <code>F(x)</code> would do something different whether it received an <code>Ob</code>-like Julia type vs a <code>Hom</code>-like type. Even if one is explicit with <code>hom_map(F, x)</code>, it still relied on dispatch to distinguish generator-like arguments, path-like arguments, and composite morphisms. However, in general one’s category could have the same Julia type for these different roles, so this code was only correct because the few instances of <code>FinCat</code>s did not have any such overlap.</p>
<p>This means when defining a <code>FinFunctor</code> or <code>FinDomFunctor</code>, one should declare whether one is sending generators to generators, paths, or homs. A new <code>homtype</code> keyword argument allows us to specify this:</p>
<div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb5-1">C <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">FinCat</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parallel_arrows</span>(Graph, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))</span>
<span id="cb5-2"></span>
<span id="cb5-3">h <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@acset</span> Graph <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span> V<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>; E<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>; src<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>]; tgt<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb5-4">D <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">FinCat</span>(h)</span>
<span id="cb5-5"></span>
<span id="cb5-6">F <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">FinFunctor</span>((V<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>], E<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>], [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>]]), C, D; homtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=:</span>list)</span>
<span id="cb5-7">G <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">FinFunctor</span>((V<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>], E<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>]), C, D; homtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=:</span>generator)</span></code></pre></div>
<iframe class="quiver-embed" src="https://q.uiver.app/#q=WzAsOCxbMCwwLCJ7XFxtYXRoc2YgQ18xfSJdLFsyLDAsIntcXG1hdGhzZiBDXzJ9Il0sWzAsMiwie1xcbWF0aHNmIERfMX0iXSxbMSwxLCJ7XFxtYXRoc2YgRF8yfSJdLFsxLDMsIntcXG1hdGhzZiBEXzN9Il0sWzIsMiwie1xcbWF0aHNmIERfNH0iXSxbMCw0LCJ7XFxtYXRoc2YgQ18xfSJdLFsyLDQsIntcXG1hdGhzZiBDXzJ9Il0sWzAsMSwiMiIsMix7ImN1cnZlIjoxfV0sWzAsMSwiMSIsMCx7ImN1cnZlIjotMX1dLFsyLDMsIjEiXSxbMiw0LCIyIiwyXSxbMyw1LCIzIl0sWzQsNSwiNCIsMl0sWzIsNSwiWzEsM10iLDEseyJjdXJ2ZSI6LTJ9XSxbMiw1LCJbMiw0XSIsMSx7ImN1cnZlIjoyfV0sWzAsMiwiRiIsMix7InN0eWxlIjp7ImJvZHkiOnsibmFtZSI6ImRhc2hlZCJ9fX1dLFsxLDUsIiIsMSx7InN0eWxlIjp7ImJvZHkiOnsibmFtZSI6ImRhc2hlZCJ9fX1dLFs2LDQsIiIsMix7InN0eWxlIjp7ImJvZHkiOnsibmFtZSI6ImRvdHRlZCJ9fX1dLFs3LDUsIkciLDIseyJzdHlsZSI6eyJib2R5Ijp7Im5hbWUiOiJkb3R0ZWQifX19XSxbNiw3LCIiLDEseyJjdXJ2ZSI6LTF9XSxbNiw3LCIiLDEseyJjdXJ2ZSI6MX1dLFs4LDE1LCIiLDIseyJjdXJ2ZSI6LTIsInNob3J0ZW4iOnsic291cmNlIjoyMCwidGFyZ2V0IjoxMH0sImxldmVsIjoxLCJzdHlsZSI6eyJib2R5Ijp7Im5hbWUiOiJkYXNoZWQifX19XSxbOSwxNCwiIiwwLHsiY3VydmUiOjEsInNob3J0ZW4iOnsic291cmNlIjoyMCwidGFyZ2V0IjoxMH0sImxldmVsIjoxLCJzdHlsZSI6eyJib2R5Ijp7Im5hbWUiOiJkYXNoZWQifX19XSxbMjAsMTMsIiIsMSx7InNob3J0ZW4iOnsidGFyZ2V0IjoxMH0sImxldmVsIjoxLCJzdHlsZSI6eyJib2R5Ijp7Im5hbWUiOiJkb3R0ZWQifX19XSxbMjEsMTMsIiIsMSx7ImxldmVsIjoxLCJzdHlsZSI6eyJib2R5Ijp7Im5hbWUiOiJkb3R0ZWQifX19XV0=&amp;embed" width="432" height="688" style="border-radius: 8px; border: none;">
</iframe>
<p>The models of <code>ThFinDomFunctor</code> include <code>CompositeFinDomFunctor</code>, <code>FinDomFunctorMap</code>, <code>IdentityFinDomFunctor</code>, and <code>OppositeFinDomFunctor</code>. Although we could define a separate theory <code>ThFinFunctor</code>, instead we opt to make a <code>FinFunctor</code> be a <code>FinDomFunctor</code> whose codomain happens to be a <code>FinCat</code> as there is no difference in the interface, even at the level of input and return types to the operations of the theory (in both cases, generators are sent to homs in the codomain).</p>
</section>
<section id="what-really-is-a-free-diagram" class="level2">
<h2 class="anchored" data-anchor-id="what-really-is-a-free-diagram">What really is a free diagram?</h2>
<p>Free diagrams in Catlab refer to <code>DiscreteDiagram</code>, <code>ComposableMorphisms</code>, <code>ParallelMorphisms</code>, <code>Multispan</code>, <code>Multicospan</code>, <code>BipartiteGraph</code>, and <code>FreeDiagram</code><sup>3</sup>. In old Catlab these are a bunch of related data structures which shared some overlapping interfaces. This is now made more explicit in the refactored code, where we are forced to confront this section’s titular question.</p>
<p>Mathematically, a free diagram is a functor out of a small (free) category. For us, this means <code>FreeDiagram</code> is like a functor but with a domain <code>Graph</code> (viewed as a free category). However, we don’t worry about including the category structure of the codomain (e.g.&nbsp;a pair of composable morphisms need not carry the information for how to obtain a single composite morphism). This means in order to get the mathematical definition of a free diagram out of <code>FreeDiagram</code>, one must also supply a codomain <code>Category</code>. We opt for this simplicity because a <code>FreeDiagram</code> is supposed to be a syntactic object; expecting them to have the complete data of a (possibly large) category is unreasonable.</p>
<p>Because <code>FreeDiagram</code> does not know what its codomain category is (just the Julia types of its objects and morphisms), the <code>FinDomFunctor(diagram)</code> method is no longer supported. This was only possible because it used to be that one knew the full category of structure just from the types of obs and homs (because the <code>ThCategory</code> implementation was determined by type dispatch).</p>
<p>Now let’s look at the interface:</p>
<div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb6-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@theory</span> ThFreeDiagram <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span> </span>
<span id="cb6-2">  V<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE</span>; E<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE</span>; Ob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE</span>; Hom<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE</span>; FSet<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE{FinSet}</span>;</span>
<span id="cb6-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">src</span>(h<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">E</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">V</span>;</span>
<span id="cb6-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tgt</span>(h<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">E</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">V</span>;</span>
<span id="cb6-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">obset</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">FSet</span></span>
<span id="cb6-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">homset</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">FSet</span></span>
<span id="cb6-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">obmap</span>(v<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">V</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span></span>
<span id="cb6-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">hommap</span>(<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">E</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span></span>
<span id="cb6-9"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb6-10"></span>
<span id="cb6-11">ThFreeDiagram.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Meta</span>.<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@wrapper</span> FreeDiagram</span></code></pre></div>
<p>The refactor of FreeDiagrams was more than just a cosmetic reorganization of free floating methods into the above interface. This is because old Catlab’s implementations for some of these <code>ThFreeDiagram</code> models did not contain enough data to implement this interface. For example, a <code>Span</code> in old Catlab has the data of a pair of morphisms. We can imagine <code>V={1,2,3}</code>, <code>E={1,2}</code>: the morphisms give the data of <code>hommap</code>, but not <code>obmap</code>. Old Catlab effectively derived what <code>obmap</code> was by presupposing that we can call <code>(co)dom</code> on whatever Julia type <code>Hom</code> is; however we just mentioned that we no longer want to presume the entire category structure of the free diagram’s codomain! After all, a term of some morphism type <code>Foo</code> can now have many different (co)domains, as we can have many different models of <code>ThCategory</code> with <code>Foo</code> as its morphisms. Thus our new design forces us modify the <code>Span</code> data structure to include the extra <code>obmap</code> data.<sup>4</sup></p>
<p>Just to get a flavor of what a model of <code>ThFreeDiagram</code> looks like, consider:</p>
<div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb7-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@instance</span> ThFreeDiagram{<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>,<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>,<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Union</span>{Ob,Foot},Hom</span>
<span id="cb7-2">                       } [model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Multispan{Ob,Hom,Foot,V,W}</span></span>
<span id="cb7-3">                         ] <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> {Ob, Hom, Foot, V, W} <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb7-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">src</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb7-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tgt</span>(x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb7-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">obmap</span>(x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Union{Ob,Foot} </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@match</span> x <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span> </span>
<span id="cb7-7">    <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apex</span>(model)</span>
<span id="cb7-8">    i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">feet</span>(model)[i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb7-9">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb7-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">hommap</span>(i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model[i]</span>
<span id="cb7-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">obset</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">FinSet </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">FinSet</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(model)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb7-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">homset</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">FinSet </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">FinSet</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(model))</span>
<span id="cb7-13"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
</section>
<section id="limits-and-colimits" class="level2">
<h2 class="anchored" data-anchor-id="limits-and-colimits">Limits and colimits</h2>
<p>Limits and colimits of free diagrams were controlled in old Catlab by a complicated process which involved defining methods for particular <code>FreeDiagram{Ob,Hom}</code> types, dispatching on the <code>Ob</code> and <code>Hom</code> types of these diagrams. In contrast, we now have a base theory for categories with limits:<sup>5</sup></p>
<div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb8-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@theory</span> ThCategoryLimitBase <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> ThCategoryExplicitSets </span><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb8-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Limit</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE{AbsLimit}</span></span>
<span id="cb8-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ob</span>(lim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Limit</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span></span>
<span id="cb8-4">  MSpan<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE{Multispan}</span></span>
<span id="cb8-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apex</span>(s<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">MSpan</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span></span>
<span id="cb8-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cone</span>(l<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Limit</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">MSpan</span></span>
<span id="cb8-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apex</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cone</span>(l)) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ob</span>(l) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">⊣</span> [l<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Limit</span>]</span>
<span id="cb8-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>Now for any particular kind of free diagram we can define a (co)limit theory, e.g.&nbsp;for <code>ParallelMorphisms</code>:</p>
<div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb9-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@theory</span> ThCategoryWithEqualizers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> ThCategoryLimitBase </span><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb9-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ParallelDiagram</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE{ParallelMorphisms}</span></span>
<span id="cb9-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">limit</span>(p<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">ParallelDiagram</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Limit</span></span>
<span id="cb9-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">universal</span>(eq<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Limit</span>, p<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">ParallelDiagram</span>, s<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">MSpan</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">(apex</span>(s) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">→</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ob</span>(eq))</span>
<span id="cb9-5"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb9-6"></span>
<span id="cb9-7">ThCategoryWithEqualizers.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Meta</span>.<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@wrapper</span> CatWithEqualizers</span></code></pre></div>
<p>Now we can implement such a theory for any given model, e.g.</p>
<div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb10-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@instance</span> ThCategoryWithEqualizers{FinSetInt, FinFunction} [model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">SkelFinSet</span>] begin</span>
<span id="cb10-2"></span>
<span id="cb10-3">  function <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">limit</span>(para<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">ParallelMorphisms</span>)</span>
<span id="cb10-4">    <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@assert</span> !<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isempty</span>(para)</span>
<span id="cb10-5">    f1, frest <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> para[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], para[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span>]</span>
<span id="cb10-6">    m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dom</span>(para))</span>
<span id="cb10-7">    eq <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">FinFunction</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter</span>(i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">all</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">f1</span>(i) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">f</span>(i) for f <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> frest), <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>m), m)</span>
<span id="cb10-8">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">LimitCone</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Multispan</span>(dom[model](eq), [eq]; cat<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>model), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">FreeDiagram</span>(para))</span>
<span id="cb10-9">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span> </span>
<span id="cb10-10">  </span>
<span id="cb10-11">  function <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">universal</span>(res<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AbsLimit</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">ParallelMorphisms</span>, span<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Multispan</span>)</span>
<span id="cb10-12">    ι <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">collect</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">only</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cone</span>(res)))</span>
<span id="cb10-13">    h <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">only</span>(span)</span>
<span id="cb10-14">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">FinFunction</span>(<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">only</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">searchsorted</span>(ι, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">h</span>(i))) for i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> dom[model](h)], <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(ι))</span>
<span id="cb10-15">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span> </span>
<span id="cb10-16"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>With the interface implemented as above, we will <em>not</em> get a runtime error if we try to wrap <code>SkelFinSet()</code> with <code>CatWithEqualizers</code>.</p>
<p>To compare to old Catlab: we are no longer dispatching on the types of <code>Ob</code> and <code>Hom</code> which appear in the diagram, so we now able to have different (co)limits for the same type of diagram, e.g.&nbsp;<code>DiscreteDiagram{Int, FinFunction}</code>. This interface no longer offers an <code>alg</code> keyword (for example, the many different join algorithms for pullbacks), as the GAT formalism doesn’t have a built-in notion of optional or keyword argument. In this case, whatever the default algorithm was is the one that appears in <code>@instance</code>. The other methods (e.g.&nbsp;<code>nested_loop_limit(cospan::Multicospan)</code>) are still preserved in the codebase, but need to be explicitly called rather than invoked via the <code>alg</code> keyword.</p>
</section>
<section id="monoidal-limits" class="level2">
<h2 class="anchored" data-anchor-id="monoidal-limits">Monoidal limits</h2>
<p>In old Catlab, there is a macro <code>@(co)cartesian_monoidal_instance ObType HomType</code> which generates a bunch of methods related to monoidal categories (e.g.&nbsp;<code>delete</code>, <code>copy</code>, <code>swap</code>) on the assumption that <code>ObType</code> and <code>HomType</code> have the right (co)limit methods already defined. Because the (co)limit methods are now tied to models rather than to the types themselves, we can replace this macro with an implementation of <code>Th(Co)CartesianCategory</code> given any model of <code>ThCatWithUnbiased(Co)Products</code>.<sup>6</sup> We can use a <em>wrapped</em> model of <code>ThCatWithUnbiased(Co)Products</code> as our <em>raw</em> model for <code>Th(Co)CartesianCategory</code>:<sup>7</sup></p>
<div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb11-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@instance</span> ThCocartesianCategory{Ob, Hom} [model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TypedCatWithCoproducts{Ob,Hom}</span></span>
<span id="cb11-2">    ] <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> {Ob,Hom} <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb11-3"></span>
<span id="cb11-4">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">swap</span>(A<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span>, B<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span>)</span>
<span id="cb11-5">    AB <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coproduct</span>(model, A, B)</span>
<span id="cb11-6">    BA <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coproduct</span>(model, B, A)</span>
<span id="cb11-7">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">copair</span>(model, AB, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coproj2</span>(BA), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coproj1</span>(BA))</span>
<span id="cb11-8">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb11-9">  </span>
<span id="cb11-10">  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">...</span></span>
<span id="cb11-11"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>Using <code>⊕</code> and <code>⊗</code> is not as seamless as it was before because their meaning depends on a particular choice of model. And because they are binary operators, it’s not possible to use the index notation (e.g.&nbsp;<code>id[MyCat](x)</code>) to fill in the model. This is where GATlab’s <code>@withmodel</code> macro is helpful:</p>
<div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb12-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">const</span> Grph <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ACSetCategory</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Graph</span>()) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># raw model</span></span>
<span id="cb12-2"></span>
<span id="cb12-3">X <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@withmodel</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">TypedCatWithCoproducts</span>(Grph) (<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">⊗</span>,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">⊕</span>) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span> </span>
<span id="cb12-4"> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cycle_graph</span>(Graph, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">⊗</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">path_graph</span>(Graph, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">⊕</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cycle_graph</span>(Graph, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>))</span>
<span id="cb12-5"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
</section>
<section id="slice-categories" class="level2">
<h2 class="anchored" data-anchor-id="slice-categories">Slice categories</h2>
<p>One of the most touted features of GATlab is that slice categories can be done in a more robust way.</p>
<div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb13-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> SliceOb{ObT, HomT}</span>
<span id="cb13-2">  ob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">ObT</span></span>
<span id="cb13-3">  hom<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">HomT</span></span>
<span id="cb13-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb13-5"></span>
<span id="cb13-6"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> SliceC{ObT, HomT}</span>
<span id="cb13-7">  cat<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Any </span></span>
<span id="cb13-8">  over<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">ObT</span></span>
<span id="cb13-9">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SliceC</span>(cat<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Category</span>, over)</span>
<span id="cb13-10">    cat <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getvalue</span>(cat) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># unwrap after confirming it's at least a Category model</span></span>
<span id="cb13-11">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">new</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{impl_types(cat, ThCategory)...}</span>(cat, over)</span>
<span id="cb13-12">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb13-13"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb13-14"></span>
<span id="cb13-15"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@instance</span> ThCategoryExplicitSets{SliceOb{<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">ObT</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">HomT</span>}, HomT</span>
<span id="cb13-16">    } [model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">SliceC{ObT, HomT}</span>] <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> {ObT, HomT} begin</span>
<span id="cb13-17"></span>
<span id="cb13-18">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">id</span>(x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">SliceOb{&lt;:ObT, &lt;:HomT}</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> id[model.cat](x.ob)</span>
<span id="cb13-19"></span>
<span id="cb13-20">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compose</span>(f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">HomT</span>, g<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">HomT</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> compose[model.cat](f, g)</span>
<span id="cb13-21">  </span>
<span id="cb13-22">  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">...</span></span>
<span id="cb13-23"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>As mentioned in the <a href="../02/refactor1/#wrapped-models">first post</a> of this series, wrapper types put us in a tricky position when we want to use the same model in the context of multiple theories. We want the model that we are slicing over to <em>at least</em> support the theory of categories, but we’ll likely want to use it in other theories that extend <code>ThCategory</code> (e.g.&nbsp;<code>ThCategoryWithPullbacks</code>, <code>ThCategoryWithInitial</code>). The <code>(co)limit</code> methods for those will not accept a wrapped <code>Category</code> model, but they will accept the raw model (e.g.&nbsp;<code>SkelFinSet</code>) if it happens to have those interfaces implemented. For the reason, the <code>SliceC</code> data structure doesn’t store the wrapped <code>Category</code> model but rather just stores the raw model (which could have any type). There is definitely room for improvement in the future!</p>
<!-- ## Category of Diagrams

A diagram is formally just a `FinDomFunctor`, but because there are many different categories that have these as objects. Old Catlab has a `Diagram` type that wraps a `FinDomFunctor` and has type parameters (`id`, `op`, and `co`) which control how these diagrams are used. This is a great candidate for redesign using the new GATlab machinery; however, in order to minimize conflict with downstream packages such as DataMigrations.jl which use the diagram code heavily, it's best to not radically expand the scope of the present refactor. Instead of type parameters, the refactored `Diagrams.jl` has three different wrapper structs which subtype an abstract type, `Diagram`. With this, we are still able to look at a particular diagram and know purely from that what category it was intended to live in. 
-->
</section>
<section id="next-steps" class="level2">
<h2 class="anchored" data-anchor-id="next-steps">Next steps</h2>
<p>There are other interesting aspects of refactoring the <code>Cats</code> module (e.g.&nbsp;various categories of diagrams in a category), but we’ll end this post here and continue next time with discussing how various categories related to ACSets are handled!</p>


</section>


<div id="quarto-appendix" class="default"><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>

<ol>
<li id="fn1"><p>In order for the set to truly generate all morphisms, it should be the case that for every morphism there exists <em>some</em> sequence of generators which compose to↩︎</p></li>
<li id="fn2"><p>This pattern, “any <img src="https://latex.codecogs.com/png.latex?X">-model gives a <img src="https://latex.codecogs.com/png.latex?Y">-model” is common and can also often be expressed via a GAT morphism between theories <img src="https://latex.codecogs.com/png.latex?X"> and <img src="https://latex.codecogs.com/png.latex?Y"> that can functorially migrate models. This is a direction we want to move in as the GAT morphism machinery becomes more mature.↩︎</p></li>
<li id="fn3"><p>Now called <code>FreeGraph</code> because <code>FreeDiagram</code> is the wrapper type for the <code>ThFreeDiagram</code> interface↩︎</p></li>
<li id="fn4"><p>If no objects are provided, then the constructor will <em>attempt</em> to use type dispatch to figure this info out, thus recovering the old behavior.↩︎</p></li>
<li id="fn5"><p>Here we are using externally-defined Julia types <code>AbsLimit</code> and <code>Multispan</code>, rather than fully axiomatizing them in the language of GATs. This is possible but not ergonomic at the present moment: at the present we are sacrificing being explicit about what it means to be an <code>AbsLimit</code> or <code>Multispan</code> for convenience and clarity.↩︎</p></li>
<li id="fn6"><p>To be even more accurate, we should take the pushout of theories of products and terminal objects. This current implementation presumes that a model which has implemented products has already implemented terminal objects.↩︎</p></li>
<li id="fn7"><p>This would be another great application of model migration via theory morphisms once GATlab’s theory specification language becomes rich enough to specify these (co)limit constructions.↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>code</category>
  <guid>https://blog.algebraicjulia.org/post/2025/05/refactor3/</guid>
  <pubDate>Fri, 16 May 2025 00:00:00 GMT</pubDate>
  <media:content url="https://blog.algebraicjulia.org/post/2025/05/refactor3/gar.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Analogies in Planning using Functorial Data Migrations</title>
  <dc:creator>Angeline Aguinaldo</dc:creator>
  <link>https://blog.algebraicjulia.org/post/2025/04/analogicaltransfer/</link>
  <description><![CDATA[ 





<div class="hidden">
<p>$$ <!-- Number systems --> </p>
<!-- Categories -->
<!-- Graphs -->
<!-- Double categories -->
<!-- Acsets -->
<!-- Wiring diagrams -->
<!-- Dynamical systems -->
<p>$$</p>
</div>
<div class="cell">
<style>
/* Style all code-generated tables */
.cell-output table {
  border-collapse: collapse;
  border: 1px solid black;
  background-color: white;
  width: auto; /* shrink to fit contents */
}

.cell-output table th,
.cell-output table td {
  border: 1px solid black;
  padding: 0.4em 0.6em;
  font-size: 0.9em;
}
</style>
</div>
<section id="analogies-in-planning" class="level1">
<h1>Analogies in Planning</h1>
<!-- Introduction about why you want to use analogies in planning -->
<p><strong>Do X like you would Y</strong>. That’s the essence of analogical thinking which can be surprisingly powerful in planning. We often want to restate one task in the language of another to reframe how we think about the problem. This reframing then helps us solve novel problems with solutions we already know.</p>
<!-- What are we calling an analogy in this context? -->
<p>Forming an analogy is a frequent cognitive process humans engage in. In cognitive psychology, this process is described as forming a structured mapping between two interrelated networks of concepts <span class="citation" data-cites="Gentner1983">(Gentner 1983)</span>. Think: <em>the sun is to the solar system as the nucleus is to an atom</em>. In planning, this can translate to finding a correspondence between the ontologies that structure two planning domains.</p>
<!-- Quick sentence on what a functorial data migration is. -->
<p>Precisely, how do we do this? In the context of my work on task planning <span class="citation" data-cites="Aguinaldo2025dissertation">(Aguinaldo 2025)</span>, I use functorial data migrations to align planning domain ontologies and reinterpret the world in light of this. In other words, a migration functor gives us instructions for how to carry over data from one plan to another in a way that respects their shared structure.</p>
<blockquote class="blockquote">
<p>If you need a refresher on how we represent plans using Double-Pushout (DPO) rewriting in AlgebraicJulia, check out this <a href="https://blog.algebraicjulia.org/post/2022/09/ai-planning-cset/">earlier blogpost</a> or refer to <span class="citation" data-cites="Aguinaldo2023">(Aguinaldo et al. 2023)</span>.</p>
</blockquote>
<p>In this post, we’ll walk through how a plan from the Tower of Hanoi domain can be analogically transferred into the Blocksworld domain—showing an unconventional though interesting reframing of classical problems in computer science.</p>
</section>
<section id="example-tower-of-hanoi-and-blocksworld" class="level1">
<h1>Example: Tower of Hanoi and Blocksworld</h1>
<!-- Explain what is TOH and BW-->
<p><strong>Blocksworld</strong> and <strong>Tower of Hanoi</strong> are canonical planning environments, called <em>planning domains</em>, in the field of AI planning. The appeal of experimenting within these domains is their generality and resemblance to richer, more realistic planning problems.</p>
<p><img src="https://blog.algebraicjulia.org/post/2025/04/analogicaltransfer/bw_vs_toh.svg" class="img-fluid"></p>
<p>In Blocksworld, blocks are stacked on one another or on table. Planning problems in this domain try to rearrange blocks to achieve a goal configuration based on the knowledge of what blocks are on top of one another or on the table at a given point in time. In Tower of Hanoi, <img src="https://latex.codecogs.com/png.latex?n">-disks are arranged on three pegs such that a larger disk <em>cannot</em> sit on top of a smaller disk. In other words, disks must be arranged increasing in diameter, top to bottom, contrained to three positions, given by the three pegs. Planning problems in this domain aim to arrange all <img src="https://latex.codecogs.com/png.latex?n">-disks on one peg based solely on the knowlege of what disks are larger than another and which peg a given disk is on.</p>
<!-- Table comparing the domains -->
<table class="caption-top table">
<colgroup>
<col style="width: 9%">
<col style="width: 39%">
<col style="width: 51%">
</colgroup>
<thead>
<tr class="header">
<th>Domain</th>
<th>Known</th>
<th>Constraints</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Blocksworld</td>
<td>- Block <img src="https://latex.codecogs.com/png.latex?x"> is on Block <img src="https://latex.codecogs.com/png.latex?y"> <br> - Block <img src="https://latex.codecogs.com/png.latex?x"> is on the table <br> - Block <img src="https://latex.codecogs.com/png.latex?x"> is clear</td>
<td>N/A</td>
</tr>
<tr class="even">
<td>Tower of Hanoi</td>
<td>- Disk <img src="https://latex.codecogs.com/png.latex?x"> is smaller than Disk <img src="https://latex.codecogs.com/png.latex?y"> <br> - Disk <img src="https://latex.codecogs.com/png.latex?x"> is on Peg <img src="https://latex.codecogs.com/png.latex?p_i"> <br> - Disk <img src="https://latex.codecogs.com/png.latex?x"> is clear</td>
<td>- Disk must be on one of three pegs <br> - Disk must be smaller than the disk below it</td>
</tr>
</tbody>
</table>
<!-- Quickly motivate why we would want to do this with TOH and BW -->
<p>Having been educated on the nuances between these domains, we could safely agree that they have very different qualities. But… would a four-year-old say the same?</p>
<p>A newcomer to this world would probably say both are basically the same–just activities that stack something on top of one another thing! By seeing things this way, they seem to have found shared meaning between these two worlds, or in other words an <em>analogy</em>… Let’s run with that!</p>
<p>This simplification leads to two very valid inquiries:</p>
<p><strong>Question A.</strong> <em>“Could I stack blocks in Blocksworld like I am in Tower of Hanoi?”</em></p>
<p><strong>Question B.</strong> <em>“Could I stack disks in Tower of Hanoi like I am in Blocksworld?”</em></p>
<p>Let’s see!</p>
<section id="constructing-the-example" class="level2">
<h2 class="anchored" data-anchor-id="constructing-the-example">Constructing the example</h2>
<p>To answer these questions, we use the AlgebraicJulia tools at our disposal.</p>
<div id="2" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab</span></span>
<span id="cb1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">DataMigrations;</span></span></code></pre></div>
</details>
</div>
<!-- Outline general steps -->
<p>In general, the steps for transferring a plan using an analogy are:</p>
<ol type="1">
<li>Define the <em>source</em> planning domain.</li>
<li>Create a plan in that <em>source</em> planning domain by: (i) defining an initial state and goal state and (ii) solving for a sequence of actions (rewrite rules) that gets you from the initial state to the goal.</li>
<li>Define the <em>target</em> planning domain.</li>
<li>Define an <em>analogy</em> from the target planning domain to the source planning domain.</li>
<li><em>Transfer the plan</em> by transferring each state in the source plan to a state within the target planning domain.</li>
</ol>
<p>In the framework of AlgebraicJulia:</p>
<ul>
<li>Planning domains will be presented as <em>schema categories</em>, based on <code>FreeSchema</code>.</li>
<li>Planning states will be presented as <em>attributed <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets</em>, specified using <code>@acset_colim</code>.</li>
<li>Analogies will be specified as a <em>migration functor</em>, <code>@migration</code>, from the target schema category to the source schema category.</li>
<li>Plan transfer will be done using a <em>functorial data migration</em>, <code>migrate(...)</code>.</li>
</ul>
</section>
<section id="step-1-tower-of-hanoi-schema" class="level2">
<h2 class="anchored" data-anchor-id="step-1-tower-of-hanoi-schema">Step 1: Tower of Hanoi Schema</h2>
<p>For <strong>Question A.</strong> (<em>“Could I stack blocks in Blocksworld like I am in Tower of Hanoi?”</em>) above, the source planning domain is Tower of Hanoi. A schema category for this domain must capture the notions of disks, pegs, disks being on pegs, and a disk being smaller than another disk (per the table above). The schema category for Tower of Hanoi is:</p>
<div id="4" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb2-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@present</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">OntTowerOfHanoi</span>(FreeSchema) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb2-2">  Disk<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span></span>
<span id="cb2-3">  Peg<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span></span>
<span id="cb2-4"></span>
<span id="cb2-5">  diskIsOnPeg<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(Disk, Peg)</span>
<span id="cb2-6"></span>
<span id="cb2-7">  Smaller<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span></span>
<span id="cb2-8">  isSmaller_l<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(Smaller, Disk)</span>
<span id="cb2-9">  isSmaller_r<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(Smaller, Disk)</span>
<span id="cb2-10"></span>
<span id="cb2-11">  Clear<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AttrType</span></span>
<span id="cb2-12">  isClear<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Attr</span>(Disk, Clear)</span>
<span id="cb2-13"></span>
<span id="cb2-14">  MyBool<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AttrType</span></span>
<span id="cb2-15">  MyString<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AttrType</span></span>
<span id="cb2-16"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb2-17"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@acset_type</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">TowerOfHanoi</span>(OntTowerOfHanoi);</span></code></pre></div>
</details>
</div>
<blockquote class="blockquote">
<p><strong>Note:</strong> <code>MyBool</code> and <code>MyString</code> are defined to allow <code>AttrTypes</code> in the target domain that do not have counterparts, such as <code>isOnTable</code> in Blocksworld, to be sent somewhere in the source domain.</p>
</blockquote>
</section>
<section id="step-2-plan-in-tower-of-hanoi" class="level2">
<h2 class="anchored" data-anchor-id="step-2-plan-in-tower-of-hanoi">Step 2: Plan in Tower of Hanoi</h2>
<p>For this example, we’ve constructed a planning problem consisting of three disks where disk₁ &lt; disk₂ &lt; disk₃ (<img src="https://latex.codecogs.com/png.latex?x"> &lt; <img src="https://latex.codecogs.com/png.latex?y"> means Disk <img src="https://latex.codecogs.com/png.latex?x"> is smaller than Disk <img src="https://latex.codecogs.com/png.latex?y">). In this problem, we start off with disk₁ and disk₃ on peg₁ and disk₂ on peg₂. The goal is to have disk₁, disk₂, and disk₃ on peg₁.</p>
<p><img src="https://blog.algebraicjulia.org/post/2025/04/analogicaltransfer/toh_problem.svg" class="img-fluid"></p>
<p><strong>Initial State, <code>init</code>.</strong> For this problem, we define the initial state using the follow ACSet:</p>
<blockquote class="blockquote">
<p>To specify ACSets, it is necessary to define all the components of the functor, which can be cumbersome and confusing using the native specification for <code>@acset</code> (see examples in <a href="https://github.com/AlgebraicJulia/ACSets.jl/blob/main/test/ACSets.jl">here</a>).</p>
<p>Fortunately, we can use <code>yTowerOfHanoi</code> and <code>@acset_colimit</code> to compactly define states. Using these tools, we can label our set and function assignments using friendly terms, such as <code>disk1</code>, <code>peg2</code>, <code>smaller1</code>, and <code>isClear(disk1) = true</code>.</p>
</blockquote>
<div id="6" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb3-1">yTowerOfHanoi <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">yoneda</span>(TowerOfHanoi{<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Bool</span>,<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Bool</span>,<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">String</span>});  </span>
<span id="cb3-2">init <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@acset_colim</span> yTowerOfHanoi <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb3-3">  (disk1, disk2, disk3)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Disk</span></span>
<span id="cb3-4">  (peg1, peg2, peg3)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Peg</span></span>
<span id="cb3-5">  (smaller1, smaller2, smaller3)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Smaller</span></span>
<span id="cb3-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isSmaller_l</span>(smaller1) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> disk1  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># disk1 &lt; disk2</span></span>
<span id="cb3-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isSmaller_r</span>(smaller1) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> disk2</span>
<span id="cb3-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isSmaller_l</span>(smaller2) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> disk2  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># disk2 &lt; disk3</span></span>
<span id="cb3-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isSmaller_r</span>(smaller2) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> disk3</span>
<span id="cb3-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isSmaller_l</span>(smaller3) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> disk1  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># disk1 &lt; disk3</span></span>
<span id="cb3-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isSmaller_r</span>(smaller3) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> disk3</span>
<span id="cb3-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">diskIsOnPeg</span>(disk1) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> peg1</span>
<span id="cb3-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">diskIsOnPeg</span>(disk2) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> peg2</span>
<span id="cb3-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">diskIsOnPeg</span>(disk3) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> peg1</span>
<span id="cb3-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isClear</span>(disk1) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">true</span></span>
<span id="cb3-16">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isClear</span>(disk2) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">false</span></span>
<span id="cb3-17">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isClear</span>(disk3) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">true</span></span>
<span id="cb3-18"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span>;</span></code></pre></div>
</details>
</div>
<div id="8" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display">
<div class="c-set">
<span class="c-set-summary">Main.Notebook.TowerOfHanoi{Bool, Bool, String} {Disk:3, Peg:3, Smaller:3, Clear:0, MyBool:0, MyString:0}</span>

<table class="caption-top table table-sm table-striped small" data-quarto-postprocess="true">
<thead>
<tr class="header headerLastRow">
<th class="rowLabel" data-quarto-table-cell-role="th" style="text-align: right; font-weight: bold;">Disk</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">diskIsOnPeg</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">isClear</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">1</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">true</td>
</tr>
<tr class="even">
<td class="rowLabel" style="text-align: right; font-weight: bold;">2</td>
<td style="text-align: right;">2</td>
<td style="text-align: right;">false</td>
</tr>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">3</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">true</td>
</tr>
</tbody>
</table>


<table class="caption-top table table-sm table-striped small" data-quarto-postprocess="true">
<thead>
<tr class="header headerLastRow">
<th class="rowLabel" data-quarto-table-cell-role="th" style="text-align: right; font-weight: bold;">Smaller</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">isSmaller_l</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">isSmaller_r</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">1</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">2</td>
</tr>
<tr class="even">
<td class="rowLabel" style="text-align: right; font-weight: bold;">2</td>
<td style="text-align: right;">2</td>
<td style="text-align: right;">3</td>
</tr>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">3</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">3</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
<p><strong>Goal State, <code>goal</code>.</strong> And the goal state is specified using the follow ACSet:</p>
<div id="10" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb4-1">goal <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@acset_colim</span> yTowerOfHanoi <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb4-2">  (disk1, disk2, disk3)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Disk</span></span>
<span id="cb4-3">  (peg1, peg2, peg3)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Peg</span></span>
<span id="cb4-4">  (smaller1, smaller2, smaller3)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Smaller</span></span>
<span id="cb4-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isSmaller_l</span>(smaller1) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> disk1  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># disk1 &lt; disk2</span></span>
<span id="cb4-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isSmaller_r</span>(smaller1) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> disk2</span>
<span id="cb4-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isSmaller_l</span>(smaller2) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> disk2  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># disk2 &lt; disk3</span></span>
<span id="cb4-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isSmaller_r</span>(smaller2) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> disk3</span>
<span id="cb4-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isSmaller_l</span>(smaller3) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> disk1  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># disk1 &lt; disk3</span></span>
<span id="cb4-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isSmaller_r</span>(smaller3) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> disk3</span>
<span id="cb4-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">diskIsOnPeg</span>(disk1) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> peg1</span>
<span id="cb4-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">diskIsOnPeg</span>(disk2) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> peg1</span>
<span id="cb4-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">diskIsOnPeg</span>(disk3) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> peg1</span>
<span id="cb4-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isClear</span>(disk1) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">true</span></span>
<span id="cb4-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isClear</span>(disk2) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">false</span></span>
<span id="cb4-16">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isClear</span>(disk3) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">true</span></span>
<span id="cb4-17"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span>;</span></code></pre></div>
</details>
</div>
<div id="12" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display">
<div class="c-set">
<span class="c-set-summary">Main.Notebook.TowerOfHanoi{Bool, Bool, String} {Disk:3, Peg:3, Smaller:3, Clear:0, MyBool:0, MyString:0}</span>

<table class="caption-top table table-sm table-striped small" data-quarto-postprocess="true">
<thead>
<tr class="header headerLastRow">
<th class="rowLabel" data-quarto-table-cell-role="th" style="text-align: right; font-weight: bold;">Disk</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">diskIsOnPeg</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">isClear</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">1</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">true</td>
</tr>
<tr class="even">
<td class="rowLabel" style="text-align: right; font-weight: bold;">2</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">false</td>
</tr>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">3</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">true</td>
</tr>
</tbody>
</table>


<table class="caption-top table table-sm table-striped small" data-quarto-postprocess="true">
<thead>
<tr class="header headerLastRow">
<th class="rowLabel" data-quarto-table-cell-role="th" style="text-align: right; font-weight: bold;">Smaller</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">isSmaller_l</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">isSmaller_r</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">1</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">2</td>
</tr>
<tr class="even">
<td class="rowLabel" style="text-align: right; font-weight: bold;">2</td>
<td style="text-align: right;">2</td>
<td style="text-align: right;">3</td>
</tr>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">3</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">3</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
<p>Given this problem, it is straightforward to solve for a plan in our heads. One reasonable solution involves two intermediate states that result in: (i) disk₁ being on peg₃, and (ii) disk₂ being on peg₁. The next state would be the goal state.</p>
<p>The intermediate states at ACSets look like:</p>
<div class="columns">
<div class="column" style="text-align: center;">
<p><strong>Intermediate State, <code>state₁</code></strong></p>
<div id="14" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display">
<div class="c-set">
<span class="c-set-summary">Main.Notebook.TowerOfHanoi{Bool, Bool, String} {Disk:3, Peg:3, Smaller:3, Clear:0, MyBool:0, MyString:0}</span>

<table class="caption-top table table-sm table-striped small" data-quarto-postprocess="true">
<thead>
<tr class="header headerLastRow">
<th class="rowLabel" data-quarto-table-cell-role="th" style="text-align: right; font-weight: bold;">Disk</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">diskIsOnPeg</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">isClear</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">1</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">true</td>
</tr>
<tr class="even">
<td class="rowLabel" style="text-align: right; font-weight: bold;">2</td>
<td style="text-align: right;">2</td>
<td style="text-align: right;">false</td>
</tr>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">3</td>
<td style="text-align: right;">3</td>
<td style="text-align: right;">true</td>
</tr>
</tbody>
</table>


<table class="caption-top table table-sm table-striped small" data-quarto-postprocess="true">
<thead>
<tr class="header headerLastRow">
<th class="rowLabel" data-quarto-table-cell-role="th" style="text-align: right; font-weight: bold;">Smaller</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">isSmaller_l</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">isSmaller_r</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">1</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">2</td>
</tr>
<tr class="even">
<td class="rowLabel" style="text-align: right; font-weight: bold;">2</td>
<td style="text-align: right;">2</td>
<td style="text-align: right;">3</td>
</tr>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">3</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">3</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
</div><div class="column" style="text-align: center;">
<p><strong>Intermediate State, <code>state₂</code></strong></p>
<div id="16" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display">
<div class="c-set">
<span class="c-set-summary">Main.Notebook.TowerOfHanoi{Bool, Bool, String} {Disk:3, Peg:3, Smaller:3, Clear:0, MyBool:0, MyString:0}</span>

<table class="caption-top table table-sm table-striped small" data-quarto-postprocess="true">
<thead>
<tr class="header headerLastRow">
<th class="rowLabel" data-quarto-table-cell-role="th" style="text-align: right; font-weight: bold;">Disk</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">diskIsOnPeg</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">isClear</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">1</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">true</td>
</tr>
<tr class="even">
<td class="rowLabel" style="text-align: right; font-weight: bold;">2</td>
<td style="text-align: right;">2</td>
<td style="text-align: right;">false</td>
</tr>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">3</td>
<td style="text-align: right;">2</td>
<td style="text-align: right;">true</td>
</tr>
</tbody>
</table>


<table class="caption-top table table-sm table-striped small" data-quarto-postprocess="true">
<thead>
<tr class="header headerLastRow">
<th class="rowLabel" data-quarto-table-cell-role="th" style="text-align: right; font-weight: bold;">Smaller</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">isSmaller_l</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">isSmaller_r</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">1</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">2</td>
</tr>
<tr class="even">
<td class="rowLabel" style="text-align: right; font-weight: bold;">2</td>
<td style="text-align: right;">2</td>
<td style="text-align: right;">3</td>
</tr>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">3</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">3</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
</div>
</div>
<p><strong>Plan.</strong> The plan, therefore, passes through states <code>[init, state₁, state₂, goal]</code> in order.</p>
<p><img src="https://blog.algebraicjulia.org/post/2025/04/analogicaltransfer/toh_plan.svg" class="img-fluid"></p>
</section>
<section id="step-3-blocksworld-schema" class="level2">
<h2 class="anchored" data-anchor-id="step-3-blocksworld-schema">Step 3: Blocksworld Schema</h2>
<p>In this example, the target planning domain is Blocksworld. The schema category should capture the notions of blocks, a block being on another block, and blocks being on the table (per the table above). The schema category for Blocksworld is:</p>
<div id="18" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb5-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@present</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">OntBlocksworld</span>(FreeSchema) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb5-2">  Block<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span></span>
<span id="cb5-3"></span>
<span id="cb5-4">  InOn<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span></span>
<span id="cb5-5">  inOn_l<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(InOn, Block) </span>
<span id="cb5-6">  inOn_r<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(InOn, Block)</span>
<span id="cb5-7"></span>
<span id="cb5-8">  Clear<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AttrType</span></span>
<span id="cb5-9">  isClear<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Attr</span>(Block, Clear)</span>
<span id="cb5-10">  OnTable<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AttrType</span></span>
<span id="cb5-11">  isOnTable<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Attr</span>(Block, OnTable)</span>
<span id="cb5-12"></span>
<span id="cb5-13">  MyBool<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AttrType</span></span>
<span id="cb5-14">  MyString<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AttrType</span></span>
<span id="cb5-15"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb5-16"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@acset_type</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Blocksworld</span>(OntBlocksworld);</span></code></pre></div>
</details>
</div>
</section>
<section id="step-4-define-the-analogy" class="level2">
<h2 class="anchored" data-anchor-id="step-4-define-the-analogy">Step 4: Define the analogy</h2>
<p>Now that we have defined the two planning domains, we can define an analogy between them using a migration functor. This migration functor is from the Blocksworld schema category to the Tower of Hanoi schema category (Note: This is contravariant relative to the direction of plan transfer. See <span class="citation" data-cites="spivak2012">(Spivak and Kent 2012)</span> for contravariant data migrations.)</p>
<p>Each component of the Blocksworld schema category (namely every <code>::Ob</code>, <code>::Hom</code>, <code>::AttrType</code>, and <code>::Attr</code>) must correspond to a structure based on the Tower of Hanoi schema category. Most of the components have trivial analogies that can be reasoned by quick intuition, such as <code>Block =&gt; Disk</code> and <code>Clear =&gt; Clear</code>.</p>
<p>This migration, however, establishes two non-trivial correspondences: (i) the assignment of <code>InOn</code> relations and (ii) the assignment of the <code>isOnTable</code> attribute.</p>
<p><strong>Assigning <code>InOn</code>.</strong> When defining this migration functor, we are faced with the situation where the notion of <code>IsOn</code> is not present in the Tower of Hanoi planning domain. All is not lost, however, because we can infer the ordering of the disks based purely on the fact that one disk is smaller than another and the pair of disks are on the same peg. This can be captured by describing an abstracted pattern of this phenomena:</p>
<div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb6-1">  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">...</span></span>
<span id="cb6-2">  InOn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@join</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb6-3">    disk1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Disk</span></span>
<span id="cb6-4">    disk2<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Disk</span></span>
<span id="cb6-5">    peg<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Peg</span></span>
<span id="cb6-6">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">diskIsOnPeg</span>(disk1) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> peg</span>
<span id="cb6-7">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">diskIsOnPeg</span>(disk2) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> peg</span>
<span id="cb6-8">    smaller<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Smaller</span></span>
<span id="cb6-9">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isSmaller_l</span>(smaller) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> disk1  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># disk1 &lt; disk2</span></span>
<span id="cb6-10">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isSmaller_r</span>(smaller) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> disk2</span>
<span id="cb6-11">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span>  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># a disk is on another if it is smaller and on the same peg</span></span>
<span id="cb6-12">  inOn_l <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> disk1</span>
<span id="cb6-13">  inOn_r <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> disk2</span>
<span id="cb6-14">  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">...</span></span></code></pre></div>
<p>In AlgebraicJulia, this pattern is a diagram forming a <em>conjuctive query</em>, <code>@join</code>.</p>
<p><strong>Assigning <code>isOnTable</code>.</strong> Perhaps the more difficult situation we find ourselves in is how we assign a corresponding Boolean value to the attribute <code>isOnTable</code>. In Tower of Hanoi, the notion of disks being on a table is not capture. However, intuitively we can see that a disk being on the table is analogous to being at the bottom of a stack for a given peg. This is true when a disk is the largest disk of all the disks on the same peg. We can define an anonymous Julia function, given by (<code>(x -&gt; begin ... end)</code>), that determines this value.</p>
<div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb7-1">  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">...</span></span>
<span id="cb7-2">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># A disk, x, is on the table if it is the largest disk on a peg.</span></span>
<span id="cb7-3">  isOnTable <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> (x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb7-4"></span>
<span id="cb7-5">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Step 1. Get the peg that the disk `x` is on</span></span>
<span id="cb7-6">    p <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">diskIsOnPeg</span>(x) </span>
<span id="cb7-7"></span>
<span id="cb7-8">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Step 2. Get all the disks on the same peg as `x`</span></span>
<span id="cb7-9">    dop <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [i for (i, x) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">enumerate</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">collect</span>(diskIsOnPeg)) if x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> p]</span>
<span id="cb7-10"></span>
<span id="cb7-11">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Step 3. Filter `smaller` to only relations that involve the disks </span></span>
<span id="cb7-12">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># that were selected</span></span>
<span id="cb7-13">    smaller′ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>  [</span>
<span id="cb7-14">      i </span>
<span id="cb7-15">      for (i, rel) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">enumerate</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">zip</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">collect</span>(isSmaller_l), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">collect</span>(isSmaller_r))) </span>
<span id="cb7-16">      if <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">all</span>(d <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> d <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> dop, rel)</span>
<span id="cb7-17">    ]</span>
<span id="cb7-18"></span>
<span id="cb7-19">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Step 4. Check if disk is not contained in `isSmaller_l` in `smaller′`</span></span>
<span id="cb7-20">    !(x <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">collect</span>(isSmaller_l)[smaller′]) </span>
<span id="cb7-21">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span>) </span>
<span id="cb7-22">  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">...</span></span></code></pre></div>
<blockquote class="blockquote">
<p>We can determine that the variable <code>x</code> refers to a <code>Disk</code> because the source object of <code>isOnTable::Hom(Block, onTable)</code> is <code>Block</code> and we know that <code>Block =&gt; Disk</code> in our migration functor.</p>
</blockquote>
<p>Putting this all together, we get the following migration functor:</p>
<div id="20" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb8-1">F <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@migration</span> OntBlocksworld OntTowerOfHanoi <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb8-2">  Block <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> Disk</span>
<span id="cb8-3">  InOn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@join</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb8-4">    disk1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Disk</span></span>
<span id="cb8-5">    disk2<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Disk</span></span>
<span id="cb8-6">    peg<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Peg</span></span>
<span id="cb8-7">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">diskIsOnPeg</span>(disk1) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> peg</span>
<span id="cb8-8">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">diskIsOnPeg</span>(disk2) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> peg</span>
<span id="cb8-9">    smaller<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Smaller</span></span>
<span id="cb8-10">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isSmaller_l</span>(smaller) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> disk1  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># disk1 &lt; disk2</span></span>
<span id="cb8-11">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isSmaller_r</span>(smaller) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> disk2</span>
<span id="cb8-12">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span>  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># a disk is on another if it is smaller and on the same peg</span></span>
<span id="cb8-13">  inOn_l <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> disk1</span>
<span id="cb8-14">  inOn_r <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> disk2</span>
<span id="cb8-15">  Clear <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> Clear</span>
<span id="cb8-16">  isClear <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> isClear</span>
<span id="cb8-17">  OnTable <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> MyBool</span>
<span id="cb8-18">  isOnTable <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> (x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb8-19">    p <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">diskIsOnPeg</span>(x) </span>
<span id="cb8-20">    dop <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [i for (i, x) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">enumerate</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">collect</span>(diskIsOnPeg)) if x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> p]</span>
<span id="cb8-21">    smaller′ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>  [</span>
<span id="cb8-22">      i </span>
<span id="cb8-23">      for (i, rel) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">enumerate</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">zip</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">collect</span>(isSmaller_l), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">collect</span>(isSmaller_r))) </span>
<span id="cb8-24">      if <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">all</span>(d <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> d <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> dop, rel)</span>
<span id="cb8-25">    ]</span>
<span id="cb8-26">    !(x <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">collect</span>(isSmaller_l)[smaller′]) </span>
<span id="cb8-27">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span>) </span>
<span id="cb8-28">  MyBool <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> MyBool</span>
<span id="cb8-29">  MyString <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> MyString</span>
<span id="cb8-30"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span>;</span></code></pre></div>
</details>
</div>
<p>Once defined, this never needs to be defined again. This means that we can transfer any plan in Tower of Hanoi to an analogous Blocksworld plan using this specification.</p>
</section>
<section id="step-5-transfer-plan" class="level2">
<h2 class="anchored" data-anchor-id="step-5-transfer-plan">Step 5: Transfer Plan</h2>
<p>To transfer a plan, we can now very easily migrate each state in the Tower of Hanoi plan using a functorial data migration:</p>
<div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb9-1">new_init <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">migrate</span>(Blocksworld,  init, F)</span>
<span id="cb9-2">new_state₁ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">migrate</span>(Blocksworld, state₁, F)</span>
<span id="cb9-3">new_state₂ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">migrate</span>(Blocksworld, state₂, F)</span>
<span id="cb9-4">new_goal <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">migrate</span>(Blocksworld, goal, F)</span></code></pre></div>
<blockquote class="blockquote">
<p>We will address why we are migrating states instead of whole rewrite rules later in the post.</p>
</blockquote>
<div class="columns">
<div class="column" style="text-align: center;">
<p><strong>New Initial State, <code>new_init</code></strong></p>
<div id="22" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div class="c-set">
<span class="c-set-summary">Main.Notebook.Blocksworld{Bool, Bool, Bool, String} {Block:3, InOn:1, Clear:0, OnTable:0, MyBool:0, MyString:0}</span>

<table class="caption-top table table-sm table-striped small" data-quarto-postprocess="true">
<thead>
<tr class="header headerLastRow">
<th class="rowLabel" data-quarto-table-cell-role="th" style="text-align: right; font-weight: bold;">Block</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">isClear</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">isOnTable</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">1</td>
<td style="text-align: right;">true</td>
<td style="text-align: right;">false</td>
</tr>
<tr class="even">
<td class="rowLabel" style="text-align: right; font-weight: bold;">2</td>
<td style="text-align: right;">false</td>
<td style="text-align: right;">true</td>
</tr>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">3</td>
<td style="text-align: right;">true</td>
<td style="text-align: right;">true</td>
</tr>
</tbody>
</table>


<table class="caption-top table table-sm table-striped small" data-quarto-postprocess="true">
<thead>
<tr class="header headerLastRow">
<th class="rowLabel" data-quarto-table-cell-role="th" style="text-align: right; font-weight: bold;">InOn</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">inOn_l</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">inOn_r</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">1</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">3</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
</div><div class="column" style="text-align: center;">
<p><strong>New Intermediate State, <code>new_state₁</code></strong></p>
<div id="24" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div class="c-set">
<span class="c-set-summary">Main.Notebook.Blocksworld{Bool, Bool, Bool, String} {Block:3, InOn:0, Clear:0, OnTable:0, MyBool:0, MyString:0}</span>

<table class="caption-top table table-sm table-striped small" data-quarto-postprocess="true">
<thead>
<tr class="header headerLastRow">
<th class="rowLabel" data-quarto-table-cell-role="th" style="text-align: right; font-weight: bold;">Block</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">isClear</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">isOnTable</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">1</td>
<td style="text-align: right;">true</td>
<td style="text-align: right;">true</td>
</tr>
<tr class="even">
<td class="rowLabel" style="text-align: right; font-weight: bold;">2</td>
<td style="text-align: right;">false</td>
<td style="text-align: right;">true</td>
</tr>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">3</td>
<td style="text-align: right;">true</td>
<td style="text-align: right;">true</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
</div>
</div>
<div class="columns">
<div class="column" style="text-align: center;">
<p><strong>New Intermediate State, <code>new_state₂</code></strong></p>
<div id="26" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div class="c-set">
<span class="c-set-summary">Main.Notebook.Blocksworld{Bool, Bool, Bool, String} {Block:3, InOn:1, Clear:0, OnTable:0, MyBool:0, MyString:0}</span>

<table class="caption-top table table-sm table-striped small" data-quarto-postprocess="true">
<thead>
<tr class="header headerLastRow">
<th class="rowLabel" data-quarto-table-cell-role="th" style="text-align: right; font-weight: bold;">Block</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">isClear</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">isOnTable</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">1</td>
<td style="text-align: right;">true</td>
<td style="text-align: right;">true</td>
</tr>
<tr class="even">
<td class="rowLabel" style="text-align: right; font-weight: bold;">2</td>
<td style="text-align: right;">false</td>
<td style="text-align: right;">false</td>
</tr>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">3</td>
<td style="text-align: right;">true</td>
<td style="text-align: right;">true</td>
</tr>
</tbody>
</table>


<table class="caption-top table table-sm table-striped small" data-quarto-postprocess="true">
<thead>
<tr class="header headerLastRow">
<th class="rowLabel" data-quarto-table-cell-role="th" style="text-align: right; font-weight: bold;">InOn</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">inOn_l</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">inOn_r</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">1</td>
<td style="text-align: right;">2</td>
<td style="text-align: right;">3</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
</div><div class="column" style="text-align: center;">
<p><strong>New Goal State, <code>new_goal</code></strong></p>
<div id="28" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div class="c-set">
<span class="c-set-summary">Main.Notebook.Blocksworld{Bool, Bool, Bool, String} {Block:3, InOn:3, Clear:0, OnTable:0, MyBool:0, MyString:0}</span>

<table class="caption-top table table-sm table-striped small" data-quarto-postprocess="true">
<thead>
<tr class="header headerLastRow">
<th class="rowLabel" data-quarto-table-cell-role="th" style="text-align: right; font-weight: bold;">Block</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">isClear</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">isOnTable</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">1</td>
<td style="text-align: right;">true</td>
<td style="text-align: right;">false</td>
</tr>
<tr class="even">
<td class="rowLabel" style="text-align: right; font-weight: bold;">2</td>
<td style="text-align: right;">false</td>
<td style="text-align: right;">false</td>
</tr>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">3</td>
<td style="text-align: right;">true</td>
<td style="text-align: right;">true</td>
</tr>
</tbody>
</table>


<table class="caption-top table table-sm table-striped small" data-quarto-postprocess="true">
<thead>
<tr class="header headerLastRow">
<th class="rowLabel" data-quarto-table-cell-role="th" style="text-align: right; font-weight: bold;">InOn</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">inOn_l</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">inOn_r</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">1</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">2</td>
</tr>
<tr class="even">
<td class="rowLabel" style="text-align: right; font-weight: bold;">2</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">3</td>
</tr>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">3</td>
<td style="text-align: right;">2</td>
<td style="text-align: right;">3</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
</div>
</div>
<p>Therefore, the new plan in Blocksworld will look like:</p>
<p><img src="https://blog.algebraicjulia.org/post/2025/04/analogicaltransfer/bw_plan.svg" class="img-fluid"></p>
</section>
</section>
<section id="some-observations" class="level1">
<h1>Some observations</h1>
<p>Let’s check back in with our five-year-old. (Yes, they aged a year in the time we worked through this example…). So, what questions did they want to answer?</p>
<p><strong>Question A.</strong> <em>“Could I stack blocks in Blocksworld like I am in Tower of Hanoi?”</em></p>
<p><strong>Question B.</strong> <em>“Could I stack disks in Tower of Hanoi like I am in Blocksworld?”</em></p>
<p>Well…</p>
<section id="valid-tower-of-hanoi-to-blocksworld" class="level2">
<h2 class="anchored" data-anchor-id="valid-tower-of-hanoi-to-blocksworld">Valid: Tower of Hanoi to Blocksworld</h2>
<p>We have determined that seeking an analoguous Tower of Hanoi plan in the Blocksworld domain is a valid inquiry and can be computed. This is because the data migration is (<em>suspected to be</em>) functorial.</p>
<p>That is: the relationships that define how a Tower of Hanoi state behaves can be meaningfully interpreted within Blocksworld. The idea of a disk being on another—defined relationally as “smaller and on the same peg”—translates naturally into the <code>InOn</code> structure in Blocksworld. Similarly, a disk being at the bottom of the peg (i.e., the largest on that peg) maps correctly to a block being <code>isOnTable</code>.</p>
<p>So even though Blocksworld has no concept of “pegs” and Tower of Hanoi has no explicit notion of “on-ness,” the mapping works because the structure of relationships is preserved.</p>
<section id="functoriality-when-fancy-attributes-are-involved" class="level3">
<h3 class="anchored" data-anchor-id="functoriality-when-fancy-attributes-are-involved">Functoriality when fancy attributes are involved</h3>
<!-- Address that migrating morphisms is not ready yet. -->
<p>Admittedly, we have not fully demonstrated that our data migration is functorial because we have not migrated any morphisms (by design, for now).</p>
<p>That’s because migrating rewrite rules (i.e., morphisms that construct actions) gets tricky when attributes are computed via Julia code—like our function for <code>isOnTable</code>. The combinatorial part of the rewrite (i.e., those involving <code>Ob</code>s and <code>Hom</code>s) can be handled functorially, but interpreting or translating attribute-level programs—especially ones with custom logic that relies on data from other ACSet parts—is still an open area of research.</p>
<p>Because of this, migrating morphisms is left to be implemented (see <a href="https://github.com/AlgebraicJulia/DataMigrations.jl/issues/165">DataMigrations.jl #165</a>).</p>
</section>
</section>
<section id="invalid-blocksworld-to-tower-of-hanoi" class="level2">
<h2 class="anchored" data-anchor-id="invalid-blocksworld-to-tower-of-hanoi">Invalid: Blocksworld to Tower of Hanoi</h2>
<p>Now, checking that a Blocksworld plan works in the Tower of Hanoi domain is a different story.</p>
<p>Blocksworld doesn’t impose size constraints. It doesn’t distinguish between placing a smaller block on a larger one—or the reverse. It doesn’t have pegs, and it doesn’t require exclusivity about what “stack” a block belongs to. So if we try to map a Blocksworld plan back into Tower of Hanoi, we run into trouble.</p>
<div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb10-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Not valid code</span></span>
<span id="cb10-2">F⁻¹ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@migration</span> OntTowerOfHanoi OntBlocksworld <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb10-3">  Disk <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> Block</span>
<span id="cb10-4">  Peg <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> ??  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># no notion of stack position</span></span>
<span id="cb10-5">  diskIsOnPeg <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> ?? <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># no notion of blocks on "pegs"</span></span>
<span id="cb10-6">  Smaller <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> ??  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># smaller does not imply on top of</span></span>
<span id="cb10-7">  isSmaller_l <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> ??</span>
<span id="cb10-8">  isSmaller_r <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> ??</span>
<span id="cb10-9">  Clear <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> Clear</span>
<span id="cb10-10">  isClear <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> isClear</span>
<span id="cb10-11"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>Why? Because Tower of Hanoi expects more structure than Blocksworld can provide. The destination domain asks questions that the source domain can’t answer.</p>
<p>Without extra information, we can’t make that translation… and that’s okay. Not all mappings are invertible, which perhaps signals something far more interesting–the lack of a true analogy <em>from</em> Blocksworld <em>to</em> Tower of Hanoi.</p>
</section>
</section>
<section id="conclusion" class="level1">
<h1>Conclusion</h1>
<p>By interpreting the Tower of Hanoi plan in the Blocksworld domain, we didn’t just copy a sequence of actions, but instead transported meaning. We made sense of one domain in terms of another, and functorial data migrations gives us the formal machinery to coherently do that.</p>
<p>More specifically, the benefits we saw from using functorial data migrations were that:</p>
<ul>
<li>It automated the translations of states and plans, and</li>
<li>It lets us prove that there is no analogy between two schema categories in a particular direction. (This can be done automatically by computing the homset between the schemas categories and deciding that there are no migration functors that do what you want.)</li>
</ul>
<p>This opens the door to alternative approaches to planning, like: planning in simpler domains and transporting solutions to more complex ones, or designing algorithms that detect when analogies break down, or introducing new constraints to planning problems by reinterpreting them in new domains.</p>
<p>For a deeper exposition of these ideas within robot task planning, refer to <span class="citation" data-cites="Aguinaldo2025">(Aguinaldo, Patterson, and Regli 2025)</span>.</p>
</section>
<section id="references" class="level1">




</section>

<div id="quarto-appendix" class="default"><section class="quarto-appendix-contents" id="quarto-bibliography"><h2 class="anchored quarto-appendix-heading">References</h2><div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="0">
<div id="ref-Aguinaldo2025dissertation" class="csl-entry">
Aguinaldo, Angeline. 2025. <span>“Sequential, Hierarchical, and Analogical Plan Transfer in Robotics.”</span> Ph.D. Dissertation, College Park, MD: University of Maryland, College Park.
</div>
<div id="ref-Aguinaldo2023" class="csl-entry">
Aguinaldo, Angeline, Evan Patterson, James Fairbanks, William Regli, and Jaime Ruiz. 2023. <span>“<span class="nocase">A Categorical Representation Language and Computational System for Knowledge-Based Planning</span>.”</span> In <em>2023 AAAI Fall Symposium on Unifying Representations for Robot Application Development</em>.
</div>
<div id="ref-Aguinaldo2025" class="csl-entry">
Aguinaldo, Angeline, Evan Patterson, and William Regli. 2025. <span>“Automating Transfer of Robot Task Plans Using Functorial Data Migrations.”</span> <a href="https://arxiv.org/abs/2406.15961">https://arxiv.org/abs/2406.15961</a>.
</div>
<div id="ref-Gentner1983" class="csl-entry">
Gentner, Dedre. 1983. <span>“<a href="https://www.ncbi.nlm.nih.gov/pubmed/11547370"><span class="nocase">Structure Mapping: A Theoretical Framework for Analogy</span></a>.”</span> <em>Cognitive Science</em> 7: 155–70.
</div>
<div id="ref-spivak2012" class="csl-entry">
Spivak, David I., and Robert E. Kent. 2012. <span>“Ologs: A Categorical Framework for Knowledge Representation.”</span> Edited by Chris Mavergames. <em><span>PLoS</span> <span>ONE</span></em> 7 (1): e24274. <a href="https://doi.org/10.1371/journal.pone.0024274">https://doi.org/10.1371/journal.pone.0024274</a>.
</div>
</div></section></div> ]]></description>
  <category>planning</category>
  <category>c-sets</category>
  <category>data migrations</category>
  <guid>https://blog.algebraicjulia.org/post/2025/04/analogicaltransfer/</guid>
  <pubDate>Fri, 18 Apr 2025 00:00:00 GMT</pubDate>
  <media:content url="https://blog.algebraicjulia.org/post/2025/04/analogicaltransfer/bw_vs_toh_vertical.svg" medium="image" type="image/svg+xml"/>
</item>
<item>
  <title>Multi-agent Coordination with AlgebraicJulia using Cellular Sheaves</title>
  <dc:creator>Tyler Hanks</dc:creator>
  <link>https://blog.algebraicjulia.org/post/2025/04/sheafcoordination/</link>
  <description><![CDATA[ 





<div class="hidden">
<p>$$ <!-- Number systems --> </p>
<!-- Categories -->
<!-- Graphs -->
<!-- Double categories -->
<!-- Acsets -->
<!-- Wiring diagrams -->
<!-- Dynamical systems -->
<p>$$</p>
</div>
<p><img src="https://blog.algebraicjulia.org/post/2025/04/sheafcoordination/vehicles.png" class="img-fluid"> Our recent paper, <a href="https://arxiv.org/abs/2504.02049">Distributed Multi-agent Coordination over Cellular Sheaves</a>, showed how optimization problems defined over cellular sheaves, known as nonlinear homological programs, serve as a unified modeling abstraction for multi-agent coordination problems.</p>
<section id="cellular-sheaves-for-multi-agent-control-systems" class="level2">
<h2 class="anchored" data-anchor-id="cellular-sheaves-for-multi-agent-control-systems">Cellular Sheaves for Multi-agent Control Systems</h2>
<p>For our purposes, a multi-agent control system consists of a collection of <img src="https://latex.codecogs.com/png.latex?N"> agents with discrete LTI dynamics <img src="https://latex.codecogs.com/png.latex?%0Ax_i(t+1)%20=%20A_i%20x_i(t)%20+%20B_i%20u_i(t)%0A"> for each <img src="https://latex.codecogs.com/png.latex?i%5Cin%5BN%5D">, where <img src="https://latex.codecogs.com/png.latex?A_i"> and <img src="https://latex.codecogs.com/png.latex?B_i"> are matrices, <img src="https://latex.codecogs.com/png.latex?x_i"> is the state variable of agent <img src="https://latex.codecogs.com/png.latex?i">, and <img src="https://latex.codecogs.com/png.latex?u_i"> is the control input of agent <img src="https://latex.codecogs.com/png.latex?i">. We suppose that agents can have bidirectional communication with other agents. The communication topology of the agents thus forms an undirected simple graph <img src="https://latex.codecogs.com/png.latex?G">. A general multi-agent coordination problem involves each agent choosing control inputs for themselves to drive the total system towards some desired goal. The agents should make these choices using only local computation and communication with neighboring agents. Examples of coordination goals include</p>
<ul>
<li>Consensus, where each agent reaches the same position,</li>
<li>Formation, where each agent reaches a desired displacement from neighboring agents,</li>
<li>Flocking, where all agents move with the same velocity while staying a fixed distance apart from each other.</li>
</ul>
<p>The main idea of our paper was to use cellular sheaves to model the communication structure of the multi-agent system and edge potential functions to encode the coordination goals between each pair of agents. For the rest of this section, we introduce concepts from cellular sheaves as they relate to this multi-agent setup.</p>
<p>A <strong>cellular sheaf</strong> <img src="https://latex.codecogs.com/png.latex?%5Cmathcal%7BF%7D"> on an undirected simple graph <img src="https://latex.codecogs.com/png.latex?G=(V,E)"> consists of</p>
<ul>
<li>a collection of vector spaces <img src="https://latex.codecogs.com/png.latex?%5Cmathcal%7BF%7D(v)"> for each <img src="https://latex.codecogs.com/png.latex?v%5Cin%20V"> known as <strong>vertex stalks</strong>,</li>
<li>a collection of vector spaces <img src="https://latex.codecogs.com/png.latex?%5Cmathcal%7BF%7D(e)"> for each <img src="https://latex.codecogs.com/png.latex?e%5Cin%20E"> known as <strong>edge stalks</strong>,</li>
<li>For each edges <img src="https://latex.codecogs.com/png.latex?e=v%5Csim%20w">, a pair of linear maps <img src="https://latex.codecogs.com/png.latex?%5Cmathcal%7BF%7D_%7Bv%5Cto%20e%7D%5Ccolon%20%5Cmathcal%7BF%7D(v)%5Cto%20%5Cmathcal%7BF%7D(e)"> and <img src="https://latex.codecogs.com/png.latex?%5Cmathcal%7BF%7D_%7Bw%5Cto%20e%7D%5Ccolon%20%5Cmathcal%7BF%7D(w)%5Cto%5Cmathcal%7BF%7D(e)"> known as <strong>restriction maps</strong>.</li>
</ul>
<p>The graph <img src="https://latex.codecogs.com/png.latex?G"> corresponds to the communication topology of the agents, while the vertex stalks are the state spaces of each agent. The edge stalks are then the spaces of valid communications between agents and the restriction maps encodes the view of each agents state which is passed to other agents. A simple example is an agent with a complex state space who only wants to communicate its position with other agents. In this case, it would choose projection onto the position components of its state as its restriction map to its neighbors.</p>
<p>There are two important vector spaces associated to any cellular sheaf:</p>
<ol type="1">
<li>The space of 0-cochains: <img src="https://latex.codecogs.com/png.latex?C%5E0(G;%5Cmathcal%7BF%7D)%5Ccoloneqq%5Cbigoplus_%7Bv%5Cin%20V%7D%5Cmathcal%7BF%7D(v)"></li>
<li>The space of 1-cochains: <img src="https://latex.codecogs.com/png.latex?C%5E1(G;%5Cmathcal%7BF%7D)%5Ccoloneqq%5Cbigoplus_%7Be%5Cin%20E%7D%5Cmathcal%7BF%7D(e)"></li>
</ol>
<p>A <strong>global section</strong> of <img src="https://latex.codecogs.com/png.latex?%5Cmathcal%7BF%7D"> is a globally consistent choice of vectors for each vertex stalk, meaning that when we pass these vectors through the incident restriction maps, they are equal. In the context of our multi-agent system, a global section is a state for each agent which agrees when communicated with neighboring agents.</p>
<p>To compute whether a given state is a global section, we can use the coboundary map. Given an arbitrary orientation of the edges of <img src="https://latex.codecogs.com/png.latex?G">, the <strong>coboundary map</strong> of <img src="https://latex.codecogs.com/png.latex?%5Cmathcal%7BF%7D">, denoted <img src="https://latex.codecogs.com/png.latex?%5Cdelta_%5Cmathcal%7BF%7D"> is the linear map <img src="https://latex.codecogs.com/png.latex?C%5E0(G;%5Cmathcal%7BF%7D)%5Cto%20C%5E1(G;%5Cmathcal%7BF%7D)"> defined by <img src="https://latex.codecogs.com/png.latex?(%5Cdelta_%7B%5Cmathcal%7BF%7D%7D%20%5Cmathbf%7Bx%7D)_%7Be%7D%20=%20%5Cmathcal%7BF%7D_%7Bi%20%5Cto%20e%7D(x_i)%20-%20%5Cmathcal%7BF%7D_%7Bj%20%5Cto%20e%7D(x_j)"> for all edges <img src="https://latex.codecogs.com/png.latex?e=i%5Csim%20j">. It is easy to see that the zeros of the coboundary map correspond to global sections, because <img src="https://latex.codecogs.com/png.latex?(%5Cdelta_%5Cmathcal%7BF%7D%5Cmathbf%7Bx%7D)_e=0"> precisely when <img src="https://latex.codecogs.com/png.latex?%5Cmathcal%7BF%7D_%7Bi%5Cto%20e%7D(x_i)=%5Cmathcal%7BF%7D_%7Bj%5Cto%20e%7D(x_j)">.</p>
<p>To introduce different coordination goals, we can define potential functions on each edge. For an edge <img src="https://latex.codecogs.com/png.latex?e%5Cin%20E">, a potential on <img src="https://latex.codecogs.com/png.latex?e"> is a function <img src="https://latex.codecogs.com/png.latex?U_e%5Ccolon%5Cmathcal%7BF%7D(e)%5Cto%5Cmathbb%7BR%7D"> which we can think of as defining a cost for each element of the edge stalk. The function <img src="https://latex.codecogs.com/png.latex?U(%5Cmathbf%7By%7D)%20=%20%5Csum_%7Be%5Cin%20E%7DU_e(y_e)"> defines the total cost for all edges of the cellular sheaf. Given such a <img src="https://latex.codecogs.com/png.latex?U">, the coordination goal of our multi-agent system is <img src="https://latex.codecogs.com/png.latex?%0A%5Cunderset%7B%5Cmathbf%7Bx%7D%5Cin%20C%5E0(G;%5Cmathcal%7BF%7D)%7D%7B%5Ctextnormal%7Bminimize%20%7D%7D%20U(%5Cdelta_%5Cmathcal%7BF%7D%5Cmathbf%7Bx%7D).%0A"> In other words, we want our system to reach a state which minimizes the edge potential functions after being passed through the coboundary map. To get some intuition, the following table summarizes the edge potential functions associated with various coordination goals.</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th style="text-align: left;">Potential Function <img src="https://latex.codecogs.com/png.latex?U_e(y)"></th>
<th style="text-align: left;">Coordination Goal</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?(1/2)%5C%7Cy%5C%7C_2%5E2"></td>
<td style="text-align: left;">Consensus</td>
</tr>
<tr class="even">
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?(1/2)%5C%7Cy-b%5C%7C_2%5E2"></td>
<td style="text-align: left;">Reach displacement of <img src="https://latex.codecogs.com/png.latex?b"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?(%5C%7Cy%5C%7C_2%5E2-r%5E2)%5E2"></td>
<td style="text-align: left;">Reach distance of <img src="https://latex.codecogs.com/png.latex?r"></td>
</tr>
</tbody>
</table>
</section>
<section id="solving-coordination-problems" class="level2">
<h2 class="anchored" data-anchor-id="solving-coordination-problems">Solving Coordination Problems</h2>
<p>We implemented cellular sheaves with nonlinear potential functions and a solver for coordination problems in our package <a href="https://github.com/AlgebraicJulia/AlgebraicOptimization.jl"><code>AlgebraicOptimization.jl</code></a>. In our framework, a multi-agent optimal control problem consists of</p>
<ul>
<li>A cellular sheaf <img src="https://latex.codecogs.com/png.latex?%5Cmathcal%7BF%7D"> on a graph <img src="https://latex.codecogs.com/png.latex?G"></li>
<li>Potential functions for each edge</li>
<li>Single-agent optimal control objectives (specified as <a href="https://github.com/jump-dev/JuMP.jl"><code>JuMP.jl</code></a> models in our implementation) for each vertex.</li>
</ul>
<p>The overall problem is to then compute control inputs over a fixed time horizon which minimize each agents optimal control objective as much as possible while satisfying the coordination goal by the end of the time horizon.</p>
<p>Here as some examples of different coordination goals being reached by a 3 agent system, where each agents’ dynamics are given by 2-dimensional double integrators. Details on each example as well as the code to generate the plots can be found in the <a href="https://algebraicjulia.github.io/AlgebraicOptimization.jl/dev/">docs</a></p>
<section id="consensus" class="level3">
<h3 class="anchored" data-anchor-id="consensus">Consensus</h3>
<p>For this example, the agents are to reach consensus in the <img src="https://latex.codecogs.com/png.latex?x">-axis while reaching individual tracking goals in the <img src="https://latex.codecogs.com/png.latex?y">-axis. Thus each agent’s subproblem is a linear quadratic tracking problem in <img src="https://latex.codecogs.com/png.latex?y">-space with a quadratic cost on the control activation. The coordination sheaf is defined over a fully connected communication topology, where each restriction map is simply the projection onto the <img src="https://latex.codecogs.com/png.latex?x"> coordinate. Edge potentials are the standard norm squared potential function encoding the consensus goal. The results of this controller run for 100 iterations are as follows.</p>
<p><img src="https://blog.algebraicjulia.org/post/2025/04/sheafcoordination/tracking-consensus.png" class="img-fluid"></p>
</section>
<section id="stationary-formation" class="level3">
<h3 class="anchored" data-anchor-id="stationary-formation">Stationary Formation</h3>
<p>The goal in this example is for the agents reach a triangle formation centered at the origin. As such, each agent’s subproblem is a standard linear quadratic regulation problem to drive the state to 0 with a quadratic penalty on control activation. The coordination sheaf is over a fully connected communication topology with the restriction maps projecting onto the position components of the state vector. The formation goal is encoded using edge potential functions of the form <img src="https://latex.codecogs.com/png.latex?U_e(y)=(1/2)%5C%7Cy-b_e%5C%7C_2%5E2"> for desired <img src="https://latex.codecogs.com/png.latex?b_e">. The results of this controller run for 100 iterations are as follows.</p>
<p><img src="https://blog.algebraicjulia.org/post/2025/04/sheafcoordination/stationary-formation.png" class="img-fluid"></p>
</section>
<section id="flocking" class="level3">
<h3 class="anchored" data-anchor-id="flocking">Flocking</h3>
<p>For this example, agents implement the standard flocking goal of reaching consensus in velocities while staying a fixed distance away from all other agents. The constant sheaf <img src="https://latex.codecogs.com/png.latex?%5Cunderline%7B%5Cmathbb%7BR%7D%7D%5E4"> on a fully connected communication topology along with potential functions summing the standard consensus potential function on the velocity components and the fixed distance potential function with <img src="https://latex.codecogs.com/png.latex?r%5E2=5"> on the position components. Each agents’ objective is to minimize total control activation. Additionally, a designated leader agent tracks a constant rightward velocity vector. The results of this controller run for 65 iterations are as follows. Computing the distance between each agent confirms that they reached the desired pairwise distance of <img src="https://latex.codecogs.com/png.latex?%5Csqrt%7B5%7D">.</p>
<p><img src="https://blog.algebraicjulia.org/post/2025/04/sheafcoordination/flocking.png" class="img-fluid"></p>
</section>
<section id="moving-formation" class="level3">
<h3 class="anchored" data-anchor-id="moving-formation">Moving Formation</h3>
<p>This example combines a formation goal in positions with a consensus goal in velocities. As such, the coordination sheaf is the constant sheaf <img src="https://latex.codecogs.com/png.latex?%5Cunderline%7B%5Cmathbb%7BR%7D%7D%5E4"> on the three vertex path graph. This encodes a leader-follower topology with the middle agent in the path acting as the leader. The leader’s objective is to track a constant rightward velocity vector and minimize its control actuation while the followers’ objectives are to simply minimize control actuation. The edge potential functions are of the form <img src="https://latex.codecogs.com/png.latex?U_e(y)=(1/2)%5C%7Cy-b_e%5C%7C_2%5E2"> where the velocity coordinates of each <img src="https://latex.codecogs.com/png.latex?b_e"> are 0 encoding consensus in velocity while the position coordinates are chosen to achieve a fixed displacement between the leader and its followers. The results of this controller run for 160 iterations are as follows.</p>
<p><img src="https://blog.algebraicjulia.org/post/2025/04/sheafcoordination/moving-formation.png" class="img-fluid"></p>


</section>
</section>

 ]]></description>
  <category>dynamical systems</category>
  <category>optimization</category>
  <category>planning</category>
  <guid>https://blog.algebraicjulia.org/post/2025/04/sheafcoordination/</guid>
  <pubDate>Fri, 11 Apr 2025 00:00:00 GMT</pubDate>
  <media:content url="https://blog.algebraicjulia.org/post/2025/04/sheafcoordination/vehicles.png" medium="image" type="image/png" height="105" width="144"/>
</item>
<item>
  <title>Tree Decompositions in Julia</title>
  <dc:creator>Richard Samuelson</dc:creator>
  <link>https://blog.algebraicjulia.org/post/2025/04/cliquetrees/</link>
  <description><![CDATA[ 





<div class="hidden">
<p>$$ <!-- Number systems --> </p>
<!-- Categories -->
<!-- Graphs -->
<!-- Double categories -->
<!-- Acsets -->
<!-- Wiring diagrams -->
<!-- Dynamical systems -->
<p>$$</p>
</div>
<p>The newest member of the AlgebraicJulia family is <a href="https://github.com/AlgebraicJulia/CliqueTrees.jl">CliqueTrees.jl</a>. Originally written as a backend to <a href="https://github.com/AlgebraicJulia/StructuredDecompositions.jl">StructuredDecompositions.jl</a>, the package has taken on a life of its own, and it is now used by packages across the Julia ecosystem. Its dependants include</p>
<ul>
<li><a href="https://github.com/sisl/BayesNets.jl">BayesNets.jl</a></li>
<li><a href="https://github.com/mschauer/CausalInference.jl">CausalInference.jl</a></li>
<li><a href="https://github.com/JuliaLinearAlgebra/BandedMatrices.jl">BandedMatrices.jl</a></li>
<li><a href="https://github.com/jump-dev/SumOfSquares.jl">SumOfSquares.jl</a></li>
<li><a href="https://github.com/wangjie212/TSSOS">TSSOS.jl</a></li>
<li><a href="https://github.com/TensorBFS/OMEinsumContractionOrders.jl">OMEinsumContractionOrders.jl</a></li>
<li><a href="https://github.com/gdalle/SparseMatrixColorings.jl">SparseMatrixColorings.jl</a></li>
</ul>
<p>as well as the AlgebraicJulia packages <a href="https://github.com/AlgebraicJulia/StructuredDecompositions.jl">StructuredDecompositions.jl</a> and <a href="https://github.com/AlgebraicJulia/CategoricalTensorNetworks.jl">CategoricalTensorNetworks.jl</a>. CliqueTrees.jl performs two related computations: it constructs <em>tree decompositions</em> and <em>chordal extensions</em> of graphs.</p>
<section id="tree-decompositions" class="level2">
<h2 class="anchored" data-anchor-id="tree-decompositions">Tree Decompositions</h2>
<p>Let <img src="https://latex.codecogs.com/png.latex?G%20=%20(V_G,%20E_G)"> be a simple graph and <img src="https://latex.codecogs.com/png.latex?B%20=%20%5C%7BB_1,%20%5Cdots,%20B_n%5C%7D"> a family of subsets <img src="https://latex.codecogs.com/png.latex?B_i%20%5Csubseteq%20V_G">. Then a tree <img src="https://latex.codecogs.com/png.latex?T%20=%20(B,%20E_T)"> is called a <em>tree decomposition</em> of <img src="https://latex.codecogs.com/png.latex?G">—also a <em>junction tree</em>, <em>join tree</em>, or <em>clique tree</em>—if it satisfies the following properties.</p>
<ol type="1">
<li><p>For all vertices <img src="https://latex.codecogs.com/png.latex?v%20%5Cin%20V_G">, the set <img src="https://latex.codecogs.com/png.latex?%0A%5C%7B%20B_i%20%5Cin%20B%20%5Cmid%20v%20%5Cin%20B_i%20%5C%7D%0A"> induces a nonempty connected subgraph of <img src="https://latex.codecogs.com/png.latex?T">.</p></li>
<li><p>For all edges <img src="https://latex.codecogs.com/png.latex?%5C%7Bv,%20w%5C%7D%20%5Cin%20E_G">, the set <img src="https://latex.codecogs.com/png.latex?%0A%5C%7B%20B_i%20%5Cin%20B%20%5Cmid%20v%20%5Cin%20B_i%20%5Ctext%7B%20and%20%7D%20w%20%5Cin%20B_i%5C%7D%0A"> is nonempty.</p></li>
</ol>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2025/04/cliquetrees/tree_decomposition.png" class="img-fluid quarto-figure quarto-figure-center figure-img" width="600"></p>
</figure>
</div>
<p>The <em>width</em> of a tree decomposition <img src="https://latex.codecogs.com/png.latex?T"> is the number <img src="https://latex.codecogs.com/png.latex?%0A%5Ctau%20:=%20%5Cmax%20%5C%7B%20%5Clvert%20B_i%20%5Crvert%20%5Cmid%20B_i%20%5Cin%20B%20%5C%7D%20-%201,%0A"> and the <em>treewidth</em> of a graph is the width of its smallest tree decomposition. Tree decompositions of small width are highly desirable, for they can be used to implement fast algorithms on graphs and graph structured data. To see how this works, we will look at an example from dynamic programming in the next section.</p>
</section>
<section id="dynamic-programming" class="level2">
<h2 class="anchored" data-anchor-id="dynamic-programming">Dynamic Programming</h2>
<p>Suppose we want to minimize a function <img src="https://latex.codecogs.com/png.latex?%0A%20%20%20%20f:%20X%20%5Ctimes%20Y%20%5Ctimes%20Z%20%5Cto%20%5Cmathbb%7BR%7D%0A"> where <img src="https://latex.codecogs.com/png.latex?%5Clvert%20X%20%5Crvert%20=%20%5Clvert%20Y%20%5Crvert%20=%20%5Clvert%20Z%20%5Crvert%20=%20n">. Since <img src="https://latex.codecogs.com/png.latex?X">, <img src="https://latex.codecogs.com/png.latex?Y">, and <img src="https://latex.codecogs.com/png.latex?Z"> are finite sets, we can find the minimum in <img src="https://latex.codecogs.com/png.latex?n%5E3"> time by enumerating every triple <img src="https://latex.codecogs.com/png.latex?(x,%20y,%20z)%20%5Cin%20X%20%5Ctimes%20Y%20%5Ctimes%20Z">. In general, there is no faster solution. However, if <img src="https://latex.codecogs.com/png.latex?f"> is of the form <img src="https://latex.codecogs.com/png.latex?f%20=%20g%20+%20h"> for some functions <img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Baligned%7D%0A%20%20%20%20g:%20X%20%5Ctimes%20Y%20&amp;%5Cto%20%5Cmathbb%7BR%7D%5C%5C%0A%20%20%20%20h:%20Y%20%5Ctimes%20Z%20&amp;%5Cto%20%5Cmathbb%7BR%7D%5C%5C%0A%5Cend%7Baligned%7D%0A"> then we can do the following. For all <img src="https://latex.codecogs.com/png.latex?y%20%5Cin%20Y">, we compute and record the number <img src="https://latex.codecogs.com/png.latex?%0A%20%20%20%20h%5E*(y)%20:=%20%5Cmin%20%5C%7B%20h(y,%20z)%20%5Cmid%20z%20%5Cin%20Z%20%5C%7D.%0A"> Then we compute the minimum of the sum <img src="https://latex.codecogs.com/png.latex?%0A%20%20%20%20g(x,%20y)%20+%20h%5E*(y).%0A"> Both quantities can be computed in <img src="https://latex.codecogs.com/png.latex?n%5E2"> time, so the time complexity of the second procedure is <img src="https://latex.codecogs.com/png.latex?n%5E2">. What we have done is take advantage of the fact that the variables <img src="https://latex.codecogs.com/png.latex?x"> and <img src="https://latex.codecogs.com/png.latex?z"> are not directly coupled, but rather related to each other via the variable <img src="https://latex.codecogs.com/png.latex?y">. Another way of expressing this observation is to state that the <em>interaction graph</em> of <img src="https://latex.codecogs.com/png.latex?f"> admits the following tree decomposition.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2025/04/cliquetrees/interaction_graph.png" class="img-fluid quarto-figure quarto-figure-center figure-img" width="400"></p>
</figure>
</div>
<p>This trick is generalized by Algorithm 7.1 in <a href="https://www.nowpublishers.com/article/Details/OPT-006">Vandenberghe and Andersen, 2015</a>, which computes the minimum of a function <img src="https://latex.codecogs.com/png.latex?f:%20X_1%20%5Ctimes%20%5Cdots%20%5Ctimes%20X_n%20%5Cto%20%5Cmathbb%7BR%7D"> of the form <img src="https://latex.codecogs.com/png.latex?%0A%20%20%20%20f%20=%20%5Csum_%7Bi%20=%201%7D%5Em%20f_i%0A"> The algorithm takes a tree decomposition as one of its input parameters, and its runtime is determinded by the width of the decomposition.</p>
</section>
<section id="other-applications" class="level2">
<h2 class="anchored" data-anchor-id="other-applications">Other Applications</h2>
<p>Perhaps the most sucessful application of tree decompositions to numerical computing is in sparse matrix software. Libraries like SuiteSparse and HSL construct tree decompositions during the <em>symbolic factorization</em> stge of their Cholesky and LU factorization routines. Other applications include</p>
<ul>
<li>convex optimization</li>
<li>tensor network contraction</li>
<li>probabilistic inference</li>
</ul>
<p>all of which are present in the Julia ecosystem in packages like <a href="https://github.com/oxfordcontrol/Clarabel.jl">Clarabel.jl</a>, <a href="https://github.com/TensorBFS/OMEinsumContractionOrders.jl">OMEinsumContractionOrders.jl</a>, and <a href="https://github.com/mroavi/JunctionTrees.jl">JunctionTrees.jl</a>.</p>
</section>
<section id="engineering" class="level2">
<h2 class="anchored" data-anchor-id="engineering">Engineering</h2>
<p>Let <img src="https://latex.codecogs.com/png.latex?G%20=%20(V_G,%20E_G)"> be a simple graph. Every permutation <img src="https://latex.codecogs.com/png.latex?%5Csigma:%20V_G%20%5Cto%20V_G"> on the vertices of <img src="https://latex.codecogs.com/png.latex?G"> induces a tree decomposition on <img src="https://latex.codecogs.com/png.latex?G"> via a procedure called <em>vertex elimination</em>. Furthermore, the induced tree decomposition can be computed in almost-linear time, and the implementation in CliqueTrees.jl is in practice extremely fast. Hence, the problem of finding a tree decomposition of <img src="https://latex.codecogs.com/png.latex?G"> can be reduced to the problem of finding a permutation of <img src="https://latex.codecogs.com/png.latex?V_G">. CliqueTrees.jl implements a number of algorithms for solving this problem.</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th style="text-align: left;">type</th>
<th style="text-align: left;">name</th>
<th style="text-align: left;">time</th>
<th style="text-align: left;">space</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;"><a href="https://algebraicjulia.github.io/CliqueTrees.jl/dev/api/#CliqueTrees.BFS"><code>BFS</code></a></td>
<td style="text-align: left;">breadth-first search</td>
<td style="text-align: left;">O(m + n)</td>
<td style="text-align: left;">O(n)</td>
</tr>
<tr class="even">
<td style="text-align: left;"><a href="https://algebraicjulia.github.io/CliqueTrees.jl/dev/api/#CliqueTrees.MCS"><code>MCS</code></a></td>
<td style="text-align: left;">maximum cardinality search</td>
<td style="text-align: left;">O(m + n)</td>
<td style="text-align: left;">O(n)</td>
</tr>
<tr class="odd">
<td style="text-align: left;"><a href="https://algebraicjulia.github.io/CliqueTrees.jl/dev/api/#CliqueTrees.LexBFS"><code>LexBFS</code></a></td>
<td style="text-align: left;">lexicographic breadth-first search</td>
<td style="text-align: left;">O(m + n)</td>
<td style="text-align: left;">O(m + n)</td>
</tr>
<tr class="even">
<td style="text-align: left;"><a href="https://algebraicjulia.github.io/CliqueTrees.jl/dev/api/#CliqueTrees.RCMMD"><code>RCMMD</code></a></td>
<td style="text-align: left;">reverse Cuthill-Mckee (minimum degree)</td>
<td style="text-align: left;">O(m + n)</td>
<td style="text-align: left;">O(m + n)</td>
</tr>
<tr class="odd">
<td style="text-align: left;"><a href="https://algebraicjulia.github.io/CliqueTrees.jl/dev/api/#CliqueTrees.RCMGL"><code>RCMGL</code></a></td>
<td style="text-align: left;">reverse Cuthill-Mckee (George-Liu)</td>
<td style="text-align: left;">O(m + n)</td>
<td style="text-align: left;">O(m + n)</td>
</tr>
<tr class="even">
<td style="text-align: left;"><a href="https://algebraicjulia.github.io/CliqueTrees.jl/dev/api/#CliqueTrees.MCSM"><code>MCSM</code></a></td>
<td style="text-align: left;">maximum cardinality search (minimal)</td>
<td style="text-align: left;">O(mn)</td>
<td style="text-align: left;">O(n)</td>
</tr>
<tr class="odd">
<td style="text-align: left;"><a href="https://algebraicjulia.github.io/CliqueTrees.jl/dev/api/#CliqueTrees.LexM"><code>LexM</code></a></td>
<td style="text-align: left;">lexicographic breadth-first search (minimal)</td>
<td style="text-align: left;">O(mn)</td>
<td style="text-align: left;">O(n)</td>
</tr>
<tr class="even">
<td style="text-align: left;"><a href="https://algebraicjulia.github.io/CliqueTrees.jl/dev/api/#CliqueTrees.AMF"><code>AMF</code></a></td>
<td style="text-align: left;">approximate minimum fill</td>
<td style="text-align: left;">O(mn)</td>
<td style="text-align: left;">O(m + n)</td>
</tr>
<tr class="odd">
<td style="text-align: left;"><a href="https://algebraicjulia.github.io/CliqueTrees.jl/dev/api/#CliqueTrees.MF"><code>MF</code></a></td>
<td style="text-align: left;">minimum fill</td>
<td style="text-align: left;">O(mn²)</td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"><a href="https://algebraicjulia.github.io/CliqueTrees.jl/dev/api/#CliqueTrees.MMD"><code>MMD</code></a></td>
<td style="text-align: left;">multiple minimum degree</td>
<td style="text-align: left;">O(mn²)</td>
<td style="text-align: left;">O(m + n)</td>
</tr>
<tr class="odd">
<td style="text-align: left;"><a href="https://algebraicjulia.github.io/CliqueTrees.jl/dev/api/#CliqueTrees.MinimalChordal"><code>MinimalChordal</code></a></td>
<td style="text-align: left;">MinimalChordal</td>
<td style="text-align: left;"></td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"><a href="https://algebraicjulia.github.io/CliqueTrees.jl/dev/api/#CliqueTrees.CompositeRotations"><code>CompositeRotations</code></a></td>
<td style="text-align: left;">elimination tree rotation</td>
<td style="text-align: left;">O(m + n)</td>
<td style="text-align: left;">O(m + n)</td>
</tr>
<tr class="odd">
<td style="text-align: left;"><a href="https://algebraicjulia.github.io/CliqueTrees.jl/dev/api/#CliqueTrees.RuleReduction"><code>RuleReduction</code></a></td>
<td style="text-align: left;">treewith-safe rule-based reduction</td>
<td style="text-align: left;"></td>
<td style="text-align: left;"></td>
</tr>
<tr class="even">
<td style="text-align: left;"><a href="https://algebraicjulia.github.io/CliqueTrees.jl/dev/api/#CliqueTrees.ComponentReduction"><code>ComponentReduction</code></a></td>
<td style="text-align: left;">connected component reduction</td>
<td style="text-align: left;"></td>
<td style="text-align: left;"></td>
</tr>
</tbody>
</table>
<p>Several more algorithms are implemented as package extensions.</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th style="text-align: left;">type</th>
<th style="text-align: left;">name</th>
<th style="text-align: left;">time</th>
<th style="text-align: left;">space</th>
<th style="text-align: left;">package</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;"><a href="https://algebraicjulia.github.io/CliqueTrees.jl/dev/api/#CliqueTrees.AMD"><code>AMD</code></a></td>
<td style="text-align: left;">approximate minimum degree</td>
<td style="text-align: left;">O(mn)</td>
<td style="text-align: left;">O(m + n)</td>
<td style="text-align: left;"><a href="https://github.com/JuliaSmoothOptimizers/AMD.jl">AMD.jl</a></td>
</tr>
<tr class="even">
<td style="text-align: left;"><a href="https://algebraicjulia.github.io/CliqueTrees.jl/dev/api/#CliqueTrees.SymAMD"><code>SymAMD</code></a></td>
<td style="text-align: left;">column approximate minimum degree</td>
<td style="text-align: left;">O(mn)</td>
<td style="text-align: left;">O(m + n)</td>
<td style="text-align: left;"><a href="https://github.com/JuliaSmoothOptimizers/AMD.jl">AMD.jl</a></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><a href="https://algebraicjulia.github.io/CliqueTrees.jl/dev/api/#CliqueTrees.METIS"><code>METIS</code></a></td>
<td style="text-align: left;">multilevel nested dissection</td>
<td style="text-align: left;"></td>
<td style="text-align: left;"></td>
<td style="text-align: left;"><a href="https://github.com/JuliaSparse/Metis.jl">Metis.jl</a></td>
</tr>
<tr class="even">
<td style="text-align: left;"><a href="https://algebraicjulia.github.io/CliqueTrees.jl/dev/api/#CliqueTrees.Spectral"><code>Spectral</code></a></td>
<td style="text-align: left;">spectral ordering</td>
<td style="text-align: left;"></td>
<td style="text-align: left;"></td>
<td style="text-align: left;"><a href="https://github.com/danspielman/Laplacians.jl">Laplacians.jl</a></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><a href="https://algebraicjulia.github.io/CliqueTrees.jl/dev/api/#CliqueTrees.BT"><code>BT</code></a></td>
<td style="text-align: left;">Bouchitte-Todinca</td>
<td style="text-align: left;"></td>
<td style="text-align: left;"></td>
<td style="text-align: left;"><a href="https://github.com/ArrogantGao/TreeWidthSolver.jl">TreeWidthSolver.jl</a></td>
</tr>
<tr class="even">
<td style="text-align: left;"><a href="https://algebraicjulia.github.io/CliqueTrees.jl/dev/api/#CliqueTrees.SAT"><code>SAT</code></a></td>
<td style="text-align: left;">SAT encoding (picosat)</td>
<td style="text-align: left;"></td>
<td style="text-align: left;"></td>
<td style="text-align: left;"><a href="https://github.com/JuliaBinaryWrappers/PicoSAT_jll.jl">PicoSAT_jll.jl</a></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><a href="https://algebraicjulia.github.io/CliqueTrees.jl/dev/api/#CliqueTrees.SAT"><code>SAT</code></a></td>
<td style="text-align: left;">SAT encoding (cryptominisat)</td>
<td style="text-align: left;"></td>
<td style="text-align: left;"></td>
<td style="text-align: left;"><a href="https://github.com/JuliaBinaryWrappers/CryptoMiniSat_jll.jl">CryptoMiniSat_jll.jl</a></td>
</tr>
</tbody>
</table>
<p>This list includes exact, exponential-time algorithms like <code>BT</code> and <code>SAT</code>, which are guaranteed to create decompositions of minimal width, as well as linear-time heuristic algorithms like <code>AMF</code> and <code>AMD</code> that can decompose graphs with millions of vertices. Other algorithms, like <code>MinimalChordal</code> and <code>RuleReduction</code> are pre or post-processors; they are parametrized by another algorithm and work by transforming its input or output. These meta-algorithms are useful enough that some packages prefer to call their own tree decomposition algorithms through CliqueTrees.jl.</p>
</section>
<section id="coming-soon" class="level2">
<h2 class="anchored" data-anchor-id="coming-soon">Coming Soon</h2>
<p>In a subsequent blog post, I will discuss a categorification of tree decompositions called <em>structured decompositions</em>.</p>


</section>

 ]]></description>
  <category>graphs</category>
  <guid>https://blog.algebraicjulia.org/post/2025/04/cliquetrees/</guid>
  <pubDate>Mon, 07 Apr 2025 00:00:00 GMT</pubDate>
  <media:content url="https://blog.algebraicjulia.org/post/2025/04/cliquetrees/logo.png" medium="image" type="image/png" height="132" width="144"/>
</item>
<item>
  <title>JuMP-ing with AlgebraicJulia II: A practical optimization model</title>
  <dc:creator>Sean L. Wu</dc:creator>
  <link>https://blog.algebraicjulia.org/post/2025/03/optim-netflow/</link>
  <description><![CDATA[ 





<div class="hidden">
<p>$$ <!-- Number systems --> </p>
<!-- Categories -->
<!-- Graphs -->
<!-- Double categories -->
<!-- Acsets -->
<!-- Wiring diagrams -->
<!-- Dynamical systems -->
<p>$$</p>
</div>
<p>This is the second blog post in a series about tools from AlgebraicJulia to ease mathematical programming using the <a href="https://jump.dev/">JuMP</a> framework. If you haven’t seen <a href="../../../2024/09/ijklm/">JuMP-ing with AlgebraicJulia I: The IJKLM model</a> yet, I suggest you take a look at it first!</p>
<p>The <a href="https://en.wikipedia.org/wiki/Multi-commodity_flow_problem">multi-commodity network flow problem</a> is a foundational model in many fields which rely on mathematical programming such as logistics and telecommunications routing. Models of this type are called network flow problems and optimal solutions tell us the best way to send things on edges between vertices such that demands are fulfilled, subject to various flow and supply constraints. There is a <a href="https://jump.dev/JuMP.jl/stable/tutorials/linear/multi_commodity_network/">JuMP tutorial</a> page which describes a dataset used to parameterize the multi-commodity network flow problem, and solves it with JuMP. Here we show how the same model can be expressed within a single ACSet, and how to use some of the graph visualization tools of Catlab (using <a href="https://graphviz.org/">GraphViz</a>) to inspect your data and optimization model.</p>
<p>In this variant of the model, we consider a set of vertices <img src="https://latex.codecogs.com/png.latex?i%20%5Cin%20%5Cmathcal%7BV%7D">, each of which has a (potentially zero) supply capacity <img src="https://latex.codecogs.com/png.latex?u%5Es_%7Bi,p%7D">, supply cost <img src="https://latex.codecogs.com/png.latex?c%5Es_%7Bi,p%7D">, and demand <img src="https://latex.codecogs.com/png.latex?d_%7Bi,p%7D"> for each commodity <img src="https://latex.codecogs.com/png.latex?p%20%5Cin%20P">. The vertices are connected by a set of edges <img src="https://latex.codecogs.com/png.latex?(i,%20j)%20%5Cin%20%5Cmathcal%7BE%7D">, which have a shipment cost <img src="https://latex.codecogs.com/png.latex?c%5Ex_%7Bi,j,p%7D"> and a total flow capacity of <img src="https://latex.codecogs.com/png.latex?u%5Ex_%7Bi,j%7D">.</p>
<p>The decision variables are the purchased quantity of each commodity at each vertex <img src="https://latex.codecogs.com/png.latex?s_%7Bi,p%7D">, as well as the optimal shipment of each commodity along each edge <img src="https://latex.codecogs.com/png.latex?x_%7Bi,j,p%7D"> that minimizes the total cost.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Baligned%7D%0A%5Cmin%20%5C;%5C;%20&amp;%20%5Csum_%7B(i,j)%5Cin%5Cmathcal%7BE%7D,%20p%20%5Cin%20P%7D%20c%5Ex_%7Bi,j,p%7D%20x_%7Bi,j,p%7D%20+%20%5Csum_%7Bi%5Cin%5Cmathcal%7BV%7D,%20p%20%5Cin%20P%7D%20c%5Es_%7Bi,p%7D%20s_%7Bi,p%7D%20%5C%5C%0As.t.%20%5C;%5C;%20&amp;%20s_%7Bi,p%7D%20+%20%5Csum_%7B(j,%20i)%20%5Cin%20%5Cmathcal%7BE%7D%7D%20x_%7Bj,i,p%7D%20-%20%5Csum_%7B(i,j)%20%5Cin%20%5Cmathcal%7BE%7D%7D%20x_%7Bi,j,p%7D%20=%20d_%7Bi,p%7D%20&amp;%20%5Cforall%20i%20%5Cin%20%5Cmathcal%7BV%7D,%20p%20%5Cin%20P%20%5C%5C%0A%20%20%20%20%20%20%20%20%20%20&amp;%20x_%7Bi,j,p%7D%20%5Cge%200%20%20%20%20%20%20%20%20%20%20%20&amp;%20%5Cforall%20(i,%20j)%20%5Cin%20%5Cmathcal%7BE%7D,%20p%20%5Cin%20P%20%5C%5C%0A%20%20%20%20%20%20%20%20%20%20&amp;%20%5Csum_%7Bp%20%5Cin%20P%7D%20x_%7Bi,j,p%7D%20%5Cle%20u%5Ex_%7Bi,j%7D%20%20%20%20%20%20%20%20%20%20%20&amp;%20%5Cforall%20(i,%20j)%20%5Cin%20%5Cmathcal%7BE%7D%20%5C%5C%0A%20%20%20%20%20%20%20%20%20%20&amp;%200%20%5Cle%20s_%7Bi,p%7D%20%5Cle%20u%5Es_%7Bi,p%7D%20&amp;%20%5Cforall%20i%20%5Cin%20%5Cmathcal%7BV%7D,%20p%20%5Cin%20P%0A%5Cend%7Baligned%7D%0A"></p>
<section id="data-import" class="level2">
<h2 class="anchored" data-anchor-id="data-import">Data Import</h2>
<p>First let’s load the data that is used to parameterize the model. Using the SQLite.jl library, we get each table from the relational database as a <code>DataFrame</code>, as in the JuMP tutorial which can be consulted for details.</p>
<div id="2" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">SQLite</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">SQLite.DBInterface</span></span>
<span id="cb1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">DataFrames</span></span>
<span id="cb1-3"></span>
<span id="cb1-4">filename <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">joinpath</span>(<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@__DIR__</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"commodity_nz.db"</span>);</span>
<span id="cb1-5">db <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> SQLite.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DB</span>(filename)</span>
<span id="cb1-6"></span>
<span id="cb1-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">get_table</span>(db, table)</span>
<span id="cb1-8">    query <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DBInterface.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">execute</span>(db, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SELECT * FROM </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>table<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb1-9">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> DataFrames.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DataFrame</span>(query)</span>
<span id="cb1-10"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb1-11"></span>
<span id="cb1-12">df_shipping <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">get_table</span>(db, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"shipping"</span>)</span>
<span id="cb1-13">df_products <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">get_table</span>(db, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"products"</span>)</span>
<span id="cb1-14">df_supply <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">get_table</span>(db, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"supply"</span>)</span>
<span id="cb1-15">df_demand <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">get_table</span>(db, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"demand"</span>)</span>
<span id="cb1-16"></span>
<span id="cb1-17">df_cost <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataFrames.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">leftjoin</span>(df_shipping, df_products; on <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>product])</span>
<span id="cb1-18">df_cost.flow_cost <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df_cost.cost_per_km <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.*</span> df_cost.distance_km</span></code></pre></div>
</details>
</div>
<p>Unlike the tutorial, we make <code>df_edges</code> containing the <code>(src, tgt)</code> pairs, and <code>df_productvertex</code> which is the product of vertices and products (commodities). We then add the supply capacities, costs, and demands to each element of the product.</p>
<div id="4" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb2-1">places <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unique</span>([df_cost.origin; df_cost.destination])</span>
<span id="cb2-2">products <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unique</span>(df_cost.product)</span>
<span id="cb2-3"></span>
<span id="cb2-4">df_edges<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unique</span>(df_cost[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>, [<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>origin, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>destination]])</span>
<span id="cb2-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">transform!</span>(df_edges, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>origin <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ByRow</span>(o <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb2-6">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">findfirst</span>(o <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.==</span> places)</span>
<span id="cb2-7"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>src)</span>
<span id="cb2-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">transform!</span>(df_edges, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>destination <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ByRow</span>(o <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb2-9">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">findfirst</span>(o <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.==</span> places)</span>
<span id="cb2-10"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>tgt)</span>
<span id="cb2-11"></span>
<span id="cb2-12">df_productvertex <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">crossjoin</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DataFrame</span>(place<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>places), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DataFrame</span>(product<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>products))</span>
<span id="cb2-13"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">leftjoin!</span>(df_productvertex, df_supply, on<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>place<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;:</span>origin, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>product])</span>
<span id="cb2-14"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">leftjoin!</span>(df_productvertex, df_demand, on<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>place<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;:</span>destination, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>product])</span>
<span id="cb2-15">df_productvertex[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ismissing</span>.(df_productvertex.capacity), <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>capacity] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span></span>
<span id="cb2-16">df_productvertex[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ismissing</span>.(df_productvertex.cost), <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>cost] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span></span>
<span id="cb2-17">df_productvertex[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ismissing</span>.(df_productvertex.demand), <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>demand] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span></span></code></pre></div>
</details>
</div>
</section>
<section id="acset-structure" class="level2">
<h2 class="anchored" data-anchor-id="acset-structure">ACSet Structure</h2>
<p>Now we’ll generate a schema which is appropriate to represent the multi-commodity network flow problem. We use schema inheritance to inherit from <code>SchGraph</code>, the schema for simple graphs. Our new objects include <code>Commodity</code> which is the set of commodities considered, <code>CommodityVertex</code> which is the product of <code>Commodity</code> and <code>V</code>, and <code>Shipping</code> which is the product of <code>Commodity</code> and <code>E</code>. With these additional objects, we can conveniently store all the data and variables of the optimization model. We add some additional <code>AttrType</code>s to the schema as well, <code>DecisionVar</code> which will store the <code>JuMP</code> decision variables, and <code>NumVar</code> which stores numeric data (used to parameterize the model).</p>
<div id="6" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb3-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab</span></span>
<span id="cb3-2"></span>
<span id="cb3-3"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@present</span> SchMultiCommodity <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> SchGraph </span><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span>    </span>
<span id="cb3-4">    (CommodityVertex,Commodity,Shipping)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span></span>
<span id="cb3-5">    cv_c<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(CommodityVertex,Commodity)</span>
<span id="cb3-6">    cv_v<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(CommodityVertex,V)</span>
<span id="cb3-7">    s_p<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(Shipping,Commodity)</span>
<span id="cb3-8">    s_e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(Shipping,E)</span>
<span id="cb3-9"></span>
<span id="cb3-10">    Label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AttrType</span></span>
<span id="cb3-11">    vlabel<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Attr</span>(V,Label)</span>
<span id="cb3-12">    plabel<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Attr</span>(Commodity,Label)</span>
<span id="cb3-13"></span>
<span id="cb3-14">    NumVar<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AttrType</span></span>
<span id="cb3-15">    supplycap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Attr</span>(CommodityVertex,NumVar) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># supply capacity</span></span>
<span id="cb3-16">    demand<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Attr</span>(CommodityVertex,NumVar) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># demand</span></span>
<span id="cb3-17">    purcost<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Attr</span>(CommodityVertex,NumVar) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># purchase cost</span></span>
<span id="cb3-18">    shipcost<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Attr</span>(Shipping,NumVar) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># shipment cost</span></span>
<span id="cb3-19">    flowcap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Attr</span>(E,NumVar) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># flow capacity</span></span>
<span id="cb3-20"></span>
<span id="cb3-21">    DecisionVar<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AttrType</span></span>
<span id="cb3-22">    s<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Attr</span>(CommodityVertex,DecisionVar) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># optimal supply</span></span>
<span id="cb3-23">    x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Attr</span>(Shipping,DecisionVar) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># optimal shipment</span></span>
<span id="cb3-24"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb3-25"></span>
<span id="cb3-26"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to_graphviz</span>(SchMultiCommodity, graph_attrs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Dict</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"6"</span>,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>ratio<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fill"</span>))</span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2025/03/optim-netflow/index_files/figure-html/cell-4-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>We next generate the ACSet types from the schema. Note that type inheritance for ACSets is handled seperately from the schema inheritance, so we inherit from <code>HasGraph</code> to take advantage of the Graphs module of Catlab.</p>
<div id="8" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb4-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@abstract_acset_type</span> AbstractMultiCommodity <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> HasGraph</span></span>
<span id="cb4-2"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@acset_type</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">MultiCommodity</span>(SchMultiCommodity, index<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>src,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>tgt,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>cv_c,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>cv_v,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>s_p,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>s_e]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> AbstractMultiCommodity</span></span></code></pre></div>
</details>
</div>
<p>Now we are ready to generate an instance of an ACSet of this type with the data we set up previously. Like the original tutorial, we assume that the capacity of each edge is 30.</p>
<div id="10" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb5-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">JuMP</span></span>
<span id="cb5-2"></span>
<span id="cb5-3">capacity <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span></span>
<span id="cb5-4"></span>
<span id="cb5-5">multinet_acs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@acset</span> MultiCommodity{<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">String</span>,<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Float64</span>,JuMP.VariableRef} <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb5-6">    V<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(places)</span>
<span id="cb5-7">    vlabel<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>places</span>
<span id="cb5-8">    Commodity<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(products)</span>
<span id="cb5-9">    plabel<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>products</span>
<span id="cb5-10">    E<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(df_edges)</span>
<span id="cb5-11">    src<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>df_edges.src</span>
<span id="cb5-12">    tgt<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>df_edges.tgt</span>
<span id="cb5-13">    flowcap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>capacity</span>
<span id="cb5-14"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb5-15"></span>
<span id="cb5-16"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> r <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">eachrow</span>(df_productvertex)</span>
<span id="cb5-17">    v<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">only</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">incident</span>(multinet_acs, r.place, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>vlabel))</span>
<span id="cb5-18">    p<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">only</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">incident</span>(multinet_acs, r.product, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>plabel))</span>
<span id="cb5-19">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_part!</span>(</span>
<span id="cb5-20">        multinet_acs, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>CommodityVertex, </span>
<span id="cb5-21">        cv_v<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>v, cv_c<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>p,</span>
<span id="cb5-22">        supplycap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>r.capacity, demand<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>r.demand, purcost<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>r.cost</span>
<span id="cb5-23">    )</span>
<span id="cb5-24"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb5-25"></span>
<span id="cb5-26"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> r <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">eachrow</span>(df_cost)</span>
<span id="cb5-27">    src<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">only</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">incident</span>(multinet_acs, r.origin, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>vlabel))</span>
<span id="cb5-28">    tgt<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">only</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">incident</span>(multinet_acs, r.destination, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>vlabel))</span>
<span id="cb5-29">    product<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">only</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">incident</span>(multinet_acs, r.product, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>plabel))</span>
<span id="cb5-30">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_part!</span>(</span>
<span id="cb5-31">        multinet_acs, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>Shipping,</span>
<span id="cb5-32">        s_p<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>product, s_e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">only</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">edges</span>(multinet_acs, src, tgt)),</span>
<span id="cb5-33">        shipcost<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>r.flow_cost</span>
<span id="cb5-34">    )</span>
<span id="cb5-35"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
</details>
</div>
<p>Next we’d like to visualize the data and the network we created. Catlab integrates with <a href="https://graphviz.org/">GraphViz</a> for visualizations of graph-like objects, and because we want to customize how the vertices and edges are displayed, we write some code that generates the labels for vertices below. We rely on the ability of GraphViz to generate <a href="https://graphviz.org/doc/info/shapes.html#html">HTML-like labels</a> for vertices. For more information on the syntax, please see the GraphViz documentation.</p>
<p>Below we write two versions of the method that will generate the label for a vertex. <code>make_node_label_optim</code> should be run on an ACSet of type <code>AbstractMultiCommodity</code> after it has been optimized, to print out a table indicating how much of each commodity was supplied by that vertex. The <code>make_node_label_parameters</code> prints out the data that parameterizes the model for each vertex/commodity combination: the maximum supply capacity, demand, and supply cost.</p>
<div id="12" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb6-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab.Graphics.Graphviz.Html</span></span>
<span id="cb6-2"></span>
<span id="cb6-3"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb6-4"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Make a node label for a model that has been optimized.</span></span>
<span id="cb6-5"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb6-6"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">make_node_label_optim</span>(v, acs, label_dict)</span>
<span id="cb6-7">    commodity_v <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">incident</span>(acs, v, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>cv_v)</span>
<span id="cb6-8">    label <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Vector</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{String}</span>()</span>
<span id="cb6-9">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push!</span>(</span>
<span id="cb6-10">        label, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb6-11"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">            &lt;TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0"&gt;</span></span>
<span id="cb6-12"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">            &lt;TR&gt;&lt;TD COLSPAN="2"&gt;</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>(acs[v, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>vlabel])<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">&lt;/TD&gt;&lt;/TR&gt;</span></span>
<span id="cb6-13"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">            &lt;TR&gt;&lt;TD&gt;Product&lt;/TD&gt;&lt;TD&gt;Purchased&lt;/TD&gt;&lt;/TR&gt;</span></span>
<span id="cb6-14"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">        """</span></span>
<span id="cb6-15">    )</span>
<span id="cb6-16">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> cv <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> commodity_v</span>
<span id="cb6-17">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> JuMP.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">value</span>(acs[cv, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>s]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb6-18">            emoji <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> label_dict[acs[cv, (<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>cv_c, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>plabel)]]</span>
<span id="cb6-19">            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push!</span>(</span>
<span id="cb6-20">                label, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb6-21"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">                    &lt;TR&gt;&lt;TD&gt;</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>(emoji)<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">&lt;/TD&gt;&lt;TD&gt;</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>(JuMP.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">value</span>(acs[cv, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>s]))<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">&lt;/TD&gt;&lt;/TR&gt;</span></span>
<span id="cb6-22"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">                """</span></span>
<span id="cb6-23">            )</span>
<span id="cb6-24">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb6-25">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb6-26">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push!</span>(</span>
<span id="cb6-27">        label, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb6-28"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">            &lt;/TABLE&gt;</span></span>
<span id="cb6-29"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">        """</span></span>
<span id="cb6-30">    )</span>
<span id="cb6-31"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb6-32"></span>
<span id="cb6-33"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb6-34"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Make a node label for the model parameters.</span></span>
<span id="cb6-35"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb6-36"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">make_node_label_parameters</span>(v, acs, label_dict)</span>
<span id="cb6-37">    commodity_v <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">incident</span>(acs, v, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>cv_v)</span>
<span id="cb6-38">    label <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Vector</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{String}</span>()</span>
<span id="cb6-39">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push!</span>(</span>
<span id="cb6-40">        label, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb6-41"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">            &lt;TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0"&gt;</span></span>
<span id="cb6-42"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">            &lt;TR&gt;&lt;TD COLSPAN="4"&gt;</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>(acs[v, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>vlabel])<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">&lt;/TD&gt;&lt;/TR&gt;</span></span>
<span id="cb6-43"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">            &lt;TR&gt;&lt;TD&gt;Product&lt;/TD&gt;&lt;TD&gt;Supply Capacity&lt;/TD&gt;&lt;TD&gt;Demand&lt;/TD&gt;&lt;TD&gt;Purchase Cost&lt;/TD&gt;&lt;/TR&gt;</span></span>
<span id="cb6-44"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">        """</span></span>
<span id="cb6-45">    )</span>
<span id="cb6-46">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> cv <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> commodity_v</span>
<span id="cb6-47">        emoji <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> label_dict[acs[cv, (<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>cv_c, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>plabel)]]</span>
<span id="cb6-48">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push!</span>(</span>
<span id="cb6-49">            label, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb6-50"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">                &lt;TR&gt;&lt;TD&gt;</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>(emoji)<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">&lt;/TD&gt;&lt;TD&gt;</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>(acs[cv, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>supplycap])<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">&lt;/TD&gt;&lt;TD&gt;</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>(acs[cv, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>demand])<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">&lt;/TD&gt;&lt;TD&gt;</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>(acs[cv, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>purcost])<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">&lt;/TD&gt;&lt;/TR&gt;</span></span>
<span id="cb6-51"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">            """</span></span>
<span id="cb6-52">        )</span>
<span id="cb6-53">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb6-54">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push!</span>(</span>
<span id="cb6-55">        label, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb6-56"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">            &lt;/TABLE&gt;</span></span>
<span id="cb6-57"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">        """</span></span>
<span id="cb6-58">    )</span>
<span id="cb6-59"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb6-60"></span>
<span id="cb6-61">make_node_label_dict <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Dict</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>optim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span>make_node_label_optim, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>parameters<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span>make_node_label_parameters)</span></code></pre></div>
</details>
</div>
<p>Likewise we have two similar methods for edges. The first, to be run post-optimization, prints the amount of each commodity shipped on each edge. The second prints the shipping cost of each commodity, producing a visualization of the data which parameterizes the mathematical model. Finally we define <code>make_property_graph</code> which generates a property graph using these methods. Because our ACSet type inherits from <code>HasGraph</code>, we can use the <code>to_graphviz_property_graph</code> method defined on any graph-like type to do the hard work, and then simply modify edge and vertex labels.</p>
<div id="14" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb7-1"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb7-2"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Make an edge label for an optmized model.</span></span>
<span id="cb7-3"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb7-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">make_edge_label_optim</span>(<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span>, acs, label_dict)</span>
<span id="cb7-5">    ship <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">incident</span>(acs, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>s_e)</span>
<span id="cb7-6">    label <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Vector</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{String}</span>()</span>
<span id="cb7-7">    edge_label <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> acs[<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span>, (<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>s_e, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>src, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>vlabel)] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" → "</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> acs[<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span>, (<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>s_e, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>tgt, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>vlabel)]</span>
<span id="cb7-8">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push!</span>(</span>
<span id="cb7-9">        label, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb7-10"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">            &lt;TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0"&gt;</span></span>
<span id="cb7-11"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">            &lt;TR&gt;&lt;TD COLSPAN="2"&gt;</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>(edge_label)<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">&lt;/TD&gt;&lt;/TR&gt;</span></span>
<span id="cb7-12"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">            &lt;TR&gt;&lt;TD&gt;Product&lt;/TD&gt;&lt;TD&gt;Shipped&lt;/TD&gt;&lt;/TR&gt;</span></span>
<span id="cb7-13"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">        """</span></span>
<span id="cb7-14">    )</span>
<span id="cb7-15">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> s <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> ship</span>
<span id="cb7-16">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> JuMP.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">value</span>(acs[s, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>x]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span></span>
<span id="cb7-17">            emoji <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> label_dict[acs[s, (<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>s_p, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>plabel)]]</span>
<span id="cb7-18">            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push!</span>(</span>
<span id="cb7-19">                label, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb7-20"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">                    &lt;TR&gt;&lt;TD&gt;</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>(emoji)<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">&lt;/TD&gt;&lt;TD&gt;</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>(JuMP.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">value</span>(acs[s, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>x]))<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">&lt;/TD&gt;&lt;/TR&gt;</span></span>
<span id="cb7-21"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">                """</span></span>
<span id="cb7-22">            )</span>
<span id="cb7-23">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb7-24">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb7-25">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push!</span>(</span>
<span id="cb7-26">        label, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb7-27"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">            &lt;/TABLE&gt;</span></span>
<span id="cb7-28"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">        """</span></span>
<span id="cb7-29">    )</span>
<span id="cb7-30"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb7-31"></span>
<span id="cb7-32"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb7-33"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Make an edge label for the parameters of the model.</span></span>
<span id="cb7-34"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb7-35"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">make_edge_label_parameters</span>(<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span>, acs, label_dict)</span>
<span id="cb7-36">    ship <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">incident</span>(acs, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>s_e)</span>
<span id="cb7-37">    label <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Vector</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{String}</span>()</span>
<span id="cb7-38">    edge_label <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> acs[<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span>, (<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>s_e, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>src, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>vlabel)] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" → "</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> acs[<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span>, (<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>s_e, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>tgt, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>vlabel)]</span>
<span id="cb7-39">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push!</span>(</span>
<span id="cb7-40">        label, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb7-41"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">            &lt;TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0"&gt;</span></span>
<span id="cb7-42"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">            &lt;TR&gt;&lt;TD COLSPAN="2"&gt;</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>(edge_label)<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">&lt;/TD&gt;&lt;/TR&gt;</span></span>
<span id="cb7-43"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">            &lt;TR&gt;&lt;TD&gt;Product&lt;/TD&gt;&lt;TD&gt;Shipping Cost&lt;/TD&gt;&lt;/TR&gt;</span></span>
<span id="cb7-44"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">        """</span></span>
<span id="cb7-45">    )</span>
<span id="cb7-46">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> s <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> ship</span>
<span id="cb7-47">        emoji <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> label_dict[acs[s, (<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>s_p, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>plabel)]]</span>
<span id="cb7-48">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push!</span>(</span>
<span id="cb7-49">            label, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb7-50"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">                &lt;TR&gt;&lt;TD&gt;</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>(emoji)<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">&lt;/TD&gt;&lt;TD&gt;</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>(acs[s, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>shipcost])<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">&lt;/TD&gt;&lt;/TR&gt;</span></span>
<span id="cb7-51"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">            """</span></span>
<span id="cb7-52">        )</span>
<span id="cb7-53">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb7-54">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push!</span>(</span>
<span id="cb7-55">        label, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb7-56"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">            &lt;/TABLE&gt;</span></span>
<span id="cb7-57"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">        """</span></span>
<span id="cb7-58">    )</span>
<span id="cb7-59"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb7-60"></span>
<span id="cb7-61">make_edge_label_dict <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Dict</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>optim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span>make_edge_label_optim,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>parameters<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span>make_edge_label_parameters)</span>
<span id="cb7-62"></span>
<span id="cb7-63"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">make_property_graph</span>(acs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">T</span>; labels, kwargs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">...</span>) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> {T<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AbstractMultiCommodity</span>}</span>
<span id="cb7-64">    pg <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to_graphviz_property_graph</span>(acs; kwargs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">...</span>)   </span>
<span id="cb7-65">    label_dict <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Dict</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"milk"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"🥛"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"kiwifruit"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"🥝"</span>)</span>
<span id="cb7-66">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> v <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parts</span>(acs, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>V)</span>
<span id="cb7-67">        label <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> make_node_label_dict[labels](v, acs, label_dict)</span>
<span id="cb7-68">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set_vprops!</span>(pg, v, label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Html</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">join</span>(label)), shape<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"plain"</span>)</span>
<span id="cb7-69">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb7-70">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parts</span>(acs, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>E)</span>
<span id="cb7-71">        label <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> make_edge_label_dict[labels](<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span>, acs, label_dict)</span>
<span id="cb7-72">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set_eprops!</span>(pg, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span>, label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Html</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">join</span>(label)), shape<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"plain"</span>)</span>
<span id="cb7-73">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb7-74">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> pg</span>
<span id="cb7-75"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
</details>
</div>
<p>Finally, we may visualize the data which parameterizes the optimization model.</p>
<div id="16" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb8-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to_graphviz</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">make_property_graph</span>(multinet_acs, labels<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=:</span>parameters, graph_attrs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Dict</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>rankdir<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TD"</span>)))</span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2025/03/optim-netflow/index_files/figure-html/cell-9-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="optimization-model-in-jump" class="level2">
<h2 class="anchored" data-anchor-id="optimization-model-in-jump">Optimization model in JuMP</h2>
<p>Now we are ready to write the optimization model itself. We take a different approach and write methods that will add the appropriate decision variables, constraints, and objective to the ACSet. Each of them takes as argument the ACSet object and the JuMP model.</p>
<div id="18" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb9-1"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb9-2"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Adds `s` and `x`, decision variables for how much supply to procure of a product at each vertex,</span></span>
<span id="cb9-3"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">and how much of each product to ship along edges.</span></span>
<span id="cb9-4"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb9-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_variables!</span>(acs, model)</span>
<span id="cb9-6">    acs[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>s] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@variable</span>(model, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">≤</span> s[i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parts</span>(acs, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>CommodityVertex)] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">≤</span> acs[i, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>supplycap])</span>
<span id="cb9-7">    acs[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>x] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@variable</span>(model, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">≤</span> x[i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parts</span>(acs, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>Shipping)])</span>
<span id="cb9-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb9-9"></span>
<span id="cb9-10"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb9-11"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Add constraints to respect total flow capacity of all products along each edge.</span></span>
<span id="cb9-12"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb9-13"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_flow_constraint!</span>(acs, model)</span>
<span id="cb9-14">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parts</span>(acs, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>E)</span>
<span id="cb9-15">        <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@constraint</span>(</span>
<span id="cb9-16">            model,</span>
<span id="cb9-17">            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(acs[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">incident</span>(acs, i, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>s_e), <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>x]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">≤</span> acs[i, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>flowcap]</span>
<span id="cb9-18">        )</span>
<span id="cb9-19">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb9-20"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb9-21"></span>
<span id="cb9-22"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb9-23"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Add constraint that, for each product, vertex pair, the supply plus inbound</span></span>
<span id="cb9-24"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">shipping, minus outbound shipping, must equal the demand.</span></span>
<span id="cb9-25"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb9-26"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_conservation_constraint!</span>(acs, model)</span>
<span id="cb9-27">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parts</span>(acs, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>CommodityVertex)</span>
<span id="cb9-28">        v <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> acs[i, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>cv_v]</span>
<span id="cb9-29">        p <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> acs[i, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>cv_c]</span>
<span id="cb9-30"></span>
<span id="cb9-31">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># inbound shipping</span></span>
<span id="cb9-32">        inbound <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">intersect</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">incident</span>(acs, v, (<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>s_e, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>tgt)), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">incident</span>(acs, p, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>s_p))</span>
<span id="cb9-33"></span>
<span id="cb9-34">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># outbound shipping</span></span>
<span id="cb9-35">        outbound <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">intersect</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">incident</span>(acs, v, (<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>s_e, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>src)), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">incident</span>(acs, p, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>s_p))</span>
<span id="cb9-36"></span>
<span id="cb9-37">        <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@constraint</span>(</span>
<span id="cb9-38">            model,</span>
<span id="cb9-39">            acs[i, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>s] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> </span>
<span id="cb9-40">                <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(acs[inbound, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>x], init<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">zero</span>(JuMP.VariableRef)) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> </span>
<span id="cb9-41">                <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(acs[outbound, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>x], init<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">zero</span>(JuMP.VariableRef)) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> acs[i, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>demand]</span>
<span id="cb9-42">        )</span>
<span id="cb9-43">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb9-44"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb9-45"></span>
<span id="cb9-46"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb9-47"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Minimize costs of shipping and costs of purchase</span></span>
<span id="cb9-48"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb9-49"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_objective!</span>(acs, model)</span>
<span id="cb9-50">    <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@objective</span>(</span>
<span id="cb9-51">        model, Min,</span>
<span id="cb9-52">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(acs[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>shipcost] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.*</span> acs[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>x]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> </span>
<span id="cb9-53">            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(acs[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>purcost] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.*</span> acs[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>s])</span>
<span id="cb9-54">    )</span>
<span id="cb9-55"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
</details>
</div>
<p>Finally we are ready to generate and solve the model. We import <code>HiGHS</code> which contains the solvers we will use. We can then add the decision variables, constraints, and objective to the model, and solve it. We then copy the optimized values of the decision variables into the acset, and visualize the solution.</p>
<div id="20" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb10-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># make the JuMP model</span></span>
<span id="cb10-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">HiGHS</span></span>
<span id="cb10-3"></span>
<span id="cb10-4">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> JuMP.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Model</span>(HiGHS.Optimizer)</span>
<span id="cb10-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set_silent</span>(model)</span>
<span id="cb10-6"></span>
<span id="cb10-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_variables!</span>(multinet_acs, model)</span>
<span id="cb10-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_flow_constraint!</span>(multinet_acs, model)</span>
<span id="cb10-9"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_conservation_constraint!</span>(multinet_acs, model)</span>
<span id="cb10-10"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_objective!</span>(multinet_acs, model)</span>
<span id="cb10-11"></span>
<span id="cb10-12"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">optimize!</span>(model)</span>
<span id="cb10-13"></span>
<span id="cb10-14"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to_graphviz</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">make_property_graph</span>(multinet_acs, labels<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=:</span>optim, graph_attrs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Dict</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>rankdir<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TD"</span>)))</span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2025/03/optim-netflow/index_files/figure-html/cell-11-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>We may format the solution in the same way as the original tutorial to confirm that they are the same.</p>
<div id="22" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb11-1"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb11-2"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Format optimized decision variables for comparison. </span></span>
<span id="cb11-3"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb11-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format_output</span>(acs)</span>
<span id="cb11-5">    df_solution_flow <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DataFrame</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tables</span>(acs).Shipping)</span>
<span id="cb11-6">    df_solution_flow.x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> JuMP.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">value</span>.(df_solution_flow.x)</span>
<span id="cb11-7">    df_solution_flow <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df_solution_flow[df_solution_flow.x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.&gt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>]</span>
<span id="cb11-8">    df_solution_flow.origin <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> acs[df_solution_flow.s_e, (<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>src, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>vlabel)]</span>
<span id="cb11-9">    df_solution_flow.destination <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> acs[df_solution_flow.s_e, (<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>tgt, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>vlabel)]</span>
<span id="cb11-10">    df_solution_flow.product <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> acs[df_solution_flow.s_p, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>plabel]</span>
<span id="cb11-11">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select!</span>(df_solution_flow, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Not</span>([<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>s_p,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>s_e,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>shipcost]))</span>
<span id="cb11-12">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rename!</span>(df_solution_flow, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Dict</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>x_flow))</span>
<span id="cb11-13">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> df_solution_flow</span>
<span id="cb11-14"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb11-15"></span>
<span id="cb11-16"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format_output</span>(multinet_acs)</span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="1">
<div><div style="float: left;"><span>9×4 DataFrame</span></div><div style="clear: both;"></div></div><div class="data-frame" style="overflow-x: scroll;">
<table class="data-frame caption-top table table-sm table-striped small" data-quarto-postprocess="true">
<thead>
<tr class="header">
<th class="rowNumber" data-quarto-table-cell-role="th" style="text-align: right; font-weight: bold;">Row</th>
<th style="text-align: left;" data-quarto-table-cell-role="th">x_flow</th>
<th style="text-align: left;" data-quarto-table-cell-role="th">origin</th>
<th style="text-align: left;" data-quarto-table-cell-role="th">destination</th>
<th style="text-align: left;" data-quarto-table-cell-role="th">product</th>
</tr>
<tr class="subheader headerLastRow even">
<th class="rowNumber" data-quarto-table-cell-role="th" style="text-align: right; font-weight: bold;"></th>
<th style="text-align: left;" data-quarto-table-cell-role="th" title="Float64">Float64</th>
<th style="text-align: left;" data-quarto-table-cell-role="th" title="String">String</th>
<th style="text-align: left;" data-quarto-table-cell-role="th" title="String">String</th>
<th style="text-align: left;" data-quarto-table-cell-role="th" title="String">String</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td class="rowNumber" style="text-align: right; font-weight: bold;">1</td>
<td style="text-align: right;">10.0</td>
<td style="text-align: left;">waikato</td>
<td style="text-align: left;">auckland</td>
<td style="text-align: left;">milk</td>
</tr>
<tr class="even">
<td class="rowNumber" style="text-align: right; font-weight: bold;">2</td>
<td style="text-align: right;">2.0</td>
<td style="text-align: left;">waikato</td>
<td style="text-align: left;">wellington</td>
<td style="text-align: left;">milk</td>
</tr>
<tr class="odd">
<td class="rowNumber" style="text-align: right; font-weight: bold;">3</td>
<td style="text-align: right;">2.0</td>
<td style="text-align: left;">tauranga</td>
<td style="text-align: left;">auckland</td>
<td style="text-align: left;">milk</td>
</tr>
<tr class="even">
<td class="rowNumber" style="text-align: right; font-weight: bold;">4</td>
<td style="text-align: right;">2.0</td>
<td style="text-align: left;">tauranga</td>
<td style="text-align: left;">waikato</td>
<td style="text-align: left;">milk</td>
</tr>
<tr class="odd">
<td class="rowNumber" style="text-align: right; font-weight: bold;">5</td>
<td style="text-align: right;">4.0</td>
<td style="text-align: left;">christchurch</td>
<td style="text-align: left;">auckland</td>
<td style="text-align: left;">milk</td>
</tr>
<tr class="even">
<td class="rowNumber" style="text-align: right; font-weight: bold;">6</td>
<td style="text-align: right;">4.0</td>
<td style="text-align: left;">auckland</td>
<td style="text-align: left;">christchurch</td>
<td style="text-align: left;">kiwifruit</td>
</tr>
<tr class="odd">
<td class="rowNumber" style="text-align: right; font-weight: bold;">7</td>
<td style="text-align: right;">20.0</td>
<td style="text-align: left;">waikato</td>
<td style="text-align: left;">auckland</td>
<td style="text-align: left;">kiwifruit</td>
</tr>
<tr class="even">
<td class="rowNumber" style="text-align: right; font-weight: bold;">8</td>
<td style="text-align: right;">2.0</td>
<td style="text-align: left;">waikato</td>
<td style="text-align: left;">wellington</td>
<td style="text-align: left;">kiwifruit</td>
</tr>
<tr class="odd">
<td class="rowNumber" style="text-align: right; font-weight: bold;">9</td>
<td style="text-align: right;">22.0</td>
<td style="text-align: left;">tauranga</td>
<td style="text-align: left;">waikato</td>
<td style="text-align: left;">kiwifruit</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<p>I hope that this post has shown you how ACSets can helpfully structure optimization problems, joining data with the mathematical model in a single data structure, especially those models which can be represented as elaborations of graphs (of which there are many)!</p>


</section>

 ]]></description>
  <category>optimization</category>
  <category>visualization</category>
  <guid>https://blog.algebraicjulia.org/post/2025/03/optim-netflow/</guid>
  <pubDate>Wed, 26 Mar 2025 00:00:00 GMT</pubDate>
  <media:content url="https://blog.algebraicjulia.org/post/2025/03/optim-netflow/network.svg" medium="image" type="image/svg+xml"/>
</item>
<item>
  <title>Catlab Refactor II: Basic Sets</title>
  <dc:creator>Kris Brown</dc:creator>
  <link>https://blog.algebraicjulia.org/post/2025/02/refactor2/</link>
  <description><![CDATA[ 





<div class="hidden">
<p>$$ <!-- Number systems --> </p>
<!-- Categories -->
<!-- Graphs -->
<!-- Double categories -->
<!-- Acsets -->
<!-- Wiring diagrams -->
<!-- Dynamical systems -->
<p>$$</p>
</div>
<blockquote class="blockquote">
<p>This is a sequel post to <a href="https://blog.algebraicjulia.org/post/2025/02/refactor1/">Catlab Refactor I</a>. Check that one out first!</p>
</blockquote>
<p><a href="[Catlab](https://github.com/AlgebraicJulia/Catlab.jl)">Catlab.jl</a> is in the process of updating from <code>v0.16</code> to <code>v0.17</code>. In the new (<code>v0.17</code>) version of Catlab, there is now a module <code>BasicSets</code>, which handles the representation of sets and functions. The theme of this post is that we can use the design pattern of <em>interfaces</em> and <em>implementations</em> (in this post, synonymous with <em>theories</em> and <em>models</em>) to structure our code in a transparent and modular way. This will allow us to use simple types (without type parameters) that have an explicit set of methods that can be expected to work on them, in contrast to more idiomatic Julia which uses a complex type hierarchy and multiple dispatch to control code execution, as described in the <a href="(https://blog.algebraicjulia.org/post/2025/02/refactor1/)">previous post</a>.</p>
<section id="set-interfaces" class="level2">
<h2 class="anchored" data-anchor-id="set-interfaces">Set interfaces</h2>
<p>We saw the interface for <code>ThSet</code> in the previous post. Let’s reproduce it here:</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb1-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@theory</span> ThSet <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb1-2">  X<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE</span></span>
<span id="cb1-3">  Bool′<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE{Bool}</span></span>
<span id="cb1-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">contains</span>(elem<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">X</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Bool′</span></span>
<span id="cb1-5"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>Any implementation of <code>ThSet</code> must pick a Julia datatype for its elements, and we name this type <code>X</code>. However, the set might be smaller than the entire type. So, part of the data one must always provide, in order to implement <code>ThSet</code>, is a membership predicate, <code>contains</code>. This evaluates to <code>true</code> for the elements of the Julia type <code>X</code> which are actually in the set.</p>
<p>Now we define a Julia type, <code>SetOb</code>, which wraps arbitrary implementations of the theory of sets:</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb2-1">ThSet.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Meta</span>.<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@wrapper</span> SetOb <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># `Set` already claimed by Julia!</span></span></code></pre></div>
<p>Our predicate <code>contains</code> only accepts arguments which were of the right Julia type, but we can overload the <code>in</code> method to be more permissive: it returns <code>false</code> if the input was not of the right type rather than throwing a <code>MethodNotFound</code> error.</p>
<div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb3-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Base</span>.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">in</span>(x, set<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AbsSet</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span> </span>
<span id="cb3-2">  ThFinSet.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">contains</span>(set, x)</span>
<span id="cb3-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">catch</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span> </span>
<span id="cb3-4">  <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span> isa <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">MethodError</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">||</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">throw</span>(<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span>)</span>
<span id="cb3-5">  <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">false</span></span>
<span id="cb3-6"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>Next we consider how <code>ThFinSet</code> <em>extends</em> this theory with a Julia iterator<sup>1</sup> and an integer cardinality, i.e.&nbsp;a <code>length</code>.</p>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb4-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@theory</span> ThFinSet <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> ThSet </span><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb4-2">  Int′<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE{Int}</span></span>
<span id="cb4-3">  Any′<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE{Any}</span></span>
<span id="cb4-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int′</span></span>
<span id="cb4-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">iterator</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Any′ </span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># length(collect(iterator()) == length()</span></span>
<span id="cb4-6"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb4-7"></span>
<span id="cb4-8">ThFinSet.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Meta</span>.<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@wrapper</span> FinSet</span>
<span id="cb4-9"></span>
<span id="cb4-10"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">const</span> AbsSet <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Union</span>{SetOb, FinSet} <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># `AbstractSet` already claimed by Julia!</span></span></code></pre></div>
<p>Now, when you receive a <code>FinSet</code>, you know you have <em>something</em> which you can check for membership, get the length, and iterate over. There are no type parameters, in contrast to old Catlab:</p>
<div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb5-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">abstract type</span> FinSet{S,T} <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> SetOb{T} </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># OLD CATLAB</span></span></code></pre></div>
<p>This extra type parameter <code>S</code> was needed because we wanted different code to be executed when we were working in <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSkel(FinSet)%7D"> versus when we happened to have some other type of set with <code>Int</code> elements. This is an example of complicated type acrobatics needed to work directly with multiple dispatch, in contrast to the model-based approach taken in the refactored code.</p>
</section>
<section id="set-implementations" class="level2">
<h2 class="anchored" data-anchor-id="set-implementations">Set implementations</h2>
<p>The theories of sets and finite sets will make more sense if you see some examples of implementations of them. Some of these are shown below:</p>
<section id="product-sets" class="level3">
<h3 class="anchored" data-anchor-id="product-sets">Product sets</h3>
<p>Product sets are very common in math and programming. While they can be represented explicitly as sets of pairs (or, more generally, <img src="https://latex.codecogs.com/png.latex?n">-tuples, for the product of a vector of <img src="https://latex.codecogs.com/png.latex?n"> sets), it is more efficient to just store the vector of <code>SetOb</code> (or <code>FinSet</code>) components and lazily generate pairs at runtime as needed.</p>
<div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb6-1"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""" </span></span>
<span id="cb6-2"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Unbiased Cartesian product. `S` is either SetOb or FinSet. </span></span>
<span id="cb6-3"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`T` is the type of the tuple elements.</span></span>
<span id="cb6-4"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb6-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> ProdSet{S<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AbsSet</span>, T}</span>
<span id="cb6-6">  sets<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Vector{S}</span></span>
<span id="cb6-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ProdSet</span>(sets<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Vector{S}</span>) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> {S<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AbsSet</span>} <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> </span>
<span id="cb6-8">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">new</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{S, Tuple{eltype.(sets)...}}</span>(sets)</span>
<span id="cb6-9"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb6-10"></span>
<span id="cb6-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Common method for ThSet and ThFinSet implementations</span></span>
<span id="cb6-12"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">contains_set</span>(model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">ProdSet{&lt;:Any, T}</span>, i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">T</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> </span>
<span id="cb6-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">all</span>(<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">∈</span> s <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (s, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span>) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">zip</span>(model.sets, i))</span>
<span id="cb6-14"></span>
<span id="cb6-15"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@instance</span> ThSet{T} [model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">ProdSet{SetOb,T}</span>] <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> T begin</span>
<span id="cb6-16">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">contains</span>(i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">T</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Bool </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">contains_set</span>(model, i)</span>
<span id="cb6-17"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb6-18"></span>
<span id="cb6-19"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@instance</span> ThFinSet{T} [model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">ProdSet{FinSet,T}</span>] <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> T begin</span>
<span id="cb6-20">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">contains</span>(i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">T</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Bool </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">contains_set</span>(model, i)</span>
<span id="cb6-21">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">prod</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>.(model.sets))</span>
<span id="cb6-22">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">iterator</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Any </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Iterators</span>.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">product</span>(model.sets<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">...</span>)</span>
<span id="cb6-23"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>The implementation has type parameters, which we use to our advantage in order to have just one data structure that is parametric in the type of its elements and implements both <code>ThSet</code> and <code>ThFinSet</code>. However, these aren’t the problematic kind of type parameters we were trying to avoid: the only way a <code>ProdSet</code> gets used is after it has been wrapped by a <code>SetOb</code> or <code>FinSet</code>, which itself has no type parameters.</p>
</section>
<section id="finsetint" class="level3">
<h3 class="anchored" data-anchor-id="finsetint">FinSetInt</h3>
<p>Our favorite implementation of <code>ThFinSet</code> is <code>FinSetInt</code>, which is a set <code>{1,2,...,n}</code> represented by a single <code>Int</code>:</p>
<div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb7-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> FinSetInt</span>
<span id="cb7-2">  n<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span></span>
<span id="cb7-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span> </span>
<span id="cb7-4"></span>
<span id="cb7-5"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@instance</span> ThFinSet{<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>} [model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">FinSetInt</span>] begin</span>
<span id="cb7-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">contains</span>(i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Bool </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">≤</span> model.n</span>
<span id="cb7-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model.n</span>
<span id="cb7-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">iterator</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Any </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>model.n</span>
<span id="cb7-9"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<div class="callout callout-style-default callout-warning callout-titled" title="A `FinSetInt` is **not** a `FinSet`">
<div class="callout-header d-flex align-content-center" data-bs-toggle="collapse" data-bs-target=".callout-1-contents" aria-controls="callout-1" aria-expanded="true" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
A <code>FinSetInt</code> is <strong>not</strong> a <code>FinSet</code>
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-1" class="callout-1-contents callout-collapse collapse show">
<div class="callout-body-container callout-body">
<p>This is a subtle point that is worth stressing. We know <em>how</em> to obtain a <code>FinSet</code> by wrapping a <code>FinSetInt</code>, but a <code>FinSetInt</code> is a concrete datatype, whereas a <code>FinSet</code> is a wrapper around anything which implements the <code>ThFinSet</code> interface.</p>
<p>What is counterintuitive is that, even though <code>FinSet</code> is in some sense more general than <code>FinSetInt</code>, it is not the case that <code>FinSetInt &lt;: FinSet</code>, which <em>was</em> true in old Catlab. Because a datatype like <code>FinSetInt</code> could in principle implement any number of theories, there isn’t any theory in particular whose wrapper type could be privileged as <em>the</em> supertype of <code>FinSetInt</code>. So, a <code>FinSetInt</code> is not a <code>FinSet</code>. When it becomes time to implement the category of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSkel(FinSet)%7D">, it will make sense for the objects to be of type <code>FinSetInt</code> rather than <code>FinSet</code>. Whereas for the category <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BFinSet%7D">, we should have objects of type <code>FinSet</code>.</p>
<p>This is important because, when we come to <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-Sets, we’ll be tempted to say “Catlab should know how to take an <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-Set and get a <code>FinSet</code> for every object of its schema”. But at times we want to interpret the <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-Set as representing a diagram in <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSkel(FinSet)%7D">, and then we’d want to extract a <code>FinSetInt</code> rather than a <code>FinSet</code> from each object in the schema.</p>
</div>
</div>
</div>
<p>This addresses a common class of bugs in the old Catlab: accidentally getting overly strict element types when mapping over collections. When one has a list of <code>FinSetInt</code>, one doesn’t know how to distinguish from a list of <code>FinSet</code> where all elements happen to be <code>FinSetInt</code> and a list where it’s important that they are all <code>FinSetInt</code>.</p>
</section>
<section id="singleton-and-empty-sets" class="level3">
<h3 class="anchored" data-anchor-id="singleton-and-empty-sets">Singleton and Empty Sets</h3>
<p>The singleton set is a set with exactly one element. We make a particular choice that the <code>Nothing</code> type (with its unique value <code>nothing</code>) is the singleton set.</p>
<div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb8-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> SingletonSet <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span> </span>
<span id="cb8-2"></span>
<span id="cb8-3"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@instance</span> ThFinSet{<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Nothing</span>} [model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">SingletonSet</span>] begin</span>
<span id="cb8-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">contains</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Nothing</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Bool </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">true</span></span>
<span id="cb8-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb8-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">iterator</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Any </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">nothing</span>]</span>
<span id="cb8-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>Likewise, the best choice of a Julia type for the empty set is <code>Union{}</code>:</p>
<div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb9-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> EmptySet <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span> </span>
<span id="cb9-2"></span>
<span id="cb9-3"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@instance</span> ThFinSet{<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Union</span>{}} [model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">EmptySet</span>] begin</span>
<span id="cb9-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">contains</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Union{}</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Bool </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">false</span></span>
<span id="cb9-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb9-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">iterator</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Any </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Union</span>{}[]</span>
<span id="cb9-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>While we <em>could</em> model these sets as <code>FinSetInt(1)</code> and <code>FinSetInt(0)</code>,<sup>2</sup> respectively, there are downstream benefits of not presuming that these special sets have <code>Int</code> as the Julia type for their values.<sup>3</sup></p>
</section>
<section id="old-versus-new-implementations" class="level3">
<h3 class="anchored" data-anchor-id="old-versus-new-implementations">Old versus new implementations</h3>
<p>Implementations of <code>ThSet</code> correspond to subtypes of the <em>abstract</em> type <code>SetOb</code> in old Catlab. While old Catlab had <code>TypeSet</code> and <code>PredicatedSet</code>, the refactor extends this with a <code>UnionSet</code>, <code>ProdSet</code>, and various kinds of sum types: <code>EitherSet</code> (values wrapped in <code>Left</code> or <code>Right</code>), <code>SumSet</code> (values tagged by integers), and <code>NamedSumSet</code> (values tagged by arbitrary keys).</p>
<p>For subtypes of <code>FinSet</code>, old Catlab had <code>FinSetInt</code>, <code>FinSetCollection</code> (wrapper around a vector or Julia <code>Set</code>) and <code>TabularSet</code>. The refactor includes these in addition to <code>EmptyFinSet</code>, <code>SingletonSet</code>, <code>EnumSet</code> (an <code>@enum</code> type regarded as a <code>FinSet</code>), and the same flavors of union/product/sum types listed above, specialized to finite sets.</p>
</section>
</section>
<section id="default-implementations" class="level2">
<h2 class="anchored" data-anchor-id="default-implementations">Default implementations</h2>
<p>Suppose I want a <code>TypeSet</code>, which in the previous post we saw is a particular implementation of <code>ThSet</code> that is specified by Julia type.</p>
<div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb10-1">string_set <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SetOb</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">TypeSet</span>(<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">String</span>))</span>
<span id="cb10-2">int_set <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SetOb</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">TypeSet</span>(<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>))</span></code></pre></div>
<p>In old Catlab, one simply writes <code>TypeSet(String)</code> and gets a <code>SetOb</code>; this is because we used to have <code>TypeSet &lt;: SetOb</code>. That is no longer the case, so it seems like we’ve lost something; we have to do this tedious wrapping if we want to use <code>TypeSet(String)</code> as the codom of a function, since the function is expecting a model wrapped in a smart constructor, not a raw model (which could be any Julia type).</p>
<p>However, in all honesty, how many different implementations of <code>SetOb</code> are there? (not many) And how many of them simply take in a Julia type as their only data? (just one). Thus we should feel entitled to define the following shortcut:</p>
<div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb11-1"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""" Default model for a Set made out of a Julia `Type` """</span></span>
<span id="cb11-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SetOb</span>(T<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Type</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SetOb</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">TypeSet</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{T}</span>())</span></code></pre></div>
<p>Now it is just as easy as before (though we use <code>SetOb</code> rather than <code>TypeSet</code>):</p>
<div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb12-1">string_set <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SetOb</span>(<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">String</span>)</span>
<span id="cb12-2">int_set <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SetOb</span>(<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>)</span></code></pre></div>
<p>The general lesson is: if there is a ‘canonical’ implementation for some given data, we can define a method for the wrapper type to simply take in that data, call the canonical implementation on the data and then wrap that. This pattern for model wrapper types gets used all the time throughout the refactor. Another example would be:</p>
<div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb13-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">FinSet</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Nothing</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">FinSet</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SingletonSet</span>())</span></code></pre></div>
<p>There are times where there <em>isn’t</em> a canonical implementation. Consider:</p>
<div class="sourceCode" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb14-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">FinSet</span>(s1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">FinSet</span>, s2<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">FinSet</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">...</span></span></code></pre></div>
<p>We should <em>not</em> define a such a method. Do we want the product? The disjoint union? In those cases we really ought be explicit about which implementation we intend.</p>
</section>
<section id="function-interfaces" class="level2">
<h2 class="anchored" data-anchor-id="function-interfaces">Function interfaces</h2>
<p>Let’s look at the theory for functions in the new Catlab refactor, starting with a core theory shared by <code>SetFunction</code>, <code>FinFunction</code>, and <code>FinDomFunction</code>:</p>
<div class="sourceCode" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb15-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@theory</span> ThFunctionCore <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb15-2">  Dom<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE</span></span>
<span id="cb15-3">  Cod<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE</span></span>
<span id="cb15-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">app</span>(<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Dom</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Cod</span></span>
<span id="cb15-5"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>The <code>ThFunctionCore</code> interface states that we require function implementations to apply a function to some Julia type <code>Dom</code> to get elements of some other Julia type <code>Codom</code>.</p>
<div class="sourceCode" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb16-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">abstract type</span> SetFunction′ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># *only* subtyped by SetFunction</span></span>
<span id="cb16-2"></span>
<span id="cb16-3"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@theory</span> ThSetFunction <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> ThFunctionCore </span><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb16-4">  Fun′<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE{SetFunction′}</span></span>
<span id="cb16-5">  DomSet<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE{SetOb}</span></span>
<span id="cb16-6">  CodSet<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE{SetOb}</span></span>
<span id="cb16-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dom</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">DomSet </span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># eltype(dom()) &lt;: Dom</span></span>
<span id="cb16-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">codom</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">CodSet </span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># eltype(codom()) &lt;: Cod</span></span>
<span id="cb16-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">postcompose</span>(t<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Fun′</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Fun′</span></span>
<span id="cb16-10"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb16-11"></span>
<span id="cb16-12">ThSetFunction.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Meta</span>.<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@wrapper</span> SetFunction</span></code></pre></div>
<p>Implementations of the theory of <code>ThSetFunction</code> can be understand as morphisms in <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSet%7D">. For these we require that one must supply a (co)domain <code>SetOb</code><sup>4</sup> and be able to <em>post</em>compose another function. When we eventually <code>compose</code> these <code>SetFunctions</code> (in <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSet%7D">), the immediate result will be a sequence of functions. However, for performance considerations, we’ll want to be able to <em>evaluate</em> this sequence into a single <code>SetFunction</code> (via a <code>force</code> method which calls the underlying <code>postcompose</code> methods). Being able to repeatedly post-compose the first function in such a sequence is sufficient for this task and is often a more natural choice than precomposing.<sup>5</sup></p>
<p>We can overload the call syntax of Julia to use the <code>app</code> function.</p>
<div class="sourceCode" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb17-1">(f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">SetFunction</span>)(x) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ThSetFunction.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">app</span>(f, x)</span></code></pre></div>
<p>The theory of functions, now thought of as living in <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BFinSet%7D">, is very similar:</p>
<div class="sourceCode" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb18-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">abstract type</span> FinFunction′ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># *only* subtyped by FinFunction</span></span>
<span id="cb18-2"></span>
<span id="cb18-3"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@theory</span> ThFinFunction <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> ThFunctionCore </span><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb18-4">  Fun′<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE{FinFunction′}</span></span>
<span id="cb18-5">  DomSet<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE{FinSet}</span></span>
<span id="cb18-6">  CodSet<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE{FinSet}</span></span>
<span id="cb18-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dom</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">DomSet </span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># eltype(dom()) &lt;: Dom</span></span>
<span id="cb18-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">codom</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">CodSet </span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># eltype(codom()) &lt;: Cod</span></span>
<span id="cb18-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">postcompose</span>(t<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Fun′</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Fun′</span></span>
<span id="cb18-10"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb18-11"></span>
<span id="cb18-12">ThFinFunction.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Meta</span>.<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@wrapper</span> FinFunction <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> FinFunction′</span></span></code></pre></div>
<p>Note in both cases we did use an abstract type to avoid a chicken-egg problem: in the theory of finite functions we need to refer to the wrapper type for models of the theory of finite functions (which we can’t really define until the theory has been defined). Because <em>only</em> <code>FinFunction</code> type subtypes <code>FinFunction′</code>, we can treat the two types as equivalent.</p>
<p>The theory for a <code>FinDomFunction</code> is similar, where <code>DomSet</code> must be a <code>FinSet</code> but <code>CodSet</code> must be a <code>SetOb</code>.</p>
</section>
<section id="function-instances" class="level2">
<h2 class="anchored" data-anchor-id="function-instances">Function instances</h2>
<p>Let’s see a couple models of these theories to get a sense of them:</p>
<section id="identity-functions" class="level3">
<h3 class="anchored" data-anchor-id="identity-functions">Identity functions</h3>
<p>An identity function wraps a set, either <code>SetOb</code> or <code>FinSet</code>. Depending on which of those two options it received, it can either implement <code>ThSetFunction</code> or <code>ThFinFunction</code>.</p>
<div class="sourceCode" id="cb19" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb19-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> IdentityFunction{S<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AbsSet</span>, T}</span>
<span id="cb19-2">  set<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">S</span></span>
<span id="cb19-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">IdentityFunction</span>(d<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">S</span>) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> S<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AbsSet </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">new</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{S, eltype(d)}</span>(d)</span>
<span id="cb19-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb19-5"></span>
<span id="cb19-6"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@instance</span> ThFinFunction{T,T} [model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">IdentityFunction{FinSet, T}</span>] <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> T begin</span>
<span id="cb19-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dom</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">FinSet </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model.set</span>
<span id="cb19-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">codom</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">FinSet </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model.set</span>
<span id="cb19-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">app</span>(i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">T</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">T </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> i</span>
<span id="cb19-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">postcompose</span>(f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">FinFunction′</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">FinFunction′ </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> f</span>
<span id="cb19-11"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb19-12"></span>
<span id="cb19-13"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@instance</span> ThSetFunction{T,T} [model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">IdentityFunction{SetOb,T}</span>] <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> T begin</span>
<span id="cb19-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dom</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">SetOb </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model.set</span>
<span id="cb19-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">codom</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">SetOb </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model.set</span>
<span id="cb19-16">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">app</span>(i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">T</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">T </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> i</span>
<span id="cb19-17">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">postcompose</span>(f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">SetFunction′</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">SetFunction′ </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> f</span>
<span id="cb19-18"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
</section>
<section id="vector-based-finite-functions" class="level3">
<h3 class="anchored" data-anchor-id="vector-based-finite-functions">Vector-based finite functions</h3>
<p>A very common kind of function is a function with a <code>FinSetInt</code> domain. When we are in this fortunate situation, we can express a function out of that domain with a vector of values (where the values all live in some codomain set). This is handled by the following implementation:</p>
<div class="sourceCode" id="cb20" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb20-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> FinFunctionVector{S<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AbsSet</span>,T}</span>
<span id="cb20-2">  val<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AbstractVector</span></span>
<span id="cb20-3">  codom<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">S</span></span>
<span id="cb20-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">FinFunctionVector</span>(val<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AbstractVector</span>,codom<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">S</span>) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> {S<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AbsSet</span>} <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span></span>
<span id="cb20-5">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">new</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{S,eltype(codom)}</span>(val, codom)</span>
<span id="cb20-6"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb20-7"></span>
<span id="cb20-8"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@instance</span> ThFinFunction{<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>,T} [model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">FinFunctionVector{FinSet,T}</span>] <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> T begin</span>
<span id="cb20-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dom</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">FinSet </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">FinSet</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(model.val))</span>
<span id="cb20-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">codom</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">FinSet </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model.codom</span>
<span id="cb20-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">app</span>(i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">T </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model.val[i]</span>
<span id="cb20-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">postcompose</span>(f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">FinFunction′</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">FinFunction′ </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span></span>
<span id="cb20-13">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">FinFunction</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">FinFunctionVector</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">f</span>.(model.val), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">codom</span>(f)))</span>
<span id="cb20-14"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb20-15"></span>
<span id="cb20-16"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@instance</span> ThFinDomFunction{<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>,T} [model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">FinFunctionVector{SetOb,T}</span>] <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> T begin</span>
<span id="cb20-17">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dom</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">FinSet </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">FinSet</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(model.val))</span>
<span id="cb20-18">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">codom</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">SetOb </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model.codom</span>
<span id="cb20-19">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">app</span>(i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">T </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model.val[i]</span>
<span id="cb20-20">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">postcompose</span>(f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">SetFunction</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">FinDomFunction </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span></span>
<span id="cb20-21">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">FinDomFunction</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">FinFunctionVector</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">f</span>.(model.val), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">codom</span>(f)))</span>
<span id="cb20-22"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
</section>
<section id="old-versus-new-implementations-1" class="level3">
<h3 class="anchored" data-anchor-id="old-versus-new-implementations-1">Old versus new implementations</h3>
<p>The Catlab refactor has models for all the subtypes of <code>SetFunction</code>/<code>FinDomFunction</code>/<code>FinFunction</code> in old Catlab. These are <code>CallableFunction</code>, <code>CompositeFunction</code>, <code>ConstantFunction</code>, <code>IdentityFunction</code>, <code>PredicatedFunction</code>, <code>FinFunctionVector</code>, <code>IndexedFinFunctionVector</code> and <code>FinFunctionDict</code>.</p>
</section>
<section id="contrasting-design-of-functions-with-old-catlab" class="level3">
<h3 class="anchored" data-anchor-id="contrasting-design-of-functions-with-old-catlab">Contrasting design of functions with old Catlab</h3>
<p>There was not one <code>force</code> method for <code>SetFunction</code> but rather a variety of <code>force</code> methods for various subtypes of <code>SetFunction</code>. And those process of evaluating a sequence of functions was handled by type dispatch - any pair of implementations of functions could have its own idiosyncratic method for evaluating to a single implementation. This led to lots of complexity relative to the interface+model approach: it was harder to know which code will be actually executed given complicated types and it was harder to locate the relevant code within the codebase, as there is no obvious place for <code>do_compose(f::MyImplA, g::MyImplB)</code> to go, when <code>MyImplA</code> and <code>MyImplB</code> are defined in different places.</p>
<p>Regarding the complexity of type parameters for functions in old Catlab: the type <code>FinFunction</code> had four type parameters (<code>{S, S′, Dom &lt;: FinSet{S}, Codom &lt;: FinSet{S′}}</code>) in order to manage their dispatch. This gave us for free that every <code>FinFunction</code> was a <code>FinDomFunction</code> and every <code>FinDomFunction</code> was a <code>SetFunction</code>. This was often convenient but sometimes led to pernicious bugs where we really want to be able to make this distinction (the same reasons as above for not enforcing <code>FinSetInt &lt;: FinSet</code> or <code>FinSet &lt;: SetOb</code>).</p>
</section>
</section>
<section id="file-structure-and-future-posts" class="level2">
<h2 class="anchored" data-anchor-id="file-structure-and-future-posts">File structure and future posts</h2>
<p>The <code>v0.16</code> to <code>v0.17</code> refactor is concentrated on Catlab’s <code>CategoricalAlgebra</code> module. This was a folder with about 15 files in it, including <code>FinCats</code> (826 Lines Of Code), <code>FinSets</code> (1507 LOC), <code>CSets</code> (1418 LOC), <code>FunctorialDataMigrations</code> (456 LOC).</p>
<p>In the refactored version, these large files have been broken down into smaller ones which for the most part either declare a theory or declare a data structure and show how that data structure is a model of various theories. Another major structural change is to subdivide this into a sequence of modules:</p>
<ol type="1">
<li><code>Cats</code> (general machinery for categories, functors, limits, etc.)</li>
<li><code>SetCats</code> (specializing machinery in <code>Cats</code> to <strong>Set</strong>-like categories, including <strong>FinSet</strong>)</li>
<li><code>Pointwise</code> (specializing machinery in <code>Cats</code> to <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-Set-like categories, such as ACSets and VarACSets).</li>
</ol>
<p>We’ll cover these in a follow-up blog post!</p>


</section>


<div id="quarto-appendix" class="default"><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>

<ol>
<li id="fn1"><p>Julia iterators are duck-typed; there is no single abstract type that unifies all the sorts of things which we can call <code>iterate</code> on. For that reason, our interface cannot be more precise than to say the iterator is of type <code>Any</code>. It is up to implementers of <code>ThFinSet</code> that the value returned by <code>iterator()</code> is iterable. Furthermore, it’s up to the implementor to make sure the <code>length()</code> result is consistent with the <code>iterator()</code> result, as shown in the commented equation.↩︎</p></li>
<li id="fn2"><p>We <em>do</em> use <code>FinSetInt(1)</code> and <code>FinSetInt(0)</code> for the terminal and initial objects whenever we are working in <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSkel(FinSet)%7D"> rather than <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BFinSet%7D">.↩︎</p></li>
<li id="fn3"><p>For example, when unioning a set with the empty set, the element type will be the union of the Julia types for the respective sets. If the empty set were represented with <code>FinSet(0)</code>, then the element type of <code>UnionSet(set_containing_strings, empty_set)</code> would be <code>Union{Int,String}</code> rather than just <code>String</code> as we’d hope for.↩︎</p></li>
<li id="fn4"><p>The expressivity of GATs doesn’t let us talk about a <code>TYPE</code> whose terms are precisely the domain elements: rather we have a Julia type <code>Dom</code> for which a subset of elements (those in the set <code>dom()</code>) are defined (likewise for <code>Cod</code>). The <code>app</code> function sends every <code>Dom</code> to a <code>Cod</code>, which isn’t as constrained as sending every element of <code>dom()</code> to an element of <code>codom()</code>. It is expected, but can only be enforced at runtime, that <code>eltype(dom()) &lt;: Dom</code> (likewise for <code>Cod</code>). These things could be improved in the future by moving to a richer language than GATs, though it is fine in practice and is no worse than how things previously worked.↩︎</p></li>
<li id="fn5"><p>Often postcomposing allows one to keep the same structure but just update the values, e.g.&nbsp;a function (defined on the domain <img src="https://latex.codecogs.com/png.latex?%5C%7B1,...,n%5C%7D">) represented by a length-<img src="https://latex.codecogs.com/png.latex?n"> vector of values can be postcomposed with <img src="https://latex.codecogs.com/png.latex?f"> by just applying <img src="https://latex.codecogs.com/png.latex?f"> to each value in the vector. However, there are <em>some</em> function implementations which do fundamentally change upon postcomposition, such as postcomposing an <code>IdentityFunction</code> with some other <img src="https://latex.codecogs.com/png.latex?f"> or postcomposing some <img src="https://latex.codecogs.com/png.latex?f"> with a <code>ConstantFunction</code>.↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>code</category>
  <guid>https://blog.algebraicjulia.org/post/2025/02/refactor2/</guid>
  <pubDate>Tue, 25 Mar 2025 00:00:00 GMT</pubDate>
  <media:content url="https://blog.algebraicjulia.org/post/2025/02/refactor2/set.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>Catlab Refactor I: GATlab Preliminaries</title>
  <dc:creator>Kris Brown</dc:creator>
  <link>https://blog.algebraicjulia.org/post/2025/02/refactor1/</link>
  <description><![CDATA[ 





<div class="hidden">
<p>$$ <!-- Number systems --> </p>
<!-- Categories -->
<!-- Graphs -->
<!-- Double categories -->
<!-- Acsets -->
<!-- Wiring diagrams -->
<!-- Dynamical systems -->
<p>$$</p>
</div>
<p>This is a first blog post of a series which will guide you through the upcoming Catlab <a href="https://github.com/AlgebraicJulia/Catlab.jl/pull/949">major refactor</a>. At the core of this refactor is another AlgebraicJulia package, <a href="https://github.com/AlgebraicJulia/GATlab.jl">GATlab.jl</a>. This post explains how and why GATlab is important to Catlab.</p>
<section id="multiple-dispatch-vs-explicit-interfaces-with-gatlab" class="level2">
<h2 class="anchored" data-anchor-id="multiple-dispatch-vs-explicit-interfaces-with-gatlab">Multiple dispatch vs explicit interfaces with GATlab</h2>
<p>The key concept underlying this change is a contrast between two strategies for controlling what method gets executed when you type something like <code>compose(x,y)</code>. Julia is ultimately governed by a strategy called <strong>multiple dispatch</strong>. One is allowed to define the following:</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb1-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># objects are sets {1,2,...,n}</span></span>
<span id="cb1-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># morphisms n-&gt;m are functions, expressed as vectors of length n</span></span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">id</span>(x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Vector{Int} </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>i</span>
<span id="cb1-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compose</span>(f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Vector{Int}</span>, g<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Vector{Int}</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Vector{Int} </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> g[f]</span>
<span id="cb1-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dom</span>(f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Vector{Int}</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(f)</span>
<span id="cb1-6"></span>
<span id="cb1-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># there is one object (`nothing` of the unit type, `Nothing`)</span></span>
<span id="cb1-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># morphisms are lists of things</span></span>
<span id="cb1-9"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">id</span>(x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Nothing</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Vector </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb1-10"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compose</span>(f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Vector</span>, g<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Vector</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Vector </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">...</span>, g<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">...</span>]</span>
<span id="cb1-11"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dom</span>(f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Vector</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Nothing </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">nothing</span></span></code></pre></div>
<p>Which code gets executed when you call <code>compose(x,y)</code> depends on the type of the arguments <code>x</code> and <code>y</code>. A problem occurs when two different categories have the same objects:</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb2-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">id</span>(x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Matrix </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">I</span>(x) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># identity matrix</span></span>
<span id="cb2-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compose</span>(f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Matrix</span>,g<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Matrix</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Matrix </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>g <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># matrix multiplication</span></span>
<span id="cb2-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dom</span>(f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Matrix</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">first</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">size</span>(f)) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># number of rows</span></span></code></pre></div>
<p>However, now we’ve defined <code>id(x::Int)</code> twice, a problem which Julia will warn us about. We can circumvent this limitation in two ways. The first is to use a wrapper type:</p>
<div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb3-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Just an integer, but formally a different type </span></span>
<span id="cb3-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># so multiple dispatch can treat it differently</span></span>
<span id="cb3-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> MatrixOb</span>
<span id="cb3-4">  val<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int </span></span>
<span id="cb3-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span> </span>
<span id="cb3-6"></span>
<span id="cb3-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">id</span>(x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">MatrixOb</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">I</span>(x.val)</span>
<span id="cb3-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dom</span>(f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Matrix</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">MatrixOb</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">first</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">size</span>(f)))</span></code></pre></div>
<p>This is common design pattern in Julia, advertised in the <a href="https://doi.org/10.1109/HPEC.2013.6670347">earliest work</a> on the language, and Catlab has often taken this approach. However, it can become very inconvenient. In order to have fine-grained control over the dispatch, Catlab was forced to promote an unwieldy amount of information into the type parameters of its data structures.</p>
<p>Another strategy to address this problem is to control dispatch by using an extra argument parameter, a strategy known as “<a href="https://ucidatascienceinitiative.github.io/IntroToJulia/Html/DispatchDesigns#Traits-and-THTT">Holy traits</a>” in Julia. For technical reasons, we call such a parameter a <strong>model</strong> (of a theory). Such parameters are often singleton types, like below:</p>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb4-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> FinSetCat <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># a model</span></span>
<span id="cb4-2"></span>
<span id="cb4-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">id</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">FinSetCat</span>, x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>i</span>
<span id="cb4-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compose</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">FinSetCat</span>, f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Vector{Int}</span>, g<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Vector{Int}</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> g[f]</span>
<span id="cb4-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dom</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">FinSetCat</span>, f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Vector{Int}</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(f)</span>
<span id="cb4-6"></span>
<span id="cb4-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> MatrixCat <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># a model</span></span>
<span id="cb4-8"></span>
<span id="cb4-9"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">id</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">MatrixCat</span>, x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">I</span>(x)</span>
<span id="cb4-10"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compose</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">MatrixCat</span>, f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Matrix</span>,g<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Matrix</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>g </span>
<span id="cb4-11"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dom</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">MatrixCat</span>, f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Matrix</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">first</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">size</span>(f))</span>
<span id="cb4-12"></span>
<span id="cb4-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># model parameter used to control multiple dispatch</span></span>
<span id="cb4-14"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">id</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">FinSetCat</span>(), <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>] </span>
<span id="cb4-15"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">id</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">MatrixCat</span>(), <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>; <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span></code></pre></div>
<p>An advantage of the latter approach is that it captures the fact that the collection of methods <code>id</code>, <code>compose</code>, <code>dom</code>, etc. are <em>grouped</em> together into some cohesive unit (in other languages, this would be an <em>interface</em> or a <em>typeclass</em>). <a href="https://github.com/AlgebraicJulia/GATlab.jl">GATlab.jl</a> allows us to make these groupings of methods explicit via GATs (generalized algebraic theories), which play the role of interfaces:</p>
<div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb5-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@theory</span> ThCategory <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb5-2">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Syntactic sugar</span></span>
<span id="cb5-3">  <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@op</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb5-4">    (<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">→</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> Hom</span>
<span id="cb5-5">    (<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">⋅</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> compose</span>
<span id="cb5-6">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb5-7">  </span>
<span id="cb5-8">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Types </span></span>
<span id="cb5-9">  Ob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE</span></span>
<span id="cb5-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Hom</span>(dom<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span>, codom<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE</span></span>
<span id="cb5-11">  </span>
<span id="cb5-12">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Operations</span></span>
<span id="cb5-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">id</span>(A<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">(A </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">→</span> A)</span>
<span id="cb5-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compose</span>(f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">(A </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">→</span> B), g<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">(B </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">→</span> C))<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">(A </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">→</span> C) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">⊣</span> [A<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span>, B<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span>, C<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span>]</span>
<span id="cb5-15">  </span>
<span id="cb5-16">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Laws that the operations must satisfy</span></span>
<span id="cb5-17">  (f <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">⋅</span> g) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">⋅</span> h <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> f <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">⋅</span> (g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">⋅</span> h) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">⊣</span> [A<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span>, B<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span>, C<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span>, D<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span>,</span>
<span id="cb5-18">                                f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">(A </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">→</span> B), g<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">(B </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">→</span> C), h<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">(C </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">→</span> D)]</span>
<span id="cb5-19">  f <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">⋅</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">id</span>(B) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> f <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">⊣</span> [A<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span>, B<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span>, f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">(A </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">→</span> B)]</span>
<span id="cb5-20">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">id</span>(A) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">⋅</span> f <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> f <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">⊣</span> [A<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span>, B<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span>, f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">(A </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">→</span> B)]</span>
<span id="cb5-21"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>GATlab also provides an <code>@instance</code> macro to allow declaring a particular model for a theory:</p>
<div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb6-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@instance</span> ThCategory{Ob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>, Hom<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Vector</span>{<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>}} [model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">MatrixCat</span>] begin </span>
<span id="cb6-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">id</span>(x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">MatrixOb</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">I</span>(x.val)</span>
<span id="cb6-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compose</span>(f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Matrix</span>,g<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Matrix</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Matrix </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>g </span>
<span id="cb6-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dom</span>(f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Matrix</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">MatrixOb </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">first</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">size</span>(f))</span>
<span id="cb6-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">codom</span>(f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Matrix</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">MatrixOb </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">last</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">size</span>(f))) </span>
<span id="cb6-6"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>Here the <code>@instance</code> macro is handling lots of boilerplate; most importantly it defines the methods which have <code>MatrixCat</code> as its first parameter, throwing an error if any operations have not been provided. Additionally, a <code>getindex</code> method is generated to allow for passing in a model as the first parameter:</p>
<div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb7-1">id[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">MatrixCat</span>()](<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">id</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">WithModel</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">MatrixCat</span>()), <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>; <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span></code></pre></div>
<p>The <code>WithModel</code> wrapper is owned by GATlab and helps us distinguish when a Julia value is used as a model rather than as a piece of data.</p>
<p>In summary, the major refactor of Catlab is a major shift away from type dispatch via intricate types and towards using explicit interfaces and models. Although Julia doesn’t provide a built-in notion of interface, with the help of Julia’s macro system, we can create an ergonomic interface system via a library.</p>
</section>
<section id="wrapped-models" class="level2">
<h2 class="anchored" data-anchor-id="wrapped-models">Wrapped models</h2>
<p>GATlab allows us to declare that some Julia type <code>M</code> is a model of some theory <code>T</code>. Once we do this, we can write code that takes in both raw data and models which guide how to process that data:</p>
<div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb8-1"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""" Expects `model` to be an instance of `ThCategory` """</span></span>
<span id="cb8-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compose_three</span>(model, x, y, z)</span>
<span id="cb8-3">  compose[model](compose[model](x,y), z)</span>
<span id="cb8-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>We could make our assumptions more explicit (and get better errors than <code>MethodNotFound</code>) if we do the following:</p>
<div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb9-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compose_three</span>(model, x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">H</span>, y<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">H</span>, z<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">H</span>) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> {H}</span>
<span id="cb9-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">implements</span>(model, ThCategory, [<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Union</span>{}, H]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">||</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">error</span>(</span>
<span id="cb9-3">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Model </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>model<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;"> doesn't implement ThCategory with homs of type </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>H<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb9-4">  </span>
<span id="cb9-5">  compose[model](compose[model](x,y), z)</span>
<span id="cb9-6"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p><code>implements</code> is provided by GATlab.<sup>1</sup> However, we can do better with <strong>smart constructors</strong> - for example:</p>
<div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb10-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> Category{Ob,Hom}</span>
<span id="cb10-2">  model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Any </span></span>
<span id="cb10-3">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Category</span>(model)</span>
<span id="cb10-4">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">implements</span>(model, ThCategory) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">||</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">error</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bad model </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>model<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb10-5">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">new</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{O,H}</span>(model)</span>
<span id="cb10-6">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb10-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb10-8"></span>
<span id="cb10-9"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compose</span>(c<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Category</span>, f, g) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> compose[c.model](f, g)</span>
<span id="cb10-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># etc, for other methods</span></span></code></pre></div>
<p>Now we can write a well-typed function which will not have any runtime errors:</p>
<div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb11-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compose_three</span>(model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Category{O,H}</span>, x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">H</span>, y<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">H</span>, z<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">H</span>) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> {O,H} <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span></span>
<span id="cb11-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compose</span>(model, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compose</span>(model, x,y), z)</span></code></pre></div>
<p>Trying to use a Julia value that isn’t a model of <code>ThCategory</code> will be caught earlier, whenever we tried to wrap it in the <code>Category</code> smart constructor. GATlab can automatically generate two wrapper types for any GAT (a version which has type parameters and one which has no type parameters).</p>
<p>The Catlab refactor uses these smart constructors when possible, but there is one scenario in which the former ‘risky’ strategy is used: a Julia value can be a model of <em>multiple</em> theories. What if our function needs to take in such a model with the intent of using it for <code>T₁</code>,<code>T₂</code>, and <code>T₃</code>? Until we have a wrapper for the union of these theories it’s more convenient to just pass in the ‘raw’ model and use it as a model of various theories:</p>
<div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb12-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">example</span>(model, a, b, c)</span>
<span id="cb12-2">  T₁.op1[model](a) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> T₂.op2[model](b) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> T₃.op3[model](c)</span>
<span id="cb12-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>The best way to address this is to glue the theories together <code>T = T₁+T₂+T₃</code> (formally a pushout, which allows one to coherently do “multiple-inheritance” of interfaces) and make a wrapper type for theory <code>T</code>. As our theory morphism<sup>2</sup> infrastructure becomes more robust, we can rely less on the risky workaround and use this as the preferred solution.</p>
</section>
<section id="gats-with-fixed-julia-types" class="level2">
<h2 class="anchored" data-anchor-id="gats-with-fixed-julia-types">GATs with fixed Julia types</h2>
<p>A model of a theory assigns a Julia type for each type constructor of the theory (e.g.&nbsp;<code>{Ob = Int, Hom = Matrix}</code>). Sometimes we know at the time we’re writing our theory that we have a particular Julia type in mind for a type constructor. GATlab provides the syntax <code>MyTypeCon::TYPE{MyJuliaType}</code> within a <code>@theory</code> declaration to allow one to make explicit that <strong>all</strong> models of the theory should send the type constructor <code>MyTypeCon</code> to the julia type <code>MyJuliaType</code>.</p>
<p>For example, Catlab has a <code>DiscreteDiagram</code> type which wraps a vector of objects in some category. Any model which implements the below interface is a means of taking a discrete diagram into a <code>AbstractColimit</code> and applying the universal property of that colimit to a cocone (i.e.&nbsp;multi-cospan) to obtain a hom from the apex of the colimit into the apex of the cocone.</p>
<div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb13-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@theory</span> ThCategoryUnbiasedCoproducts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> ThCategoryColimitBase </span><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb13-2">  DiscDiag<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE{DiscreteDiagram}</span></span>
<span id="cb13-3"></span>
<span id="cb13-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">colimit</span>(d<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">DiscDiag</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Colimit</span></span>
<span id="cb13-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">universal</span>(Σ<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Colimit</span>, d<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">DiscDiag</span>, csp<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">MCospan</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">(ob</span>(Σ) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">→</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apex</span>(csp))</span>
<span id="cb13-6"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb13-7"></span>
<span id="cb13-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Note: `ThCategoryColimitBase &lt;: ThCategory` fixes </span></span>
<span id="cb13-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#       `Colimit` to the Julia type `AbstractColimit` and</span></span>
<span id="cb13-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#       `MCospan` to the Julia type `Multicospan`</span></span></code></pre></div>
<p>Without asserting various types of this theory should be sent to specific Julia types, the semantics of what <code>colimit</code> means would only be constrained by documentation (it could be some arbitrary function between arbitrary types). As GATlab develops, a more expressive language for expressing theories could eventually allow for encoding richer constraints into the GAT itself (e.g.&nbsp;support for <a href="https://www.localcharts.org/t/a-generalization-of-gat-syntax/9836">variadic arguments</a>), and then we could rely less on fixing particular Julia types.</p>
</section>
<section id="putting-it-all-together-handling-sets-in-catlab" class="level2">
<h2 class="anchored" data-anchor-id="putting-it-all-together-handling-sets-in-catlab">Putting it all together: handling sets in Catlab</h2>
<p>To help solidify the abstract topics above, let’s compare how old and new Catlab handle the concept of a <strong>set</strong>. In old Catlab, we have <code>SetOb</code> as an abstract type. Subtypes of <code>SetOb</code> are expected to have certain methods defined for them, though this isn’t made explicit anywhere!</p>
<div class="sourceCode" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb14-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">abstract type</span> SetOb{T} <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb14-2"></span>
<span id="cb14-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Base</span>.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">eltype</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Type{&lt;:SetOb{T}}</span>) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> T <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> T</span>
<span id="cb14-4"></span>
<span id="cb14-5"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""" A Julia data type regarded as a set. """</span></span>
<span id="cb14-6"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> TypeSet{T} <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> SetOb{T} </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb14-7"></span>
<span id="cb14-8"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Base</span>.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">in</span>(elem,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TypeSet{T}</span>) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> T <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isa</span>(elem,T)</span>
<span id="cb14-9"></span>
<span id="cb14-10"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""" A bool-valued function tests membership in the set """</span></span>
<span id="cb14-11"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> PredicatedSet{T} <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> SetOb{T}</span></span>
<span id="cb14-12">  predicate<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Any</span></span>
<span id="cb14-13"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb14-14"></span>
<span id="cb14-15"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Base</span>.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">in</span>(s<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">PredicatedSet{T}</span>, x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">T</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Bool </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> {T}</span>
<span id="cb14-16">  s.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">predicate</span>(x)</span>
<span id="cb14-17"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>Here the abstract type <code>SetOb</code> is the interface. Just like with <code>AbstractVector</code> and other abstract types in Julia’s standard library, one’s best hope is to delve into <a href="https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-array">documentation</a> to know which methods are mandatory, which are optional, and which are derived from other interfaces. Whether or not one has implemented the interface appropriately cannot be checked at the time of declaring that a type implements the interface.</p>
<p>From the new perspective, there was a theory (i.e.&nbsp;interface) that should have been made explicit.</p>
<div class="sourceCode" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb15-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@theory</span> ThSet <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb15-2">  Bool′<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE{Bool}</span></span>
<span id="cb15-3">  Any′<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TYPE{Any}</span></span>
<span id="cb15-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">contains</span>(<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Any′</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Bool′</span></span>
<span id="cb15-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">eltype</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Any′</span></span>
<span id="cb15-6"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb15-7"></span>
<span id="cb15-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Wrapper type</span></span>
<span id="cb15-9">ThSet.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Meta</span>.<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@wrapper</span> SetOb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> AbsSet</span></span></code></pre></div>
<p>We reproduce the old behavior by making two models for that theory.</p>
<div class="sourceCode" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb16-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> TypeSet{T} <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb16-2"></span>
<span id="cb16-3"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@instance</span> ThSet [model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">TypeSet{T}</span>] <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> T begin</span>
<span id="cb16-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">contains</span>(i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Any</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Bool </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> i isa T</span>
<span id="cb16-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">eltype</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Any </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> T</span>
<span id="cb16-6"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb16-7"></span>
<span id="cb16-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> PredicatedSet{T}</span>
<span id="cb16-9">  predicate<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Any</span></span>
<span id="cb16-10"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb16-11"></span>
<span id="cb16-12"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@instance</span> ThSet [model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">PredicatedSet{T}</span>] <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> T begin</span>
<span id="cb16-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">contains</span>(i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Any</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Bool </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> i isa T <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span> model.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">predicate</span>(i)</span>
<span id="cb16-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">eltype</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Any </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> T</span>
<span id="cb16-15"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>If our model is not a zero-field struct, it might have some actual data inside of it that is relevant. In this case, we can refer to the model (which is <em>implicitly</em> the first argument for the functions defined within an <code>@instance</code>) with the name <code>model</code>, as was done above for <code>model.predicate(i)</code>.</p>
<p>We no longer have the <code>T</code> element type parameter for <code>SetOb</code>. This was needed in old Catlab because a lot of code would dispatch on that <code>T</code> parameter (e.g.&nbsp;limits and colimits - thus implicitly presupposing a particular <code>ThCategory</code> model for objects of that type).</p>
<p>Stay tuned for future posts which will walk through key parts of the Catlab refactor!</p>


</section>


<div id="quarto-appendix" class="default"><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>

<ol>
<li id="fn1"><p><code>implements</code> takes a model <code>m::M</code>, a theory <code>T</code>, and the Julia types associated with the type constructors of <code>T</code>. It uses Julia’s <code>hasmethod</code> function to check whether appropriate methods (with <code>WithModel{M}</code> as the first argument) have been defined. If no types are provided, it will determine them via an <code>impl_type</code> method.↩︎</p></li>
<li id="fn2"><p>A key reason for why we want to think about interfaces in mathematical language of GATs is that we have a well-defined notion of <em>morphism</em> between GATs, enabling us to address problems like gluing together interfaces by using off-the-shelf mathematical tools. This is described in <a href="https://arxiv.org/abs/2404.04837">our paper</a>.↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>GATs</category>
  <category>logic</category>
  <category>code</category>
  <guid>https://blog.algebraicjulia.org/post/2025/02/refactor1/</guid>
  <pubDate>Tue, 18 Feb 2025 00:00:00 GMT</pubDate>
  <media:content url="https://blog.algebraicjulia.org/post/2025/02/refactor1/gat.jpeg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>JuMP-ing with AlgebraicJulia I: The IJKLM model</title>
  <dc:creator>Sean L. Wu</dc:creator>
  <link>https://blog.algebraicjulia.org/post/2024/09/ijklm/</link>
  <description><![CDATA[ 





<div class="hidden">
<p>$$ <!-- Number systems --> </p>
<!-- Categories -->
<!-- Graphs -->
<!-- Double categories -->
<!-- Acsets -->
<!-- Wiring diagrams -->
<!-- Dynamical systems -->
<p>$$</p>
</div>
<p>In this blog post, we will look at how AlgebraicJulia can bring new tools to mathematical programming, using <a href="https://jump.dev/">JuMP</a>.</p>
<p>Mathematical programming, and more specifically, linear (LP) and mixed-integer (MIP) programming are a staple for process optimization in dozens of industries, from electricity distribution, public transportation planning, airline scheduling, employee shift scheduling, supply chain planning, manufacturing, and more. For all but the simplest models, it is a necessity for users to be able to generate the LP/MIP problems via the use of an algebraic modeling language. These languages allow the user to write down a model close to how one might see it presented in an operations research or management science textbook. The language then applies simplifications, before passing it off to a dedicated solver program once it is in a standard form. There are a lot of modeling languages, some of the best known commercial ones being <a href="https://www.gams.com/">GAMS</a> and <a href="https://ampl.com/">AMPL</a>.</p>
<p>In all algebraic modeling languages, <em>sets</em> are a fundamental way to organize variables and constraints. For example, in the famous <a href="https://en.wikipedia.org/wiki/Stigler_diet">diet problem</a>, the set of foodstuffs may be used to index the decision variables corresponding to the amount of each food item in the diet. Both the <a href="https://www.gams.com/46/docs/UG_SetDefinition.html#UG_SetDefinition_Introduction">GAMS documentation</a> and <a href="https://ampl.com/learn/ampl-book/">AMPL documentation</a> contain significant sections related to the creation, traversal, and manipulation of sets and subsets. While the similarity of many tasks in model building to database operations has been noticed for several decades, most clearly in <span class="citation" data-cites="fourer1997database">Fourer (1997)</span>, support for more complex operations including n-ary products and relations has remained limited, and modelers often use ad hoc techniques which increase model generation times, sometimes prohibitively. In this post, we show how to use acsets, a categorical data structure described by <span class="citation" data-cites="2106.04703">Patterson, Lynch, and Fairbanks (2021)</span>, and categorical operations to formally and efficiently generate mathematical programming models.</p>
<section id="the-ijklm-model" class="level2">
<h2 class="anchored" data-anchor-id="the-ijklm-model">The IJKLM model</h2>
<p>In a <a href="https://www.gams.com/blog/2023/07/performance-in-optimization-models-a-comparative-analysis-of-gams-pyomo-gurobipy-and-jump/">blog post on the GAMS blog</a>, a comparison was made between several open source modeling languages including JuMP, and GAMS. The initial JuMP implementation saw poor performance due to inefficient Julia code. The JuMP dev team responded with their own <a href="https://jump.dev/2023/07/20/gams-blog/">blog post on the JuMP website</a>, using a fast solution based on <a href="https://dataframes.juliadata.org/stable/">DataFrames.jl</a>. In this post we will see how to use tools from AlgebraicJulia to accomplish the example modeling task. The original data and code is at <a href="https://github.com/justine18/performance_experiment">justine18/performance_experiment</a>.</p>
<p>The model is given as:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7Bmin%7D%20%5C%20z%20=%201"></p>
<p><img src="https://latex.codecogs.com/png.latex?%5Csum_%7B(j,k):(i,j,k)%20%5Cin%20%5Cmathcal%7BIJK%7D%7D%20%5C%20%5Csum_%7Bl:(j,k,l)%20%5Cin%20%5Cmathcal%7BJKL%7D%7D%20%5C%20%5Csum_%7Bm:(k,l,m)%20%5Cin%20%5Cmathcal%7BKLM%7D%7D%20x_%7Bi,j,k,l,m%7D%20%5Cge%200%20%5Chspace%7B1cm%7D%20%5Cforall%20%5C%20i%20%5Cin%20%5Cmathcal%7BI%7D"></p>
<p><img src="https://latex.codecogs.com/png.latex?x_%7Bi,j,k,l,m%7D%20%5Cge%200%20%5Chspace%7B1cm%7D%20%5Cforall%20%5C%20(i,j,k)%20%5Cin%20%5Cmathcal%7BIJK%7D,%20l:(j,k,l)%20%5Cin%20%5Cmathcal%7BJKL%7D,%20m:(k,l,m)%20%5Cin%20%5Cmathcal%7BKLM%7D%20"></p>
<p>The GAMS blog post calls subsets of Cartesian products “maps”, but we will use the standard term “relations” for subsets of n-ary products.</p>
</section>
<section id="data-generation" class="level2">
<h2 class="anchored" data-anchor-id="data-generation">Data generation</h2>
<p>First we load some packages. <code>DataFrames</code> for data frames, <code>Distributions</code> for sampling binomial random variates, <code>JuMP</code> to set up the model, and <code>HiGHS</code> for a solver. <code>Catlab</code> and <code>DataMigrations</code> are the two AlgebraicJulia packages we will use.</p>
<div id="2" class="cell" data-results="false" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">DataFrames</span></span>
<span id="cb1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Distributions</span></span>
<span id="cb1-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">JuMP</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">HiGHS</span></span>
<span id="cb1-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">DataMigrations</span></span>
<span id="cb1-5"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">BenchmarkTools</span></span></code></pre></div>
</details>
</div>
<p>The first step is to generate synthetic data according to the method from the original repo. The probability of all zeros with the given model sizes is incomprehensibly small but there is a check for it anyway. Maybe a cosmic ray will pass through your processor at a bad time.</p>
<p>Like the original code, the sets <img src="https://latex.codecogs.com/png.latex?I,J,K,L,M"> are vectors of strings. There are 3 relations which are “sparse” subsets of the corresponding products, <img src="https://latex.codecogs.com/png.latex?IJK,JKL,KLM">.</p>
<div id="4" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb2-1">SampleBinomialVec <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(A,B,C,p<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)</span>
<span id="cb2-2">    vec <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rand</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Binomial</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, p), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(A) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(B) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(C))</span>
<span id="cb2-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">while</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(vec) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb2-4">        vec <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rand</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Binomial</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, p), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(A) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(B) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(C))</span>
<span id="cb2-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb2-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> vec</span>
<span id="cb2-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb2-8"></span>
<span id="cb2-9">n<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># something large</span></span>
<span id="cb2-10">m<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 20</span></span>
<span id="cb2-11"></span>
<span id="cb2-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Sets IJKLM </span></span>
<span id="cb2-13">I <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"i</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>x<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> for x <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n]</span>
<span id="cb2-14">J <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"j</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>x<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> for x <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>m]</span>
<span id="cb2-15">K <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"k</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>x<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> for x <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>m]</span>
<span id="cb2-16">L <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"l</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>x<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> for x <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>m]</span>
<span id="cb2-17">M <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"m</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>x<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> for x <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>m]</span>
<span id="cb2-18"></span>
<span id="cb2-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># make IJK</span></span>
<span id="cb2-20">IJK <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DataFrame</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Iterators</span>.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">product</span>(I,J,K))</span>
<span id="cb2-21"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rename!</span>(IJK, [<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>i,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>j,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>k])</span>
<span id="cb2-22">IJK.value <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SampleBinomialVec</span>(I,J,K)</span>
<span id="cb2-23"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter!</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>value <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> v <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> v <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, IJK)</span>
<span id="cb2-24"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select!</span>(IJK, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Not</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>value))</span>
<span id="cb2-25"></span>
<span id="cb2-26"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># make JKL</span></span>
<span id="cb2-27">JKL <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DataFrame</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Iterators</span>.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">product</span>(J,K,L))</span>
<span id="cb2-28"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rename!</span>(JKL, [<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>j,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>k,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>l])</span>
<span id="cb2-29">JKL.value <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SampleBinomialVec</span>(J,K,L)</span>
<span id="cb2-30"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter!</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>value <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> v <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> v <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, JKL)</span>
<span id="cb2-31"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select!</span>(JKL, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Not</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>value))</span>
<span id="cb2-32"></span>
<span id="cb2-33"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># make KLM</span></span>
<span id="cb2-34">KLM <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DataFrame</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Iterators</span>.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">product</span>(K,L,M))</span>
<span id="cb2-35"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rename!</span>(KLM, [<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>k,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>l,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>m])</span>
<span id="cb2-36">KLM.value <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SampleBinomialVec</span>(K,L,M)</span>
<span id="cb2-37"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">filter!</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>value <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> v <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> v <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, KLM)</span>
<span id="cb2-38"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select!</span>(KLM, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Not</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>value))</span></code></pre></div>
</details>
</div>
</section>
<section id="the-intuitive-formulation" class="level2">
<h2 class="anchored" data-anchor-id="the-intuitive-formulation">The “intuitive” formulation</h2>
<p>As given in the original GAMS blog post, this is the naive formulation that relies on nested for loops. As remarked in the JuMP blog, this is equivalent to taking two inner joins. Another way to look at it is as finding “paths” through the relations, such that they match on common elements. Each formulation will be benchmarked.</p>
<div id="6" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb3-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@benchmark</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">let</span> </span>
<span id="cb3-2">    x_list <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb3-3">        (i, j, k, l, m)</span>
<span id="cb3-4">        for (i, j, k) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">eachrow</span>(IJK)</span>
<span id="cb3-5">        for (jj, kk, l) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">eachrow</span>(JKL) if jj <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> j <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span> kk <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> k</span>
<span id="cb3-6">        for (kkk, ll, m) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">eachrow</span>(KLM) if kkk <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> k <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span> ll <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> l</span>
<span id="cb3-7">    ]</span>
<span id="cb3-8">    model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> JuMP.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Model</span>()</span>
<span id="cb3-9">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set_silent</span>(model)</span>
<span id="cb3-10">    <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@variable</span>(model, x[x_list] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb3-11">    <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@constraint</span>(</span>
<span id="cb3-12">        model,</span>
<span id="cb3-13">        [i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> I], </span>
<span id="cb3-14">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(x[k] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> k <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> x_list <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> k[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> i) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb3-15">    )</span>
<span id="cb3-16"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre><code>BenchmarkTools.Trial: 13 samples with 1 evaluation per sample.
 Range (min … max):  400.831 ms … 415.654 ms  ┊ GC (min … max): 2.45% … 4.53%
 Time  (median):     410.973 ms               ┊ GC (median):    4.86%
 Time  (mean ± σ):   409.814 ms ±   3.953 ms  ┊ GC (mean ± σ):  4.43% ± 0.80%

  ▁         ▁                ▁     ▁      ▁█▁▁▁▁   ▁          ▁  
  █▁▁▁▁▁▁▁▁▁█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▁▁▁▁▁█▁▁▁▁▁▁██████▁▁▁█▁▁▁▁▁▁▁▁▁▁█ ▁
  401 ms           Histogram: frequency by time          416 ms &lt;

 Memory estimate: 233.84 MiB, allocs estimate: 6081245.</code></pre>
</div>
</div>
</section>
<section id="the-dataframes-version" class="level2">
<h2 class="anchored" data-anchor-id="the-dataframes-version">The DataFrames version</h2>
<p>The JuMP blog authors used a version based on two inner joins to vastly improve computation speed.</p>
<div id="8" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb5-1">ijklm_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataFrames.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">innerjoin</span>(</span>
<span id="cb5-2">    DataFrames.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">innerjoin</span>(IJK, JKL; on <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>j, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>k]),</span>
<span id="cb5-3">    KLM;</span>
<span id="cb5-4">    on <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>k, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>l],</span>
<span id="cb5-5">)</span>
<span id="cb5-6"></span>
<span id="cb5-7"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@benchmark</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">let</span></span>
<span id="cb5-8">    ijklm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataFrames.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">innerjoin</span>(</span>
<span id="cb5-9">        DataFrames.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">innerjoin</span>(IJK, JKL; on <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>j, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>k]),</span>
<span id="cb5-10">        KLM;</span>
<span id="cb5-11">        on <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>k, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>l],</span>
<span id="cb5-12">    )</span>
<span id="cb5-13">    model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> JuMP.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Model</span>()</span>
<span id="cb5-14">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set_silent</span>(model)</span>
<span id="cb5-15">    ijklm[!, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>x] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@variable</span>(model, x[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">size</span>(ijklm, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb5-16">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> df <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> DataFrames.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">groupby</span>(ijklm, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>i)</span>
<span id="cb5-17">        <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@constraint</span>(model, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(df.x) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb5-18">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb5-19"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre><code>BenchmarkTools.Trial: 6197 samples with 1 evaluation per sample.
 Range (min … max):  671.750 μs …   5.711 ms  ┊ GC (min … max):  0.00% … 85.60%
 Time  (median):     708.000 μs               ┊ GC (median):     0.00%
 Time  (mean ± σ):   805.644 μs ± 387.005 μs  ┊ GC (mean ± σ):  10.99% ± 15.37%

  █▇▆▄▃▂▁                                                       ▁
  ███████▇▆▅▅▅▁▃▁▃▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▅▆▇▇████▇▇█▇▇▇▇▇▆▇ █
  672 μs        Histogram: log(frequency) by time       2.42 ms &lt;

 Memory estimate: 1.69 MiB, allocs estimate: 17264.</code></pre>
</div>
</div>
</section>
<section id="the-acsets-version" class="level2">
<h2 class="anchored" data-anchor-id="the-acsets-version">The Acsets version</h2>
<p>Acsets (Attributed C-Sets) are a categorical data structure provided in the <a href="https://github.com/AlgebraicJulia/ACSets.jl">ACSets.jl</a> library, and imported and extended with machinery from applied category theory in <a href="https://github.com/AlgebraicJulia/Catlab.jl">Catlab.jl</a>. One of the advantages of using acsets and categorical machinery in general is that they have a natural graphical presentation, which in many cases is very readable and illuminating. If this is your first exposure to acsets, a gentle introduction can be found at <a href="../../../2020/09/cset-graphs-1/">Graphs and C-sets I: What is a graph?</a>.</p>
<p>We use <code>@present</code> to make a schema for the acset which will store the data. Note that each “set” has turned into an object in the schema, and that the relations are also objects. There are projections (homs) from the relations into the sets which are involved in each relation.</p>
<div id="10" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb7-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@present</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">IJKLMSch</span>(FreeSchema) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb7-2">    (I,J,K,L,M,IJK,JKL,KLM)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span></span>
<span id="cb7-3">    IJK_I<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(IJK,I)</span>
<span id="cb7-4">    IJK_J<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(IJK,J)</span>
<span id="cb7-5">    IJK_K<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(IJK,K)</span>
<span id="cb7-6">    JKL_J<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(JKL,J)</span>
<span id="cb7-7">    JKL_K<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(JKL,K)</span>
<span id="cb7-8">    JKL_L<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(JKL,L)</span>
<span id="cb7-9">    KLM_K<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(KLM,K)</span>
<span id="cb7-10">    KLM_L<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(KLM,L)</span>
<span id="cb7-11">    KLM_M<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(KLM,M)</span>
<span id="cb7-12"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb7-13"></span>
<span id="cb7-14">Catlab.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to_graphviz</span>(IJKLMSch, graph_attrs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Dict</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>dpi<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"72"</span>,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>ratio<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"expand"</span>,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"8"</span>))</span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2024/09/ijklm/index_files/figure-html/cell-6-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>Using <code>@acset_type</code> will programatically generate a data type and methods specific to the schema provided. We then use <code>@acset</code> to build a data instance on our schema.</p>
<div id="12" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb8-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@acset_type</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">IJKLMData</span>(IJKLMSch, index<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>IJK_I,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>IJK_J,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>IJK_K,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>JKL_J,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>JKL_K,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>JKL_L,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>KLM_K,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>KLM_L,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>KLM_M])</span>
<span id="cb8-2"></span>
<span id="cb8-3">ijklm_acs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@acset</span> IJKLMData <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb8-4">    I <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> n</span>
<span id="cb8-5">    J <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> m</span>
<span id="cb8-6">    K <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> m</span>
<span id="cb8-7">    L <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> m</span>
<span id="cb8-8">    M <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> m</span>
<span id="cb8-9"></span>
<span id="cb8-10">    IJK <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(IJK)</span>
<span id="cb8-11">    IJK_I <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parse</span>(<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>, i[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span>]) for i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> IJK.i]</span>
<span id="cb8-12">    IJK_J <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parse</span>(<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>, j[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span>]) for j <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> IJK.j]</span>
<span id="cb8-13">    IJK_K <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parse</span>(<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>, k[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span>]) for k <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> IJK.k]</span>
<span id="cb8-14"></span>
<span id="cb8-15">    JKL <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(JKL)</span>
<span id="cb8-16">    JKL_J <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parse</span>(<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>, j[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span>]) for j <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> JKL.j]</span>
<span id="cb8-17">    JKL_K <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parse</span>(<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>, k[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span>]) for k <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> JKL.k]</span>
<span id="cb8-18">    JKL_L <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parse</span>(<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>, l[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span>]) for l <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> JKL.l]</span>
<span id="cb8-19"></span>
<span id="cb8-20">    KLM <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nrow</span>(KLM)</span>
<span id="cb8-21">    KLM_K <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parse</span>(<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>, k[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span>]) for k <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> KLM.k]</span>
<span id="cb8-22">    KLM_L <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parse</span>(<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>, l[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span>]) for l <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> KLM.l]</span>
<span id="cb8-23">    KLM_M <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parse</span>(<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>, m[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span>]) for m <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> KLM.m]</span>
<span id="cb8-24"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
</details>
</div>
<section id="conjunctive-queries-on-acsets" class="level3">
<h3 class="anchored" data-anchor-id="conjunctive-queries-on-acsets">Conjunctive Queries on Acsets</h3>
<p>The critical thing that the JuMP devs did to speed thing up was to replace the for loops with 2 inner joins, to get the “paths” through the relations. How to do this with acsets? Well one thing to do is execute a conjunctive query on the acset to get the same thing. This is described in a <a href="../../../2020/12/cset-conjunctive-queries/">C-sets for data analysis: relational data and conjunctive queries</a>.</p>
<div id="14" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb9-1">connected_paths_query <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@relation</span> (i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>i,j<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>j,k<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>k,l<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>l,m<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>m) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb9-2">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">IJK</span>(IJK_I<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>i, IJK_J<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>j, IJK_K<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>k)</span>
<span id="cb9-3">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">JKL</span>(JKL_J<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>j, JKL_K<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>k, JKL_L<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>l)</span>
<span id="cb9-4">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">KLM</span>(KLM_K<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>k, KLM_L<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>l, KLM_M<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>m)</span>
<span id="cb9-5"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb9-6"></span>
<span id="cb9-7">Catlab.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to_graphviz</span>(connected_paths_query, box_labels<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=:</span>name, junction_labels<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=:</span>variable, graph_attrs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Dict</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>dpi<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"72"</span>,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"3.5"</span>,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>ratio<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"expand"</span>))</span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2024/09/ijklm/index_files/figure-html/cell-8-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>While the blog post should be consulted for a complete explanation, the conjunctive query is expressed using an undirected wiring diagram (UWD) which is visualized above. Nodes (labeled ovals) in the UWD correspond to tables (primary keys) in the acset. Junctions (labeled dots) correspond to variables. Ports, which are unlabed in this graphical depiction, are where wires connect junctions to nodes. These correspond to columns of the table they are connected to. Outer ports, which are wires that run “off the page”, are the columns of the table that will be returned as the result of the query. Conceptually, rows that are returned from the query come from filtering the Cartesian product of the tables (nodes) such that variables in columns match according to ports that share a junction.</p>
<p>The JuMP blog post notes that while the data frames version doesn’t resemble the nested summation it is arguably just as readable, especially if the columns were related to the process that was being modeled. We suggest that the acsets version is also just as readable, if not more, as the data schema and query diagram directly represent the data that parameterizes the optimization model. Furthermore because the schema of the acset is known at compile time, incorrect queries (or other operations) on acsets will be caught as compile time errors.</p>
<p>The query can then be evaluated on the specific acset instance. We can confirm that both the acsets and data frame methods return the same number of rows.</p>
<div id="16" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb10-1">ijklm_query <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">query</span>(ijklm_acs, connected_paths_query)</span>
<span id="cb10-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">size</span>(ijklm_query) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">size</span>(ijklm_df)</span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre><code>true</code></pre>
</div>
</div>
<p>Now we can go ahead and see how fast the acsets version is. The fact that the acsets based query is right on the tails of the <code>DataFrames</code> version is a performance win for the acsets library, as it is usually a generic conjunctive query engine across very general data structures (i.e., acsets are in general much more complex than a single dataframe, due to presence of multiple tables connected via foreign keys).</p>
<div id="18" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb12-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@benchmark</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">let</span></span>
<span id="cb12-2">    ijklm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">query</span>(ijklm_acs, connected_paths_query)</span>
<span id="cb12-3">    model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> JuMP.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Model</span>()</span>
<span id="cb12-4">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set_silent</span>(model)</span>
<span id="cb12-5">    ijklm[!, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>x] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@variable</span>(model, x[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">size</span>(ijklm, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb12-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> df <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> DataFrames.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">groupby</span>(ijklm, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>i)</span>
<span id="cb12-7">        <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@constraint</span>(model, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(df.x) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb12-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb12-9"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre><code>BenchmarkTools.Trial: 4282 samples with 1 evaluation per sample.
 Range (min … max):  902.250 μs …  18.836 ms  ┊ GC (min … max):  0.00% … 92.54%
 Time  (median):     971.458 μs               ┊ GC (median):     0.00%
 Time  (mean ± σ):     1.166 ms ± 797.132 μs  ┊ GC (mean ± σ):  14.59% ± 16.74%

  ██▆▄▃▃▁                                                       ▁
  ███████▇▄▁▁▃▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▃▁▆▇▆▇▇█▇██▇▇█▇▇▇▆▆ █
  902 μs        Histogram: log(frequency) by time       3.92 ms &lt;

 Memory estimate: 2.53 MiB, allocs estimate: 23908.</code></pre>
</div>
</div>
</section>
<section id="data-migrations-between-acsets" class="level3">
<h3 class="anchored" data-anchor-id="data-migrations-between-acsets">Data Migrations between Acsets</h3>
<p>While the query execution in the previous section is already quite useful for practical application, it does have one downside, and that is the type of the return object is a <code>DataFrame</code>. While this is appropriate for many cases, one of the benefits of acsets is that, from one point of view, they are in-memory relational databases, and are therefore capable of representing data more complex than can be expressed in a single table. Therefore, it would be nice if one could execute a <em>data migration</em> from one type of acset, where “type” means the schema, to another, that is able to carry along further data we need. For more details on data migration, please see Evan Patterson’s Topos Institute colloquium talk <a href="https://www.youtube.com/live/Ra-PLnog_M0?si=1_ex4wLud2hSR7be">“Categories of diagrams in data migration and computational physics”</a>.</p>
<p>In this context, if the “set” objects (<img src="https://latex.codecogs.com/png.latex?I,%20J">, etc) were further connected to other tables, maybe, say, a list of suppliers, or a list of materials, or even a process graph of downstream work, it would be inconvenient at least, if we lost that relational information during a query. In that case, we’d really want to return <em>another acset</em> on a different schema that is precisely the right shape for what we want to do.</p>
<p>In this simple case, the schema we want is shown below. We’ll think of the object <img src="https://latex.codecogs.com/png.latex?IJKLM"> as being mapped to the subset of the n-ary product that has those “paths” through the relations we are seeking.</p>
<div id="20" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb14-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@present</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">IJKLMRelSch</span>(FreeSchema) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb14-2">    (IJKLM,I,J,K,L,M)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span></span>
<span id="cb14-3">    i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(IJKLM,I)</span>
<span id="cb14-4">    j<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(IJKLM,J)</span>
<span id="cb14-5">    k<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(IJKLM,K)</span>
<span id="cb14-6">    l<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(IJKLM,L)</span>
<span id="cb14-7">    m<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(IJKLM,M)</span>
<span id="cb14-8"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb14-9"></span>
<span id="cb14-10"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@acset_type</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">IJKLMRelType</span>(IJKLMRelSch)</span>
<span id="cb14-11"></span>
<span id="cb14-12">Catlab.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to_graphviz</span>(IJKLMRelSch, graph_attrs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Dict</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>dpi<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"72"</span>,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>ratio<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"expand"</span>,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"3.5"</span>))</span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2024/09/ijklm/index_files/figure-html/cell-11-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>Now we formulate the data migration, using <a href="https://github.com/AlgebraicJulia/DataMigrations.jl">AlgebraicJulia/DataMigrations.jl</a>. While we will not be able to rigorously explain data migration here, if one has <img src="https://latex.codecogs.com/png.latex?C">-Set (instance of data on schema <img src="https://latex.codecogs.com/png.latex?C">) and wants to migrate it to a <img src="https://latex.codecogs.com/png.latex?D">-Set, a data migration functor <img src="https://latex.codecogs.com/png.latex?F"> needs to be specified.</p>
<p>Here, <img src="https://latex.codecogs.com/png.latex?C"> is our schema <code>IJKLMSch</code> and <img src="https://latex.codecogs.com/png.latex?D"> is <code>IJKLMRelSch</code>. The functor <img src="https://latex.codecogs.com/png.latex?F"> is a mapping from <img src="https://latex.codecogs.com/png.latex?D"> to the category of diagrams on <img src="https://latex.codecogs.com/png.latex?C">; formally we denote it <img src="https://latex.codecogs.com/png.latex?F:D%5Crightarrow%20%5Ctext%7BDiag%7D%5E%7B%5Ctext%7Bop%7D%7D(C)">. Each object in <img src="https://latex.codecogs.com/png.latex?D"> gets assigned a diagram into <img src="https://latex.codecogs.com/png.latex?C">, and morphisms in <img src="https://latex.codecogs.com/png.latex?D"> get assigned to contravariant morphisms of diagrams.</p>
<div id="22" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb15-1">M <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@migration</span> IJKLMRelSch IJKLMSch <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb15-2">    IJKLM <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@join</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb15-3">        ijk<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">IJK</span></span>
<span id="cb15-4">        jkl<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">JKL</span></span>
<span id="cb15-5">        klm<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">KLM</span></span>
<span id="cb15-6">        i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">I</span></span>
<span id="cb15-7">        j<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">J</span></span>
<span id="cb15-8">        k<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">K</span></span>
<span id="cb15-9">        l<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">L</span></span>
<span id="cb15-10">        m<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">M</span></span>
<span id="cb15-11">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">IJK_I</span>(ijk) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> i</span>
<span id="cb15-12">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">IJK_J</span>(ijk) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> j</span>
<span id="cb15-13">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">JKL_J</span>(jkl) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> j</span>
<span id="cb15-14">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">IJK_K</span>(ijk) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> k</span>
<span id="cb15-15">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">JKL_K</span>(jkl) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> k</span>
<span id="cb15-16">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">KLM_K</span>(klm) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> k</span>
<span id="cb15-17">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">JKL_L</span>(jkl) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> l</span>
<span id="cb15-18">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">KLM_L</span>(klm) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> l</span>
<span id="cb15-19">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">KLM_M</span>(klm) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> m</span>
<span id="cb15-20">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb15-21">    I <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> I</span>
<span id="cb15-22">    J <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> J</span>
<span id="cb15-23">    K <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> K</span>
<span id="cb15-24">    L <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> L</span>
<span id="cb15-25">    M <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> M</span>
<span id="cb15-26">    i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> i</span>
<span id="cb15-27">    j <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> j</span>
<span id="cb15-28">    k <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> k</span>
<span id="cb15-29">    l <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> l</span>
<span id="cb15-30">    m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> m</span>
<span id="cb15-31"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span>;</span></code></pre></div>
</details>
</div>
<p>A diagram is itself a functor <img src="https://latex.codecogs.com/png.latex?D:J%5Crightarrow%20C">, where <img src="https://latex.codecogs.com/png.latex?J"> is (usually) a small category, and <img src="https://latex.codecogs.com/png.latex?D"> will point at some instance of the diagram in <img src="https://latex.codecogs.com/png.latex?C">. We can plot what the largest diagram looks like, that which object <code>IJKLM</code> in <img src="https://latex.codecogs.com/png.latex?D"> is mapped to. Note the similarity to the conjunctive query visualized as a UWD previously. In particular, note that “relation” elements must agree upon the relevant “set” elements via their morphisms. The object in <img src="https://latex.codecogs.com/png.latex?C"> that each object in <img src="https://latex.codecogs.com/png.latex?J"> corresponds to is given by the text after the colon in the relevant node.</p>
<div id="24" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb16-1">F <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">functor</span>(M)</span>
<span id="cb16-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to_graphviz</span>(F.ob_map[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>IJKLM],node_labels<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">true</span>)</span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2024/09/ijklm/index_files/figure-html/cell-13-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>Because of the simplicity of the schema <code>IJKLMRelSch</code>, the contravariant morphisms of diagrams simply pick out the object in <img src="https://latex.codecogs.com/png.latex?D"> associated with the source of the morphism. Likewise, the natural transformation part of morphisms of diagrams simply selects for each object its identity morphism.</p>
<p>We run the data migration to move data from the schema <code>IJKLMSch</code> to <code>IJKLMRelSch</code> using the function <code>migrate</code>, and check that the result has the same number of records as other methods.</p>
<div id="26" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb17-1">ijklm_migrate_acset <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">migrate</span>(IJKLMRelType, ijklm_acs, M)</span>
<span id="cb17-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nparts</span>(ijklm_migrate_acset, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>IJKLM) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">size</span>(ijklm_query,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre><code>true</code></pre>
</div>
</div>
<p>Once again, let’s benchmark. The data migration is slightly slower than the conjunctive query method, but data migrations can express a much richer language of data manipulation than conjunctive queries are capable of.</p>
<div id="28" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb19" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb19-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@benchmark</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">let</span></span>
<span id="cb19-2">    ijklm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">migrate</span>(IJKLMRelType, ijklm_acs, M)</span>
<span id="cb19-3">    model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> JuMP.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Model</span>()</span>
<span id="cb19-4">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set_silent</span>(model)</span>
<span id="cb19-5">    <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@variable</span>(model, x[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parts</span>(ijklm, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>IJKLM)] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb19-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parts</span>(ijklm, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>I)</span>
<span id="cb19-7">        <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@constraint</span>(model, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(x[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">incident</span>(ijklm, i, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>i)]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb19-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb19-9"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre><code>BenchmarkTools.Trial: 1774 samples with 1 evaluation per sample.
 Range (min … max):  2.088 ms … 33.095 ms  ┊ GC (min … max):  0.00% … 91.29%
 Time  (median):     2.424 ms              ┊ GC (median):     0.00%
 Time  (mean ± σ):   2.814 ms ±  1.381 ms  ┊ GC (mean ± σ):  13.26% ± 17.61%

  ▄█▂▄▃▄▁                                                     
  ████████▆▅▄▃▃▃▂▂▂▂▂▂▂▂▂▂▂▁▂▂▂▁▂▂▁▁▂▁▁▂▁▂▂▃▃▃▃▃▃▃▃▃▃▂▃▂▂▂▂▂ ▃
  2.09 ms        Histogram: frequency by time        6.11 ms &lt;

 Memory estimate: 6.91 MiB, allocs estimate: 48899.</code></pre>
</div>
</div>
<p>To summarize, acsets and tools for working with them provided by AlgebraicJulia can greatly ease development of complex mathematical programming models. Relations, unions, and other concepts from sets are elegantly generalized by category theory, and can help develop more correct, formal, and expressive models. While the optimization “model” examined in this article is fairly abstract, we will investigate model of more practical interest in future installments on the blog.</p>
</section>
</section>
<section id="acknowledgements" class="level2">
<h2 class="anchored" data-anchor-id="acknowledgements">Acknowledgements</h2>
<p>I would like to thank <a href="https://topos.site/people/kevin-carlson/">Kevin Carlson</a> for his assistance regarding <a href="https://github.com/AlgebraicJulia/DataMigrations.jl">DataMigrations.jl</a>.</p>



</section>

<div id="quarto-appendix" class="default"><section class="quarto-appendix-contents" id="quarto-bibliography"><h2 class="anchored quarto-appendix-heading">References</h2><div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="0">
<div id="ref-fourer1997database" class="csl-entry">
Fourer, Robert. 1997. <span>“Database Structures for Mathematical Programming Models.”</span> <em>Decision Support Systems</em> 20 (4): 317–44.
</div>
<div id="ref-2106.04703" class="csl-entry">
Patterson, Evan, Owen Lynch, and James Fairbanks. 2021. <span>“Categorical Data Structures for Technical Computing.”</span> <a href="https://doi.org/10.32408/compositionality-4-5">https://doi.org/10.32408/compositionality-4-5</a>.
</div>
</div></section></div> ]]></description>
  <category>algebra</category>
  <category>logic</category>
  <category>optimization</category>
  <guid>https://blog.algebraicjulia.org/post/2024/09/ijklm/</guid>
  <pubDate>Fri, 06 Sep 2024 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Introducing InterTypes</title>
  <dc:creator>Owen Lynch</dc:creator>
  <link>https://blog.algebraicjulia.org/post/2023/11/intertypes/</link>
  <description><![CDATA[ 





<section id="motivation" class="level1">
<h1>Motivation</h1>
<p>Part of the AlgebraicJulia vision for scientific computing is that a scientific model should be piece of data that can be inspected, analyzed, passed between programming languages, and saved in a database.</p>
<p>In order to do this, we need to make sure that different languages can load and save the models.</p>
<p>One way to do this would be to define a data type for “all scientific models”, and then implement that data type in each programming language we care about. But this is clearly ridiculous; there is no one data type that can encompass every single scientific model. Moreover, often we want to specify that we only want a certain type of scientific model.</p>
<p>Another approach would be to manually implement, for each type of scientific model, types in every language we care about. However, this is an <img src="https://latex.codecogs.com/png.latex?m%20%5Ctimes%20n"> problem, where <img src="https://latex.codecogs.com/png.latex?m"> is the number of languages and <img src="https://latex.codecogs.com/png.latex?n"> is the number of types of scientific models. Moreover, it is error-prone (because there are subtle differences between the type systems of different languages), and would be a massive drag on rapid iteration; any new type of model or change to a modeling framework needs to be implemented across many different languages.</p>
<p>The better way to do it would be to define your types <em>once</em>, in a language-agnostic way, and then generate the types in each language automatically along with serialization/deserialization code. This sort of system has been done before: see</p>
<ul>
<li><a href="https://developers.google.com/protocol-buffers/">protobuf</a></li>
<li><a href="https://thrift.apache.org/">thrift</a></li>
<li><a href="https://typedefs.com/">typedefs</a></li>
<li><a href="https://capnproto.org/">capnproto</a></li>
</ul>
<p>The relevant XKCD is, of course,</p>
<p><img src="https://imgs.xkcd.com/comics/standards_2x.png" class="img-fluid"></p>
<p>So why make a new one? Well, I want to support <a href="https://github.com/AlgebraicJulia/ACSets.jl">ACSets</a> natively, as many of our scientific models are built on top of them <span class="citation" data-cites="2106.04703">(Patterson, Lynch, and Fairbanks 2021)</span>. And it seemed that modifying an existing system would be more work than building a new one from scratch. But more importantly, I find that building this kind of thing from scratch gives you a much better picture of the kind of design decisions that go into this, and thus if I end up trying to modify a pre-existing one later down the line I’ll have a better idea of how to go about it.</p>
<p>One difference between InterTypes and these other formats is that I don’t intend (at least at first) to have a custom serialization format that goes along with it. The main feature of InterType is to generate the data structures in each programming language. Currently we have serialization/deserialization to JSON (including 64-bit integer support!), but we could also support other serialization formats. The whole point of InterTypes is that you shouldn’t have to think about the underlying serialization details. Along with this, from an intertype specification one can generate a JSONSchema file that describes the JSON produced by the automatically generated serialization.</p>
</section>
<section id="use" class="level1">
<h1>Use</h1>
<p>WARNING: InterTypes is <em>alpha-quality</em> software, and not only are there certainly bugs but also the interface to it may change radically.</p>
<p>The core of InterTypes is the intertype schema, which declares a collection of types that can refer to one another. An intertype schema is a file ending in <code>.it</code>. Currently, we use the Julia parser to parse the <code>.it</code> file, and we use Julia to generate code for all languages. However, we hope to in the future to produce a standalone binary that will parse the <code>.it</code> file and generate the code in other languages. So although <code>.it</code> files look like Julia, most features of Julia will not work with in an intertype schema; for instance, you cannot define functions in an intertype schema, or refer to types that are defined outside of an intertype schema.</p>
<p>There are 4 fundamental building blocks of InterTypes.</p>
<ol type="1">
<li>Primitive types.</li>
</ol>
<ul>
<li><code>Int32</code>/<code>Int64</code>/<code>UInt32</code>/<code>UInt64</code> for integer numbers. We have 32 bit and 64 bit integers, because only 32 bit integers are safe to put in JSON numbers and 64 bit integers must be put in JSON strings.</li>
<li><code>Bool</code> for booleans.</li>
<li><code>Float64</code> for floating point numbers.</li>
<li><code>String</code> for strings.</li>
<li><code>Symbol</code> for symbols. In languages that don’t have symbols, this is the same as <code>String</code>.</li>
<li><code>Vector{T}</code> for representing sequences (arrays and lists) of type <code>T</code></li>
<li><code>Binary</code> for sequences of raw bytes without a numeric interpretation. In Julia, this maps to <code>Vector{UInt8}</code>, but we think of it as a binary blob rather than a sequence of values.</li>
<li><code>Dict{K,V}</code> for representing dictionaries with key type <code>K</code> and value type <code>V</code>.</li>
</ul>
<ol start="2" type="1">
<li>Structs. A struct has a list of fields and each field has a name and a type. This looks like:</li>
</ol>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb1-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> Point2D</span>
<span id="cb1-2">  x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Float64</span></span>
<span id="cb1-3">  y<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Float64</span></span>
<span id="cb1-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<ol start="3" type="1">
<li>Sum types, also known as “tagged unions”. A sum type has a list of variants, and each variant is a record containing fields. This looks like</li>
</ol>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb2-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@sum</span> Op <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb2-2">  Plus</span>
<span id="cb2-3">  Mul</span>
<span id="cb2-4"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb2-5"></span>
<span id="cb2-6"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@sum</span> Term <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb2-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Constant</span>(val<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Float64</span>)</span>
<span id="cb2-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">App</span>(op<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Op</span>, arg1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Term</span>, arg2<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Term</span>)</span>
<span id="cb2-9"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<ol start="4" type="1">
<li>ACSets. ACSets are handled a little differently than they work in Julia, in order to paper over the fact that I have yet to fully figure out Python’s (and pydantic’s, which is the validation/serialization framework) support for generic types. When you declare the schema, you have to specify a concrete type for every AttrType. Then, when you declare an instance of the schema, you do not get a generic instance like you do in Julia; you get an instance with attribute types fixed to the supplied types. This looks like:</li>
</ol>
<div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb3-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> EdgeData</span>
<span id="cb3-2">  name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Symbol</span></span>
<span id="cb3-3">  length<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">UInt64</span></span>
<span id="cb3-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb3-5"></span>
<span id="cb3-6"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@schema</span> SchGraph <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb3-7">  (E,V)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span></span>
<span id="cb3-8">  (src, tgt)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(E, V)</span>
<span id="cb3-9"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb3-10"></span>
<span id="cb3-11"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@schema</span> SchWeightedGraph <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> SchGraph </span><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb3-12">  Weight<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AttrType</span>(EdgeData) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># note that we provide a type here</span></span>
<span id="cb3-13">  weight<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Attr</span>(E, Weight)</span>
<span id="cb3-14"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb3-15"></span>
<span id="cb3-16"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@abstract_acset_type</span> AbstractGraph</span>
<span id="cb3-17"></span>
<span id="cb3-18"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@acset_type</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">EDWeightedGraph</span>(SchWeightedGraph,</span>
<span id="cb3-19">                            generic<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>WeightedGraph, index<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>src, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>tgt]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> AbstractGraph</span></span></code></pre></div>
<p>This is equivalent to the Julia code</p>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb4-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> EdgeData</span>
<span id="cb4-2">  name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Symbol</span></span>
<span id="cb4-3">  length<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">UInt64</span></span>
<span id="cb4-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb4-5"></span>
<span id="cb4-6"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@schema</span> SchGraph <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb4-7">  (E,V)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span></span>
<span id="cb4-8">  (src, tgt)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(E, V)</span>
<span id="cb4-9"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb4-10"></span>
<span id="cb4-11"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@schema</span> SchWeightedGraph <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> SchGraph </span><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb4-12">  Weight<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AttrType </span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># note that there is no type here</span></span>
<span id="cb4-13">  weight<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Attr</span>(E, Weight)</span>
<span id="cb4-14"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb4-15"></span>
<span id="cb4-16"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@abstract_acset_type</span> AbstractGraph</span>
<span id="cb4-17"></span>
<span id="cb4-18"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@acset_type</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">WeightedGraph</span>(SchWeightedGraph, index<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>src, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>tgt]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> AbstractGraph</span></span>
<span id="cb4-19"></span>
<span id="cb4-20"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">const</span> EDWeightedGraph <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> WeightedGraph{EdgeData}</span></code></pre></div>
<p>However in the Python code, no data structure with the name <code>WeightedGraph</code> is produced; only <code>EDWeightedGraph</code>. This is because the Python and Julia ACSets code were written pre-intertype, so their handling of attrtypes weren’t fully compatible, and we had to get something working; hopefully in the future Python and Julia will be more congruous. This is a good first issue for someone familiar with types in Python/pydantic!</p>
<p>To use an intertype schema, one “declares an intertype module” like so:</p>
<div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb5-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@intertypes</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"weightedgraph.it"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">module</span> weightedgraph <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>Then <code>weightedgraph</code> is a module that contains an export for each type defined in <code>weightedgraph.it</code>. It also contains a <code>Meta</code> variable, which stores the parsed intertype definition. This can then be used to write out generated python code, via</p>
<div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb6-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">generate_python_module</span>(weightedgraph, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"."</span>)</span></code></pre></div>
<p>which writes a python file called <code>weightedgraph.py</code> in the current directory. This python file imports both <code>acsets</code> and <code>intertypes</code>, so in order to use it one must have the <a href="https://github.com/AlgebraicJulia/py-acsets">py-acsets</a> library installed, and also a copy of <code>intertypes.py</code>, which can be produced with</p>
<div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb7-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">write</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"intertypes.py"</span>, InterTypes.INTERTYPE_PYTHON_MODULE)</span></code></pre></div>
<p>In a similar manner, a JSONSchema definition for the json produced by intertypes can be produced with</p>
<div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb8-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">generate_jsonschema_module</span>(weightedgraph, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"."</span>)</span></code></pre></div>
<p>which writes a JSONSchema file called <code>weightedgraph_schema.json</code> in the current directory. This is a file which has a JSONSchema <code>def</code> for each type in the intertype definition file.</p>
<p>Intertype modules can refer to one another. For instance, we could write another file called <code>twoweightedgraphs.it</code> with contents of:</p>
<div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb9-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> TwoWeightedGraphs</span>
<span id="cb9-2">  g1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">weightedgraph.EDWeightedGraph</span></span>
<span id="cb9-3">  g2<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">weightedgraph.EDWeightedGraph</span></span>
<span id="cb9-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>and then import it like:</p>
<div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb10-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@intertypes</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"twoweightedgraphs.it"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">module</span> twoweightedgraphs</span>
<span id="cb10-2">  <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">..weightedgraph</span></span>
<span id="cb10-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>In fact, <code>weightedgraph.it</code> and <code>twoweightedgraphs.it</code> could be in completely different packages; as long as the first package exports the <code>weightedgraph</code> Julia module this will work fine.</p>
<p>For more examples of how to use intertypes, it would probably be best to refer to the <a href="https://github.com/AlgebraicJulia/ACSets.jl/blob/main/test/intertypes/InterTypes.jl">test file</a>.</p>
</section>
<section id="future-work" class="level1">
<h1>Future Work</h1>
<p>There are a lot of directions I’m excited to take intertypes in.</p>
<p>First of all, I need to write more documentation beyond this blog post.</p>
<p>After that, I plan to add support for Scala, TypeScript, and Rust. Scala in particular would solve a lot of problems between AlgebraicJulia and Semagrams, so I’m going to tackle that next.</p>
<p>Thirdly, I’d like to think about integrating GATlab with InterType, so that scientific models with algebraic expressions in them can be first-class.</p>
<p>Longer down the road, I want to investigate combinatorial data structures beyond acsets, as laid out in <a href="https://www.localcharts.org/t/array-systems/9927">array systems</a> and <a href="https://www.localcharts.org/t/combinatorial-data-structures-via-finite-existential-types/10724/5">combinatorial data structures via finite existential types</a>, and also think about <em>structured version control</em> for intertypes in line with <a href="https://github.com/davidad/chit">chit</a>.</p>
<p>But finally, I want to use intertypes to make the vision at the beginning a reality, a vision where scientific models can be passed around between programming languages and stored in databases. This is beyond a technical vision; this is a <em>social</em> vision; I hope to reshape how people think about scientific models. If you are interested in this, please reach out on the <a href="https://categorytheory.zulipchat.com/">category theory zulip</a>, <a href="https://julialang.zulipchat.com/">julia zulip</a>, <a href="https://www.localcharts.org/">localcharts</a>, or <a href="https://github.com/AlgebraicJulia/ACSets.jl/issues">github issues</a>.</p>



</section>

<div id="quarto-appendix" class="default"><section class="quarto-appendix-contents" id="quarto-bibliography"><h2 class="anchored quarto-appendix-heading">References</h2><div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="0">
<div id="ref-2106.04703" class="csl-entry">
Patterson, Evan, Owen Lynch, and James Fairbanks. 2021. <span>“Categorical Data Structures for Technical Computing.”</span> <a href="https://doi.org/10.32408/compositionality-4-5">https://doi.org/10.32408/compositionality-4-5</a>.
</div>
</div></section></div> ]]></description>
  <category>attributed-c-sets</category>
  <category>integration</category>
  <guid>https://blog.algebraicjulia.org/post/2023/11/intertypes/</guid>
  <pubDate>Tue, 14 Nov 2023 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Agent-based modeling via graph rewriting</title>
  <dc:creator>Kris Brown</dc:creator>
  <link>https://blog.algebraicjulia.org/post/2023/07/graphical-schedule/</link>
  <description><![CDATA[ 





<div class="hidden">
<p>$$ <!-- Number systems --> </p>
<!-- Categories -->
<!-- Graphs -->
<!-- Double categories -->
<!-- Acsets -->
<!-- Wiring diagrams -->
<!-- Dynamical systems -->
<p>$$</p>
</div>
<p><em>Note: the code in this post is not kept in sync with the latest developments of AlgebraicRewriting.jl. Please see the <a href="https://algebraicjulia.github.io/AlgebraicRewriting.jl/dev/generated/lotka_volterra/">official documentation</a> for examples of code that runs with the latest versions of AlgebraicJulia libraries.</em></p>
<section id="background" class="level1">
<h1>Background</h1>
<p>Scientists and engineers are often interested in representing the state of the world, <img src="https://latex.codecogs.com/png.latex?S">. We might decide to encode this as the set of possible instances of a class,<sup>1</sup> or as the set of terms of an algebraic data type,<sup>2</sup> or as possible databases on a schema (i.e.&nbsp; <a href="https://blog.algebraicjulia.org/post/2020/09/cset-graphs-1/"><img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets</a>). We are also often interested in encoding the transition <img src="https://latex.codecogs.com/png.latex?%7BS%20%5Crightarrow%20S%7D">, a relationship between one state of the world and the <em>next</em> one. If we can communicate this relationship to a computer, then we can execute simulations to see how hypothetical states of the world evolve over time. The question we explore in this post is: <strong>what is a good syntax for representing these kinds of functions?</strong> Some virtues that we will care about:</p>
<ul>
<li>It should be easy for an engineer to <em>construct</em> such functions from simpler ones.</li>
<li>It should be easy to implement the simulator in a clean, elegant way that does not have complicated edge cases to handle.</li>
<li>The syntax should be <em>general</em>, such that we can use the same code to perform, e.g., chemistry, robotics, or epidemiology simulations.<br>
</li>
<li>It should be natural to generalize the output of the simulation (e.g.&nbsp;many possible outcomes, <img src="https://latex.codecogs.com/png.latex?S%20%5Crightarrow%20%7B%5Crm%20List%7D(S)">, or a probability distribution of outcomes, <img src="https://latex.codecogs.com/png.latex?S%20%5Crightarrow%20%7B%5Crm%20Dist%7D(S)">) without changing much code.</li>
<li>The structure of the representation should be transparent and introspectable:
<ul>
<li>We can write programs to check whether properties of interest hold (e.g.&nbsp; will the program terminate on all inputs?).</li>
<li>Most importantly, if our representation of the world is fundamentally changed (suppose the world is better modeled by <img src="https://latex.codecogs.com/png.latex?T">, rather than <img src="https://latex.codecogs.com/png.latex?S">), we can <em>automatically</em> convert our <img src="https://latex.codecogs.com/png.latex?S">-simulator to a <img src="https://latex.codecogs.com/png.latex?T">-simulator, given some high-level description of the relationship between <img src="https://latex.codecogs.com/png.latex?S"> and <img src="https://latex.codecogs.com/png.latex?T">.</li>
</ul></li>
</ul>
<p>It is difficult to obtain many of these properties when one’s syntax for <img src="https://latex.codecogs.com/png.latex?S"> is an arbitrary datatype and one’s syntax for the <img src="https://latex.codecogs.com/png.latex?%7BS%20%5Crightarrow%20S%7D"> relationship is just an arbitrary function in your programming language. However, we propose that the syntax of <strong>directed wiring diagrams</strong> organizing <strong>rewrite rules</strong> makes these properties more tractable. Although this post will focus on engineering, we can use category theory to describe in more detail what it really <em>means</em> to be a good syntax and show how we can interpret our directed wiring diagrams as agent-based models.</p>
</section>
<section id="a-language-for-graphical-rewriting-programs" class="level1 page-columns page-full">
<h1>A language for graphical rewriting programs</h1>
<section id="example-schema" class="level2">
<h2 class="anchored" data-anchor-id="example-schema">Example schema</h2>
<p><img src="https://blog.algebraicjulia.org/post/2023/07/graphical-schedule/schema.png" class="img-fluid quarto-figure quarto-figure-center" style="width:40.0%" alt="schema"> <img src="https://blog.algebraicjulia.org/post/2023/07/graphical-schedule/legend.png" class="img-fluid quarto-figure quarto-figure-center" style="width:55.0%" alt="schema"></p>
<p>This schema (with objects: Wolf, Sheep, Edge, Vertex, and attribute types: Dir and <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BN%7D">) characterizes states of the world where there are wolves and sheep moving around a directed graph.<sup>3</sup> These animals have a position, direction, as well as an energy level. Furthermore, the vertices have grass growing which is also represented by an energy level (let <code>grass=0</code> mean the grass is ready to eat, while <code>grass=n</code> means there are <img src="https://latex.codecogs.com/png.latex?n"> days left for the grass to grow). The legend on the right shows how we informally represent instances of this schema, although for simplicity we neglect to visually depict the direction of edges or animals. Using Catlab.jl, we can define this schema:</p>
<div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb3-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">AlgebraicRewriting</span></span>
<span id="cb3-2"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@present</span> SchLV <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> SchGraph </span><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb3-3">  (Sheep,Wolf)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span></span>
<span id="cb3-4">  spos<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(Sheep, V); wpos<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(Wolf, V)</span>
<span id="cb3-5"></span>
<span id="cb3-6">  (Dir,Eng)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AttrType</span></span>
<span id="cb3-7">  grass<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Attr</span>(V, Eng)</span>
<span id="cb3-8">  seng<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Attr</span>(Sheep, Eng); weng<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Attr</span>(Wolf, Eng)</span>
<span id="cb3-9">  dir<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Attr</span>(E, Dir)</span>
<span id="cb3-10">  sdir<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Attr</span>(Sheep, Dir); wdir<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Attr</span>(Wolf, Dir)</span>
<span id="cb3-11"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span>;</span>
<span id="cb3-12"></span>
<span id="cb3-13"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@acset_type</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">LV_Generic</span>(SchLV) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Dir and Eng are abstract</span></span>
<span id="cb3-14"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">const</span> LV <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> LV_Generic{<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Symbol</span>, <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>} <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Dir is a Symbol, Eng is an Int</span></span>
<span id="cb3-15"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">const</span> yLV <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">yoneda_cache</span>(LV) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># precompute the 'generic' sheep/wolf/grass etc.</span></span></code></pre></div>
</section>
<section id="rewrite-rules-primitives-for-data-manipulation" class="level2">
<h2 class="anchored" data-anchor-id="rewrite-rules-primitives-for-data-manipulation">Rewrite rules: primitives for data manipulation</h2>
<p>Rewrite rules are good candidates for simple <img src="https://latex.codecogs.com/png.latex?S%20%5Crightarrow%20S"> building blocks, as they can express interesting dynamics while nevertheless being easier objects to work with than general purpose code.<sup>4</sup> This has the data a partial map <img src="https://latex.codecogs.com/png.latex?L%5Cnrightarrow%20R"> which says, for any pattern match of <img src="https://latex.codecogs.com/png.latex?L"> into one’s world of interest, a possible way for the world to update is to replace <img src="https://latex.codecogs.com/png.latex?L"> with <img src="https://latex.codecogs.com/png.latex?R">. For example, the below rule says that, if a wolf and sheep are in the same location, the wolf can eat the sheep and gain its energy units.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2023/07/graphical-schedule/wolfeat.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:40.0%" alt="schema"></p>
</figure>
</div>
<p>Or, in code:</p>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb4-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># pattern we're looking for: wolf + sheep on the same V</span></span>
<span id="cb4-2">L <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@acset_colim</span> yLV <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span>  s<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Sheep</span>; w<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Wolf</span>; <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">spos</span>(s)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">wpos</span>(w) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb4-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># what we're replacing with: just a wolf</span></span>
<span id="cb4-4">R <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@acset_colim</span> yLV <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span> w<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Wolf </span><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb4-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Get the ID's of the relevant energy variables</span></span>
<span id="cb4-6">L_wolf, L_sheep, R_wolf <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">only</span>(x).val for x <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> [L[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>weng], L[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>seng], R[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>weng]]]</span>
<span id="cb4-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Combine into a rule: L &lt;- R -&gt; R</span></span>
<span id="cb4-8">wolf_eat <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Rule</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">homomorphism</span>(R,L), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">id</span>(R); </span>
<span id="cb4-9">                expr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(Eng<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Dict</span>(R_wolf <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> engs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> engs[L_wolf]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>engs[L_sheep]),))</span></code></pre></div>
<p>As another rule, consider two sheep which reproduce if the vertex they share is grassy, <em>unless</em> there is a wolf within striking distance. We can add to the data of a rewrite rule a Negative Application Condition (NAC) which embeds the matched pattern <img src="https://latex.codecogs.com/png.latex?L"> into a forbidden pattern <img src="https://latex.codecogs.com/png.latex?N"> with the implied semantics of: the rule cannot be applied to a given pattern <img src="https://latex.codecogs.com/png.latex?L"> if <img src="https://latex.codecogs.com/png.latex?N"> also matches.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2023/07/graphical-schedule/sheep_reprod.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:60.0%" alt="schema"></p>
</figure>
</div>
<p>Or, in code:</p>
<div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb5-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Pattern we're looking for: sheep + sheep on green grass (i.e. grass = 0)</span></span>
<span id="cb5-2">L <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@acset_colim</span> yLV <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span> </span>
<span id="cb5-3">  (s1,s2)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Sheep</span>; </span>
<span id="cb5-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">spos</span>(s1) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">spos</span>(s2); <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">grass</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">spos</span>(s1)) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> </span>
<span id="cb5-5"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span> </span>
<span id="cb5-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Replacing with: new sheep facing North @ 5 eng</span></span>
<span id="cb5-7">R <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@acset_colim</span> yLV <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span> </span>
<span id="cb5-8">  (s1,s2,s3)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Sheep</span>; </span>
<span id="cb5-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">spos</span>(s1) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">spos</span>(s2); <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">grass</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">spos</span>(s1)) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> </span>
<span id="cb5-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">spos</span>(s2) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">spos</span>(s3); <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seng</span>(s3) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>; <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sdir</span>(s3) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>N</span>
<span id="cb5-11"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span> </span>
<span id="cb5-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Negative application condition</span></span>
<span id="cb5-13">N <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@acset_colim</span> yLV <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span> </span>
<span id="cb5-14">  (s1,s2)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Sheep</span>; w<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Wolf</span>; <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">E</span></span>
<span id="cb5-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">spos</span>(s1) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">spos</span>(s2); <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">grass</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">spos</span>(s1)) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> </span>
<span id="cb5-16">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">src</span>(<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">wpos</span>(w); <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tgt</span>(<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">spos</span>(s1)</span>
<span id="cb5-17"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span> </span>
<span id="cb5-18">NAC <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">AppCond</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">homomorphism</span>(L, N; monic<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">true</span>), <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">false</span>)</span>
<span id="cb5-19"></span>
<span id="cb5-20"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Overall rule</span></span>
<span id="cb5-21">sheep_reprod <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Rule</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">id</span>(L), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">homomorphism</span>(L,R; monic<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">true</span>), ac<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[NAC])</span></code></pre></div>
<p>Rewrite rules are nifty ways of expressing some basic data operations (merging, copying, deleting, adding) and basic logic in a graphical / combinatorial way, i.e.&nbsp;requiring only <em>data</em> rather than general purpose <em>code</em>. But one quickly hits limits in expressivity for what can be accomplished by a single rewrite rule, and there remains the problem of how one structures the execution of many rewrite rules in an organized fashion.</p>
</section>
<section id="wiring-diagram-syntax-and-control-flow-boxes" class="level2">
<h2 class="anchored" data-anchor-id="wiring-diagram-syntax-and-control-flow-boxes">Wiring diagram syntax and control flow boxes</h2>
<p>If we view the rewrite rule as system that can be entered and exited in various ways, we might draw it like this:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2023/07/graphical-schedule/reprod.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:40.0%" alt="schema"></p>
</figure>
</div>
<p>During a simulation, we imagine that the ‘world state’ moves along wires in a diagram like above and is possibly altered by the boxes it passes through. For a deterministic simulation, after entering a box, we will then exit exactly one of the box’s outwires. Although the above box is an example of something that can alter the world state living on the wire, it has no <em>internal</em> state itself. In contrast, we can consider control flow boxes which cannot affect the state of the world yet can have their own state and choose which outwire to exit through as a function of their internal state and the world state.</p>
<p>For example, we can make a <code>repeat3</code> box which sends the world out the first wire the first three times it run, and subsequently outputs on its second wire. Another box, <code>coin</code>, flips a pseudorandom coin to decide where its output goes. The following diagram communicates a program which first flips a coin, and (if heads) it attempts three times to apply the Reprod rule, ending immediately if at any point it is successfully applied.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2023/07/graphical-schedule/coin.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:40.0%" alt="schema"></p>
</figure>
</div>
<p>There are many tools at our disposal to construct wiring diagrams like these using Catlab and AlgebraicRewriting. These include calling <code>A⋅B</code> to compose diagrams (which match head-to-tail) in sequence, and calling <code>A⊗B</code> to compose diagrams in parallel. Another powerful tool, which constructs the above diagram in one step, uses the fact that <em>acyclic</em> wiring diagrams can be expressed very naturally using a simple programming-like syntax, where variables correspond to wires, ‘calling a function’ corresponds to feeding wires into a box, and the special syntax <code>[x₁,...,xₙ]</code> corresponds to merging wires together:</p>
<div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb6-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mk_sched</span>(</span>
<span id="cb6-2">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1 *looped* argument </span></span>
<span id="cb6-3">  (r3_loop,),  </span>
<span id="cb6-4">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1 normal argument</span></span>
<span id="cb6-5">  (coin_in,), </span>
<span id="cb6-6">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Bind these names to boxes / wiring diagrams defined elsewhere</span></span>
<span id="cb6-7">  (C <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> coin, R3 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> repeat3, R <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sheep_reprod), </span>
<span id="cb6-8">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Construct an acyclic wiring diagram</span></span>
<span id="cb6-9">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">quote</span> </span>
<span id="cb6-10">    coin_yes, coin_no <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">C</span>(coin_in)</span>
<span id="cb6-11">    R3_input <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [r3_loop, coin_yes]</span>
<span id="cb6-12">    repeat3_looping, repeat3_finished <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">R3</span>(R3_input)</span>
<span id="cb6-13">    reprod_suc, reprod_fail <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">R</span>(repeat3_looping)</span>
<span id="cb6-14">    output <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [reprod_suc, repeat3_finished, coin_no]</span>
<span id="cb6-15">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># The 1st argument is fed back into `r3_loop`.</span></span>
<span id="cb6-16">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> (reprod_fail,  output)        </span>
<span id="cb6-17"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span>)</span></code></pre></div>
<p>Our desired program was not, in fact, acyclic, but by asking for the first <img src="https://latex.codecogs.com/png.latex?n"> outputs to be looped back into the first <img src="https://latex.codecogs.com/png.latex?n"> inputs (where <img src="https://latex.codecogs.com/png.latex?n"> is the length of the first argument to <code>mk_sched</code>), we have a general strategy for making diagrams with loops.</p>
</section>
<section id="agent-based-modeling" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="agent-based-modeling">Agent-based modeling</h2>
<p>Simulations are often <strong>agent-based</strong>: instead of thinking of the world state as a monolithic thing <img src="https://latex.codecogs.com/png.latex?S"> and rewrite rules as functions <img src="https://latex.codecogs.com/png.latex?%7BS%20%5Crightarrow%20S%7D"> that operate on the entire world state, we think of the world state as a collection of agents operating in a shared environment. Updates are <em>relative to a particular agent</em> performing the update.</p>
<p>Thus, we must now consider a state <em>and</em> a particular choice of agent as living on wires, and we must think of rewrite rules as executed “from the perspective of that agent”. Let’s be more precise about what an agent is: given a world state <img src="https://latex.codecogs.com/png.latex?X">, we want to pick out a particular substructure of <img src="https://latex.codecogs.com/png.latex?X">, meaning our agents are actually maps <img src="https://latex.codecogs.com/png.latex?A%5Crightarrow%20X"> <em>into</em> <img src="https://latex.codecogs.com/png.latex?X">, where <img src="https://latex.codecogs.com/png.latex?A"> describes the <em>shape</em> of the agent. Note that the empty ACSet, denoted as <img src="https://latex.codecogs.com/png.latex?0">, picks out nothing in particular and corresponds to our earlier perspective of a monolithic view of the entire world, <img src="https://latex.codecogs.com/png.latex?X">.</p>
<div class="quarto-figure quarto-figure-center page-columns page-full">
<figure class="figure page-columns page-full">
<p><img src="https://blog.algebraicjulia.org/post/2023/07/graphical-schedule/agent.png" class="img-fluid figure-img" style="width:70.0%" alt="schema"></p>
<figcaption class="margin-caption">A state of the world, <img src="https://latex.codecogs.com/png.latex?X">, with three vertices, three edges, three sheep, and two wolves. What counts as an ‘agent’ here depends on your perspective: if you want to think of two sheep on the same vertex as the active agent for some process (e.g.&nbsp;reproduction), then a map <img src="https://latex.codecogs.com/png.latex?SS%5Crightarrow%20X"> picks out such an agent. Alternatively, a map into <img src="https://latex.codecogs.com/png.latex?X"> from the wolf shape <img src="https://latex.codecogs.com/png.latex?W"> picks out a wolf agent.</figcaption>
</figure>
</div>
<p>So how does this change our notion of a rewrite rule <img src="https://latex.codecogs.com/png.latex?L%20%5Cnrightarrow%20R">? We are no longer rewriting a state <img src="https://latex.codecogs.com/png.latex?X"> but rather a state with an agent: <img src="https://latex.codecogs.com/png.latex?A%0A%5Crightarrow%20X">. We need an extra map <img src="https://latex.codecogs.com/png.latex?Agent_%7BIn%7D%20%5Crightarrow%20L"> to show, given the agent, how it must relate to our pattern. Furthermore, we need an agent (possibly different) from which to exit the rule application, given by a map <img src="https://latex.codecogs.com/png.latex?Agent_%7BOut%7D%20%5Crightarrow%20R">. Adding the data <img src="https://latex.codecogs.com/png.latex?W%20%5Crightarrow%20L"> in the <code>wolf_eat</code> rule transforms the it from “Some wolf eats some sheep” into “<em>This</em> wolf eats some sheep”.</p>
<p>Most often, the incoming and outgoing agents for a rewrite rule are the same. An example where this is not possible is the rule that says “<em>This</em> sheep starves if its energy reaches <img src="https://latex.codecogs.com/png.latex?0">.”</p>
<div class="quarto-figure quarto-figure-center page-columns page-full">
<figure class="figure page-columns page-full">
<p><img src="https://blog.algebraicjulia.org/post/2023/07/graphical-schedule/die.png" class="img-fluid figure-img" style="width:80.0%" alt="schema"></p>
<figcaption class="margin-caption">The distinction between informal graphical syntax and <em>very</em> informal graphical syntax.</figcaption>
</figure>
</div>
</section>
<section id="the-query-box" class="level2">
<h2 class="anchored" data-anchor-id="the-query-box">The <code>Query</code> box</h2>
<p>The <em>trajectory</em> of the world state while executing a program looks like this:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2023/07/graphical-schedule/state.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:40.0%" alt="schema"></p>
</figure>
</div>
<p>This means it’s possible to take an agent <img src="https://latex.codecogs.com/png.latex?A_i"> and interpret it in the ‘current’ state of the world, <img src="https://latex.codecogs.com/png.latex?X_n">, by composing it with the partial maps between <img src="https://latex.codecogs.com/png.latex?X_i"> and <img src="https://latex.codecogs.com/png.latex?X_n">. This updating of an agent could result in a map which is total (i.e.&nbsp;the agent ‘survived’ the update process) or partial, which would happen if some part of the agent was deleted between step <img src="https://latex.codecogs.com/png.latex?i"> and step <img src="https://latex.codecogs.com/png.latex?n">. We take advantage of this ability to update agents with the last major kind of box, the <strong>Query</strong> box.</p>
<p>These are yellow boxes which execute a subroutine for each agent of a particular shape. Once this set of matches is found, the query box stores them in its internal state. Each time we return through the second in port, we pop off the next agent in the queue and exit the second out port. Once this queue is empty, we exit out the first port with our original agent. (There is an edge case to consider: what if, while executing the actions of all the sub-agents from the query, our original agent is deleted? In this case we exit a third output door, which has no agent.)</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2023/07/graphical-schedule/query.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:50.0%" alt="schema"></p>
</figure>
</div>
<p>For example, we may wish to organize our wolf-sheep-grass model as a <code>while</code> loop wrapping three <code>for</code> loops, doing some actions per sheep, per wolf, and per vertex.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2023/07/graphical-schedule/lv.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:50.0%" alt="schema"></p>
</figure>
</div>
<p>In the figure above, ‘Daily’ refers to another program which performs the actions that are common to both sheep and wolves (e.g.&nbsp;rotating, moving, starving). These are originally defined for just sheep, but by observing the symmetry of wolves and sheep in our schema, we can use a <img src="https://latex.codecogs.com/png.latex?%5CDelta"> data migration <img src="https://latex.codecogs.com/png.latex?Swap"> to automatically translate a Sheep Daily program into a Wolf Daily program.</p>
<p>We may consider other ways of changing our agent type other than the <code>Query</code> box. A simple one is the <strong>Weakening</strong> box, which is specified by a morphism between agent shapes: <img src="https://latex.codecogs.com/png.latex?B%20%5Crightarrow%20A">. It converts <img src="https://latex.codecogs.com/png.latex?A"> agents into <img src="https://latex.codecogs.com/png.latex?B"> agents without changing the state of the world. This is because we can precompose this morphism with an agent <img src="https://latex.codecogs.com/png.latex?A%20%5Crightarrow%20X">. In particular, for any agent <img src="https://latex.codecogs.com/png.latex?A"> we can use a weakening <img src="https://latex.codecogs.com/png.latex?0%20%5Crightarrow%20A"> to discard focus on the current agent.</p>
</section>
</section>
<section id="theoretical-underpinning" class="level1">
<h1>Theoretical underpinning</h1>
<section id="what-it-means-for-a-graphical-syntax-to-be-formal" class="level2">
<h2 class="anchored" data-anchor-id="what-it-means-for-a-graphical-syntax-to-be-formal">What it means for a graphical syntax to be formal</h2>
<p>Here is a sort of idealized characterization of 2-D drawings of wiring diagrams:</p>
<ul>
<li>A wiring diagram can be one of some collection of primitive icons, e.g.:
<ul>
<li>perfectly horizontal wires and a</li>
<li>a pair of crossing wires</li>
<li>an element from primitive set of boxes with various in ports and out ports</li>
</ul></li>
<li>A wiring diagram can be made by placing simpler ones side by side<br>
</li>
<li>A wiring diagram can be made by placing simpler ones one on top of the other.</li>
</ul>
<p>The rigid, grid-like diagrams generated by the above rules can be understood as in correspondence to certain expressions in a mathematical theory. Note that the theory comes with its own notion of equality (e.g.&nbsp;<img src="https://latex.codecogs.com/png.latex?id%20%5Ccdot%20f%20=%20f">), <em>and</em> the image has its own notion of equality too: we consider images “up to planar isotopy”, which makes rigorous the notion that it doesn’t matter if you deform the precise locations of things so long as you preserve the same connectivity. Under very special circumstances we can obtain a <em>coherence theorem</em> for a class of wiring diagrams and a particular theory: this says that all equations of the diagrams correspond to equations in the theory (soundness) and all equations of diagrams are a consequence of the theory axioms (completeness). This allows us to relax how rigid our diagrams are depicted while still retaining the formality of terms in a rigorous, mathematical theory.</p>
<p>For example, consider the correspondence of wiring diagrams (without feedback loops) to a theory of symmetric monoidal categories (SMCs) with monoidal unit <img src="https://latex.codecogs.com/png.latex?I"> and a supply of monoids.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2023/07/graphical-schedule/progtable.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:80.0%" alt="schema"></p>
</figure>
</div>
<p>Once we have interpreted our wiring diagram as a morphism in a certain kind of category, applied category theory seeks to interpret the morphism in some real world context, provided that real context can be given the structure of a category (including the satisfaction of required axioms). For a certain toy model of programs with control flow, the third column describes how one can interpret the mathematical expressions in the setting of programs, such that compositions of diagrams can rigorously be interpreted as compositions of programs.</p>
<p>To show the correspondence of the first two columns in action, consider the below composite wiring diagram, which takes for granted a morphism <img src="https://latex.codecogs.com/png.latex?f:%20A%20%5Cotimes%20B%20%5Crightarrow%20A%20%5Cotimes%20B%20%5Cotimes%20C">. Dotted lines are added to visually guide you in parsing the various icons, which are composed vertically and horizontally.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2023/07/graphical-schedule/expr.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:80.0%" alt="schema"></p>
</figure>
</div>
<p>Thanks to a coherence theorem, we can rest easy knowing that the diagram has an unambiguous formal meaning, even if some of the lines are a bit wiggly and don’t <em>exactly</em> match one of our icons.</p>
<p>Some great follow-up reading for what it means for these diagrams to be <em>formal</em> are <span class="citation" data-cites="baez2011physics">Baez and Stay (2011)</span> and <span class="citation" data-cites="selinger2011survey">Selinger (2011)</span>. Also, a great application of graphical languages is pedagogically described in Pawel Sobocinski’s blog <a href="https://graphicallinearalgebra.net/">Graphical Linear Algebra</a>.</p>
</section>
<section id="whats-in-the-box" class="level2">
<h2 class="anchored" data-anchor-id="whats-in-the-box">What’s in the box?</h2>
<p>To connect the above ideas to the graphical language explored in the bulk of this post: the syntax of directed wiring diagrams (<em>with</em> feedback loops) can be given the semantics of a <em>traced SMC</em>, though unpacking what that means theoretically is beyond the scope of this post. In a programming-like setting (the final column in the table above), this corresponds to <code>while</code>-loop style iteration.</p>
<p>In <span class="citation" data-cites="brown2023dynamic">Brown and Spivak (2023)</span>, a theoretical underpinning of this work is proposed. The primary contributions are formulating a general theory of discrete dynamical systems, making progress towards showing that the relevant category is traced monoidal, and then showing how this informs the implementation of the graph rewriting programs described in this post. This involves <em>enriched</em> category theory, the language of polynomial functors, and is parameterized by a polynomial monad, such as:</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7BMaybe%7D=%5Cmathcal%7By%7D+1,%5Cqquad%0A%5Ctext%7BList%7D=%20%5Csum_%7BN:%5Cmathbb%7BN%7D%7D%5Cmathcal%7By%7D%5EN,%20%5Cqquad%0A%5Ctext%7BDist%7D=%5Csum_%7BN:%5Cmathbb%7BN%7D%7D%5CDelta_N%5Cmathcal%7By%7D%5EN%0A"></p>
<p>where <img src="https://latex.codecogs.com/png.latex?%7B%5CDelta_N=%5C%7BP:N%20%5Cto%20%5B0,1%5D%5C%20%7C%5C%201=%5Csum%20P(i)%5C%7D%7D">. It is beyond the scope of this post to rigorously explicate this formalism, which is gently introduced in <span class="citation" data-cites="niupolynomial">Niu and Spivak (n.d.)</span>. However, to provide some intuition for how, in practical ways, this formalism informed the design of the software infrastructure that represents and executes these graphical programs: consider a box <code>swap-x2</code> which has two inputs. Initially, it behaves by swapping the inputs, but once the left inport has been entered twice it behaves like a pair of parallel wires.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2023/07/graphical-schedule/swap.png" class="img-fluid quarto-figure quarto-figure-center figure-img" style="width:80.0%" alt="schema"></p>
</figure>
</div>
<p>The math dictates that what actually should go into this box is a “behavior tree”, where the branching of the tree is dictated by the number of input wires. For every input, we specify how the behavior changes by pointing to a new behavior tree, whose nodes indicate how the input is transformed into outputs.</p>
<p>All of the rewriting primitives (e.g.&nbsp;<code>Rewrite</code>, <code>ControlFlow</code>, <code>Query</code>, <code>Weaken</code>) are implemented in this generic manner, meaning just one implementation (i.e.&nbsp;behavior trees) needs to be written, rather than many special cases for language primitives. Furthermore, the language can be extended, with the formalism allowing us to not worry about unforeseen consequences that follow from <em>ad hoc</em> extension of the language - we have a precise specification for what structure a new primitive needs to satisfy.</p>
<p>The setting of polynomial functors is so expressive that the interfaces of boxes, their internals, their infinite behaviors, and monadic effects on their outputs (like <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BList%7D"> and <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BDist%7D">) are all encompassed in the same formalism, which leads to a cleaner and more general implementation than what would have been arrived upon if the problem were approached head-on in a traditional engineering style.</p>
</section>
</section>
<section id="conclusion" class="level1">
<h1>Conclusion</h1>
<p>The virtues of this approach largely come from the fact that neither code nor arbitrary functions are in principle required to specify our dynamical system <img src="https://latex.codecogs.com/png.latex?S%20%5Crightarrow%20S">. Rather than arbitrary functions (which are hard to manipulate and reason about) being the input, we automatically generate our simulator program from static, graph-like data. While we happen do this in Julia, this could in principle be done in any language because our understanding of a graph rewriting program is mathematical, rather than dependent on implementation details. In collaborations involving multiple teams, it can be helpful that the data of these programs can be serialized in a language-agnostic way.</p>
<p>I have also personally found it immensely useful to be able to apply functorial data migration (see <span class="citation" data-cites="1009.1166">Spivak (2012)</span>), e.g.&nbsp;swapping sheep and wolves, to allow high level reuse of programs in different contexts, which can be done cleanly and rigorously when one’s model is expressed via combinatorial data rather than low-level code.</p>
<p>Although there was not space to describe how all of the virtues listed in the introduction are facilitated by this formalism, I hope you’re intrigued by the possibility of structuring your model of the world’s dynamics in this formalism. Furthermore, I hope this case study in applied category theory encourages you to look into other kinds of scientific or engineering tasks can be made more scalable and maintainable through these kinds of abstractions.<sup>5</sup></p>



</section>


<div id="quarto-appendix" class="default"><section class="quarto-appendix-contents" id="quarto-bibliography"><h2 class="anchored quarto-appendix-heading">References</h2><div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="0">
<div id="ref-baez2011physics" class="csl-entry">
Baez, John, and Mike Stay. 2011. <em>Physics, Topology, Logic and Computation: A Rosetta Stone</em>. Springer.
</div>
<div id="ref-brown2022computational" class="csl-entry">
Brown, Kristopher, Evan Patterson, Tyler Hanks, and James Fairbanks. 2023. <span>“Computational Category-Theoretic Rewriting.”</span> <em>Journal of Logical and Algebraic Methods in Programming</em>, 100888. <a href="https://doi.org/10.1016/j.jlamp.2023.100888">https://doi.org/10.1016/j.jlamp.2023.100888</a>.
</div>
<div id="ref-brown2023dynamic" class="csl-entry">
Brown, Kristopher, and David I. Spivak. 2023. <span>“Dynamic Tracing: A Graphical Language for Rewriting Protocols.”</span> <a href="https://arxiv.org/abs/2304.14950">https://arxiv.org/abs/2304.14950</a>.
</div>
<div id="ref-niupolynomial" class="csl-entry">
Niu, Nelson, and David I Spivak. n.d. <span>“Polynomial Functors: A General Theory of Interaction.”</span>
</div>
<div id="ref-selinger2011survey" class="csl-entry">
Selinger, Peter. 2011. <span>“A Survey of Graphical Languages for Monoidal Categories.”</span> <em>New Structures for Physics</em>, 289–355.
</div>
<div id="ref-1009.1166" class="csl-entry">
Spivak, David I. 2012. <span>“Functorial Data Migration.”</span> <em>Information and Computation</em> 217 (August): 31–51. <a href="https://doi.org/10.1016/j.ic.2012.05.001">https://doi.org/10.1016/j.ic.2012.05.001</a>.
</div>
</div></section><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>

<ol>
<li id="fn1"><p><a href="https://github.com/krishauser/Klampt/blob/master/Cpp/docs/Tutorials/Run-a-simulation-Cpp.md">E.g.</a>, if we live in an object-oriented paradigm:</p>
<pre><code>class WorldModel
{
  int NumIDs() const;   // id's for objects in the world
  int LoadRobot(const string&amp; fn);
  int AddRobot(const string&amp; name,Robot* robot=NULL);
  void DeleteRobot(const string&amp; name);
  int main(int argc,const char** argv) {
    WorldModel world;     //create a world
    double dt = 0.1;      //between printouts 
    while(sim.time &lt; 5) { //run the simulation
      sim.Advance(dt);    //move the sim fwd
      sim.UpdateModel();  //update the world
      cout&lt;&lt;sim.time&lt;&lt;'\t'&lt;&lt;world.robots[0]-&gt;q&lt;&lt;endl;
    }
    return 0;
  }
}</code></pre>
↩︎</li>
<li id="fn2"><p><a href="https://mkdoku.github.io/posts/2021-06-19-molecular-dynamics.html">E.g.</a>, if we live in a functional paradigm:</p>
<pre><code>data Particle = Particle { idx :: Index, 
                           pos :: Position, 
                           vel :: Velocity}
type Model = [Particle]
simulate :: Display            -- Window config
  -&gt; model                     -- Model
  -&gt; (model -&gt; Picture)        -- Draw function
  -&gt; (Float -&gt; model -&gt; model) -- Update function
  -&gt; IO ()</code></pre>
↩︎</li>
<li id="fn3"><p>This is inspired by Netlogo’s <a href="http://ccl.northwestern.edu/netlogo/models/WolfSheepPredation">wolf-sheep predation model</a>. A more faithful reproduction of that model’s dynamics is found in the <a href="https://github.com/AlgebraicJulia/AlgebraicRewriting.jl/blob/main/docs/src/lotka_volterra.jl">docs</a> of AlgebraicRewriting.jl; in this post, we’ll focus on showcasing a more diverse set of AlgebraicRewriting’s features.↩︎</p></li>
<li id="fn4"><p>For more background and computational details, see <span class="citation" data-cites="brown2022computational">Brown et al. (2023)</span>. See also <a href="https://blog.algebraicjulia.org/post/2022/09/ai-planning-cset/#the-anatomy-of-a-rewrite-rule">Angeline’s description</a> on this blog.↩︎</p></li>
<li id="fn5"><p>This work came about through conversations very much akin to the example conversations between the domain expert (me) and ACT expert (David Spivak) in David’s <a href="https://www.youtube.com/watch?v=bJRCg9U7VgE">What Are We Tracking</a> talk, so I encourage you to watch that to get inspiration for other potential fruitful collaborations with mathematicians.↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>rewriting</category>
  <category>attributed-c-sets</category>
  <category>models</category>
  <category>dynamical systems</category>
  <guid>https://blog.algebraicjulia.org/post/2023/07/graphical-schedule/</guid>
  <pubDate>Fri, 07 Jul 2023 00:00:00 GMT</pubDate>
  <media:content url="https://blog.algebraicjulia.org/post/2023/07/graphical-schedule/die2.png" medium="image" type="image/png" height="78" width="144"/>
</item>
<item>
  <title>Acsets with variables</title>
  <dc:creator>Kevin Arlin</dc:creator>
  <dc:creator>Kris Brown</dc:creator>
  <link>https://blog.algebraicjulia.org/post/2023/06/varacsets/</link>
  <description><![CDATA[ 





<div class="hidden">
<p>$$ <!-- Number systems --> </p>
<!-- Categories -->
<!-- Graphs -->
<!-- Double categories -->
<!-- Acsets -->
<!-- Wiring diagrams -->
<!-- Dynamical systems -->
<p>$$</p>
</div>
<p>A central data structure in AlgebraicJulia is the acset, short for <em>attributed <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set</em>. For background on acsets, see <a href="https://blog.algebraicjulia.org/post/2020/09/cset-graphs-1/">this blog post</a>, or the original paper <span class="citation" data-cites="2106.04703">(Patterson, Lynch, and Fairbanks 2021)</span>. <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets store <em>combinatorial</em> data, which consists of sets of indistinguishable objects (such as the vertices of a graph) related by functions. Acsets extend this to include <em>non</em>-combinatorial data, which consists of things with intrinsic meaning such as integers, strings, and so on.</p>
<p>To recall notation, in order to give a category of acsets we first give a <em>schema</em>, a profunctor <img src="https://latex.codecogs.com/png.latex?%7BS:S_0%5Cnrightarrow%20S_1%7D."> Then an acset is a copresheaf <img src="https://latex.codecogs.com/png.latex?F:%7CS%7C%5Cto%20%5Cmathsf%7BSet%7D"> on the collage of <img src="https://latex.codecogs.com/png.latex?S"> with a fixed restriction <img src="https://latex.codecogs.com/png.latex?K"> to <img src="https://latex.codecogs.com/png.latex?S_1"> giving the attribute types, for which reason we’ll call <img src="https://latex.codecogs.com/png.latex?K"> the “typing map.” The morphisms of acsets thus fix everything in <img src="https://latex.codecogs.com/png.latex?K"> exactly. For example, a morphism <img src="https://latex.codecogs.com/png.latex?A%20%5Crightarrow%20B"> between <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-weighted graphs can in principle send any vertex in <img src="https://latex.codecogs.com/png.latex?A"> to any vertex in <img src="https://latex.codecogs.com/png.latex?B">, but we are <em>required</em> to send an edge of weight <img src="https://latex.codecogs.com/png.latex?2.2"> in <img src="https://latex.codecogs.com/png.latex?A"> to an edge of weight <img src="https://latex.codecogs.com/png.latex?2.2"> in <img src="https://latex.codecogs.com/png.latex?B">.</p>
<p><img src="https://blog.algebraicjulia.org/post/2023/06/varacsets/wgraph.png" class="img-fluid"></p>
<p>But for many purposes this is too restrictive. This post is about a generalization of attribute types that allows us to have special attribute values, called <em>variables</em>, which can freely map to concrete values. A major motivation for developing this generalization is to support <a href="https://topos.site/blog/2023/04/conegation-rewriting/#rewriting">rule-based rewriting</a> for acsets. We’re implementing these ideas today in our library <a href="https://github.com/AlgebraicJulia/AlgebraicRewriting.jl">Algebraic Rewriting</a>.</p>
<p>As an example scenario, suppose we are trying to program a robot to assemble objects of various shapes from raw materials. Our first job in modeling this scenario is to pick a schema to represent the state of the world, as perceived by the robot. We’ll use a schema for <em>mechanical linkages</em>, which we’ll model as an attributed <a href="https://blog.algebraicjulia.org/post/2020/09/cset-graphs-1/#symmetric-graphs">symmetric graph</a>, where edges represent links using a length attribute, and vertices represent positions using a coordinate attribute.<sup>1</sup></p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2023/06/varacsets/Schema.png" class="img-fluid figure-img"></p>
<figcaption>The schema for mechanical linkages and its typing map</figcaption>
</figure>
</div>
<p>As an illustrative rewriting rule, let’s suppose that, whenever our robot sees a rectangular figure, it is allowed to tear the top off and fold the remaining open shape into an isosceles triangle. We can draw this fact as a rewriting rule; however, a well-formed acset requires us to put concrete attribute values for all the lengths and positions:</p>
<p><img src="https://blog.algebraicjulia.org/post/2023/06/varacsets/badrule.png" class="img-fluid"></p>
<p>Having been forced to pick particular values, we are then unable to apply the rule to any rectangles of different dimensions (or located at different coordinates). The notion of a variable which can map into an arbitrary concrete value will allow us to write the rule we intended to write.</p>
<section id="whats-a-varacset" class="level1">
<h1>What’s a varacset?</h1>
<p><em>Varacsets</em>, short for “variable-equipped acsets”, allow for a supply of distinguishable <em>variables</em> from attribute types, which can be mapped to constants under acset morphisms. This should leave our rewrite rule looking something like this (with position variables omitted for brevity):</p>
<p><img src="https://blog.algebraicjulia.org/post/2023/06/varacsets/rule.png" class="img-fluid"></p>
<p>By allowing a set of distinguishable variables, which can explicitly be equal or not equal to each other, rather than merely extending the attribute type <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D"> to include a wildcard element, <img src="https://latex.codecogs.com/png.latex?%7B%5Cmathbb%7BR%7D+%5C%7B*%5C%7D%7D">, we can model a <em>parallelogram</em> with the leftmost acset, rather than an arbitrary quadrilateral.</p>
<p>Although we can visualize these varacsets as undirected graphs, varacsets on any schema can be viewed as a set of tables in its database representation:</p>
<div id="database" class="quarto-layout-panel" data-layout-ncol="2">
<div class="quarto-layout-row">
<div class="quarto-layout-cell" style="flex-basis: 50.0%;justify-content: center;">
<table class="caption-top table">
<thead>
<tr class="header">
<th style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?V"></th>
<th style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?%5Ctexttt%7Bpos%7D"></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?1"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?(5,-2,7.1)"></td>
</tr>
<tr class="even">
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?2"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?%5Cmathbf%7BAttrVar%7D(1)"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?3"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?(%5Cpi,2%5Cpi,-2/3)"></td>
</tr>
</tbody>
</table>
</div>
<div class="quarto-layout-cell" style="flex-basis: 50.0%;justify-content: center;">
<table class="caption-top table">
<thead>
<tr class="header">
<th style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?E"></th>
<th style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?x"></th>
<th style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?t"></th>
<th style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?%5Csigma"></th>
<th style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?%5Ctexttt%7Blen%7D"></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?1"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?1"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?2"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?2"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?%5Cmathbf%7BAttrVar%7D(1)"></td>
</tr>
<tr class="even">
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?2"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?2"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?1"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?1"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?%5Cmathbf%7BAttrVar%7D(1)"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?3"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?2"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?3"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?4"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?15.2"></td>
</tr>
<tr class="even">
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?4"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?3"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?2"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?3"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?15.2"></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2023/06/varacsets/Database.png" class="img-fluid figure-img"></p>
<figcaption>The database view of a mechanical linkage</figcaption>
</figure>
</div>
</section>
<section id="whats-the-category-of-varacsets" class="level1">
<h1>What’s the category of varacsets?</h1>
<p>Although the objects of acsets are the same as relational databases, they are much more powerful because we understand them as a category and can perform categorical constructions. Thus it’s important to understand how varacsets are a category such that we can find homomorphisms and compute (co)limits.</p>
<section id="defining-the-category" class="level2">
<h2 class="anchored" data-anchor-id="defining-the-category">Defining the category</h2>
<p>Let’s figure out what the category of varacsets looks like more precisely. Given a schema <img src="https://latex.codecogs.com/png.latex?S_0%5Cnrightarrow%20S_1,"> we start with a typing map <img src="https://latex.codecogs.com/png.latex?K:S_1%5Cto%20%5Cmathsf%7BSet%7D"> which gives the values of each attribute type. Our full varacset should augment this data with combinatorial data over <img src="https://latex.codecogs.com/png.latex?S_0"> and a supply of variables over <img src="https://latex.codecogs.com/png.latex?S_1,"> plus the actual attribute functions. Furthermore, we want to end up in a category where the morphisms fix the constants of each attribute type but move variables freely. This defines a category well enough, but its nature isn’t very clear.</p>
<section id="why-a-different-approach-from-acsets-is-needed" class="level3">
<h3 class="anchored" data-anchor-id="why-a-different-approach-from-acsets-is-needed">Why a different approach from acsets is needed</h3>
<section id="acsets-as-a-slice-category-of-mathsfc-mathsfset" class="level4">
<h4 class="anchored" data-anchor-id="acsets-as-a-slice-category-of-mathsfc-mathsfset">Acsets as a slice category of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-<img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSet%7D"></h4>
<p>In the original acsets paper, the authors proved that the category of acsets with attribute types determined by <img src="https://latex.codecogs.com/png.latex?K:S_1%5Cto%20%5Cmathsf%7BSet%7D"> is equivalent to the slice category of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSet%7D%5E%7BS_0%7D"> over a certain functor <img src="https://latex.codecogs.com/png.latex?K'"> closely related to <img src="https://latex.codecogs.com/png.latex?K">. This characterization is very helpful in seeing that the category of acsets with fixed typing is friendly (indeed, a topos), but it’s not computationally usable, because the functor <img src="https://latex.codecogs.com/png.latex?K'"> (a certain right Kan extension) is generally something badly infinite. But the most interesting computations we can do in AlgebraicJulia, such as acset homomorphism search, depend on looking at acsets whose values over <img src="https://latex.codecogs.com/png.latex?S_0"> are finite sets. In any case, this trick can’t be readily imported to our situation, because the analog of <img src="https://latex.codecogs.com/png.latex?K'"> would depend on the variables present in each particular acset and not only on the schema.</p>
</section>
<section id="flipping-the-slice" class="level4">
<h4 class="anchored" data-anchor-id="flipping-the-slice">Flipping the slice</h4>
<p>While the collaginess of <img src="https://latex.codecogs.com/png.latex?%7CS%7C"> sure makes us want to think of <img src="https://latex.codecogs.com/png.latex?F"> being <em>over</em> <img src="https://latex.codecogs.com/png.latex?K"> in some sense, this is largely an illusion. What’s much more straightforward to formalize is a view of <img src="https://latex.codecogs.com/png.latex?F"> as <em>under</em> a relative of <img src="https://latex.codecogs.com/png.latex?K:"> namely, the functor <img src="https://latex.codecogs.com/png.latex?K_!"> which adds empty values over <img src="https://latex.codecogs.com/png.latex?S_0"> to extend <img src="https://latex.codecogs.com/png.latex?K"> to all of <img src="https://latex.codecogs.com/png.latex?%7CS%7C."></p>
<div id="fig-overunder" class="quarto-layout-panel">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-overunder-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<div class="quarto-layout-row">
<div class="quarto-layout-cell-subref quarto-layout-cell" data-ref-parent="fig-overunder" style="flex-basis: 50.0%;justify-content: flex-start;">
<div id="fig-over" class="quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-subfloat-fig figure">
<div aria-describedby="fig-over-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://blog.algebraicjulia.org/post/2023/06/varacsets/Over.png" class="img-fluid figure-img" data-ref-parent="fig-overunder">
</div>
<figcaption class="quarto-float-caption-bottom quarto-subfloat-caption quarto-subfloat-fig" id="fig-over-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
(a) A mechanical linkage, apparently over <img src="https://latex.codecogs.com/png.latex?K">
</figcaption>
</figure>
</div>
</div>
<div class="quarto-layout-cell-subref quarto-layout-cell" data-ref-parent="fig-overunder" style="flex-basis: 50.0%;justify-content: flex-start;">
<div id="fig-under" class="quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-subfloat-fig figure">
<div aria-describedby="fig-under-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://blog.algebraicjulia.org/post/2023/06/varacsets/Under.png" class="img-fluid figure-img" data-ref-parent="fig-overunder">
</div>
<figcaption class="quarto-float-caption-bottom quarto-subfloat-caption quarto-subfloat-fig" id="fig-under-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
(b) The true situation, revealed
</figcaption>
</figure>
</div>
</div>
</div>
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-overunder-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1: Over or under?
</figcaption>
</figure>
</div>
<p>Indeed, the <em>coslice</em> category <img src="https://latex.codecogs.com/png.latex?K_!/%20%5Cmathsf%7BSet%7D%5E%7B%7CS%7C%7D"> is awfully close to the category of acsets. Specifically, if you restrict to the full subcategory of the coslice spanned by maps from <img src="https://latex.codecogs.com/png.latex?K_!"> which are <em>invertible</em> over <img src="https://latex.codecogs.com/png.latex?S_1,"> then this is equivalent to the category of acsets as defined above. Indeed, maps in <img src="https://latex.codecogs.com/png.latex?K_!/%20%5Cmathsf%7BSet%7D%5E%7B%7CS%7C%7D"> have to leave the image of <img src="https://latex.codecogs.com/png.latex?K">, i.e.&nbsp;our attribute values, put, but are just any old natural transformations on the rest of the functor, i.e.&nbsp;our combinatorial data.</p>
<p>For varacsets, we don’t want a coslice object <img src="https://latex.codecogs.com/png.latex?K_!%5Cto%20F"> which is <em>iso</em> over <img src="https://latex.codecogs.com/png.latex?S_1,"> though. Instead, since we want to be able to add variables to our attribute types, we’d better relax at least to a mono. And that’s really all you have to do! The key observation is that <em>variables</em> in the attribute types behave precisely like combinatorial data: we can permute them around however we want without changing the meaning of an acset. This is basically the category we have implemented in AlgebraicJulia today: the full subcategory of <img src="https://latex.codecogs.com/png.latex?K_!%5Cdownarrow%20%5Cmathsf%7BSet%7D%5E%7B%7CS%7C%7D"> on monomorphisms.</p>
</section>
</section>
<section id="final-definition" class="level3">
<h3 class="anchored" data-anchor-id="final-definition">Final definition</h3>
<p>The nicest definition of a category of varacsets with attribute types given by <img src="https://latex.codecogs.com/png.latex?K:S_1%5Cto%5Cmathsf%7BSet%7D,"> though, is simply the <em>entire coslice category</em> <img src="https://latex.codecogs.com/png.latex?K_!%5Cdownarrow%20%5Cmathsf%7BSet%7D%5E%7B%7CS%7C%7D,"> without the monicity restriction. One can imagine applications of the case where the coslice morphism is non-monic; for instance, such a varacset on the weighted graph schema would allow us to mix ordinary weighted graphs, with edges weighted in <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%20R,"> with “angled graphs”, with edges weighted in the circle, <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%20R/2%5Cpi."> In this case, the component of the coslice structure map at the weights object would be the canonical projection from the line to the circle.</p>
<p>Is this good? Maybe! In any case, the full coslice category has much better mathematical properties than the mono-coslice category. We will show in the next section precautions we can take if we wish to maintain the monicity restriction in practice.</p>
</section>
</section>
<section id="wandering-variables" class="level2">
<h2 class="anchored" data-anchor-id="wandering-variables">Wandering variables</h2>
<p>We can also define <em>wandering variables</em> as elements over some <img src="https://latex.codecogs.com/png.latex?A%5Cin%20S_1"> that are not in the image of any attribute function. Varacsets with no wandering variables have some good properties; for example, only if <img src="https://latex.codecogs.com/png.latex?X"> has no wandering variables can we enumerate morphisms <img src="https://latex.codecogs.com/png.latex?%7B%5Calpha:%20X%20%5Crightarrow%20Y%7D."> (In database theory lingo, we could say that such an acset has all its variables in the <em>active domain</em>.)</p>
<p>To illustrate, when each weight variable in a weighted graph has an associated edge, the regular acset search algorithm (which finds all compatible assignments of edges and vertices) will homomorphism determine where the edge weights must be sent via the naturality condition associated with the weight attribute (<img src="https://latex.codecogs.com/png.latex?%5Calpha_E%5Ccdot%20Y_%7Bweight%7D%20=%20X_%7Bweight%7D%5Ccdot%20%5Calpha_%7B%5Ctexttt%7BWeight%7D%7D">). However, a wandering variable’s image is not determined by this constraint, and in principle it could map to <em>any</em> weight variable in <img src="https://latex.codecogs.com/png.latex?Y"> as well as any concrete value in <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">. This means there would be an infinite number of morphisms <img src="https://latex.codecogs.com/png.latex?X%20%5Crightarrow%20Y."> We’ll see further below that the category of acsets without any wandering variables is better-behaved than you might expect.</p>
</section>
<section id="computing-colimits" class="level2">
<h2 class="anchored" data-anchor-id="computing-colimits">Computing colimits</h2>
<p>The coslice <img src="https://latex.codecogs.com/png.latex?K_!%5Cdownarrow%20%5Cmathsf%7BSet%7D%5E%7B%7CS%7C%7D"> is complete and cocomplete, and more: it’s not a topos anymore, but it <em>is</em> the category of models of a multi-sorted algebraic theory, which is pretty good.<sup>2</sup> The monos-only category won’t even be cocomplete, since for instance pushouts will screw up mono-ness. In contrast, <img src="https://latex.codecogs.com/png.latex?K_!%5Cdownarrow%20%5Cmathsf%7BSet%7D%5E%7B%7CS%7C%7D"> has colimits computed mostly as in <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSet%7D%5E%7B%7CS%7C%7D,"> that is, levelwise; you just have to replace coproducts with pushouts under <img src="https://latex.codecogs.com/png.latex?K_!,"> and similarly for other colimits over non-connected diagrams.</p>
<p>In terms of varacsets, passing to the full coslice category allows us to consider something like the pushout of a span whose legs send a variable-weight edge to edges of two different constant weights.</p>
<p><img src="https://blog.algebraicjulia.org/post/2023/06/varacsets/badglue.png" class="img-fluid"></p>
<p>In the pushout, we just won’t be able to distinguish those two weights from each other anymore. If they don’t <em>need</em> to be distinguished, then this is great! That said, we generally only expect to be computing colimits that don’t require gluing together terms of the type of constants in an attribute, and so far we do not support any means of representing the resulting infinite sets with some elements marked as equivalent. So, with the caveat that we throw a runtime error in case concrete attribute values get identified, the colimits coming from <img src="https://latex.codecogs.com/png.latex?K_!%5Cdownarrow%20%5Cmathsf%7BSet%7D%5E%7B%7CS%7C%7D"> are doing exactly what we want.</p>
</section>
<section id="computing-limits" class="level2">
<h2 class="anchored" data-anchor-id="computing-limits">Computing limits</h2>
<p>Varacsets are an unusual category in which limits are trickier than colimits. To be sure, the limits in a coslice of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSet%7D%5E%7B%7CS%7C%7D"> are computed exactly as in <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSet%7D%5E%7B%7CS%7C%7D,"> that is, levelwise. However, these limits have some issues, semantically. For instance, suppose you take the <em>product</em> of, say, two weighted graphs, with weights valued in <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%20R."> Then the product in <img src="https://latex.codecogs.com/png.latex?K%5Cdownarrow%20%5Cmathsf%7BSet%7D%5E%7B%7CS%7C%7D"> is going to have the weights valued in <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%20R%5Ctimes%20%5Cmathbb%20R"> and <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D%5E3%5Ctimes%20%5Cmathbb%7BR%7D%5E3,"> which is a whole different kind of situation!</p>
<p>While this is categorically-correct behavior, it’s not what we want in practice. Instead, we’d really like to make a construction that’s at least product-<em>like</em> that does not change the datatypes of attributes. It’s actually harder than you might guess to find a category in which to do this. The mono-coslice category we discussed earlier has the same products as the full coslice, and the need to allow for variables stops us thinking about the iso-coslice.</p>
<p>For further comparison, in the original slice model of acsets, the products are also a bit questionable: a product in a slice is a pullback in the base, so you end up getting a construction such that, for example, the “product” of two weighted graphs only gets those edges in the product of the underlying graphs that have the <em>exact same weight</em> under both projections! The user often won’t want to throw away so much information just to get an object projecting nicely onto the two given objects.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2023/06/varacsets/badmul.png" class="img-fluid figure-img"></p>
<figcaption><strong>Left</strong>: product in coslice category produces pairs of attribute values. <strong>Right</strong>: product in slice category only yielding the edges/vertices which have identical attribute values.</figcaption>
</figure>
</div>
<p>So the product in the coslice has the advantage of not throwing away information, but the disadvantage of changing the attribute types every time you take a product, while the product in the slice reverses these advantages and disadvantages. We’d like to at least have the option of stabilizing the situation, so that we can take products or do something similar in a category of acsets with <em>fixed</em> attribute types.</p>
<section id="the-abstraction-construction" class="level3">
<h3 class="anchored" data-anchor-id="the-abstraction-construction">The abstraction construction</h3>
<p>Given two varacsets <img src="https://latex.codecogs.com/png.latex?X,Y"> on a schema <img src="https://latex.codecogs.com/png.latex?S,"> the product-like thing you can build from them in AlgebraicJulia is constructed as follows, in elementary terms:</p>
<ol type="1">
<li>Replace <img src="https://latex.codecogs.com/png.latex?X"> and <img src="https://latex.codecogs.com/png.latex?Y"> with their <em>abstractions</em> <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7Babs%7D(X),%5Cmathrm%7Babs%7D(Y),"> copresheaves on <img src="https://latex.codecogs.com/png.latex?%7CS%7C"> (or varacsets with empty typing functor) that move every constant attribute value occurring in <img src="https://latex.codecogs.com/png.latex?X"> and <img src="https://latex.codecogs.com/png.latex?Y"> to a new variable. (So if weights <img src="https://latex.codecogs.com/png.latex?%5Cpi,e,"> and <img src="https://latex.codecogs.com/png.latex?7.0"> occur in <img src="https://latex.codecogs.com/png.latex?X,"> then <img src="https://latex.codecogs.com/png.latex?X'"> will have three new variable weights representing those values.)</li>
<li>Take the product of <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7Babs%7D(X)"> and <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7Babs%7D(Y)"> over <img src="https://latex.codecogs.com/png.latex?S_0"> and provide them with variables over <img src="https://latex.codecogs.com/png.latex?S_1"> for every pair of attribute values in the two factors.</li>
<li>Add the original <img src="https://latex.codecogs.com/png.latex?K">’s constants back into the attribute types in this product-ish object to get a varacset <img src="https://latex.codecogs.com/png.latex?X%5Cotimes%20Y"> over <img src="https://latex.codecogs.com/png.latex?K."></li>
</ol>
<p>Let’s call the resulting construction the “faux product.” For instance, if <img src="https://latex.codecogs.com/png.latex?X"> and <img src="https://latex.codecogs.com/png.latex?Y"> are weighted graphs, then the faux product <img src="https://latex.codecogs.com/png.latex?X%5Cotimes%20Y"> has underlying graph the product of the underlying graphs of <img src="https://latex.codecogs.com/png.latex?X"> and <img src="https://latex.codecogs.com/png.latex?Y,"> with <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D"> the type of constant weights, and variable weights on <em>every</em> pair of edges from <img src="https://latex.codecogs.com/png.latex?X"> and <img src="https://latex.codecogs.com/png.latex?Y."> These variables coincide if and only if the weights of their two edges coincide.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2023/06/varacsets/pprod.png" class="img-fluid figure-img"></p>
<figcaption>Although <code>x</code> is <em>not</em> itself a pair of weights, the pair can be recovered via the projection maps which send <img src="https://latex.codecogs.com/png.latex?x%5Cmapsto%20a"> and <img src="https://latex.codecogs.com/png.latex?x%20%5Cmapsto%203.1">.</figcaption>
</figure>
</div>
<p>We can extend this to limits more generally, such as the following example of stratification which more closely matches our geometric intuitions for how products of graphs ought work.</p>
<p><img src="https://blog.algebraicjulia.org/post/2023/06/varacsets/ppull.png" class="img-fluid"></p>
<p>This faux product gets us most of what we wanted. While it’s odd to have turned all the weights into variables, the user can <em>evaluate</em> the weights in the faux product in any way they like after the construction; for instance, by taking the sum or product of the weights from the two factors, or even by the tautological evaluation to a pair in <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D%5E2."> Since what evaluation, if any, will be appropriate depends on the application at hand, <img src="https://latex.codecogs.com/png.latex?X%5Cotimes%20Y"> is a good place for the general code to leave off.</p>
</section>
<section id="the-abstraction-adjunction" class="level3">
<h3 class="anchored" data-anchor-id="the-abstraction-adjunction">The abstraction adjunction</h3>
<p>It turns out that <img src="https://latex.codecogs.com/png.latex?X%5Cotimes%20Y"> has a pretty pleasing categorical description. In general, let <img src="https://latex.codecogs.com/png.latex?i:%5Cmathsf%7BC%7D%5Cleftrightarrows%20%5Cmathsf%7BD%7D:R"> be a coreflective subcategory, that is, <img src="https://latex.codecogs.com/png.latex?i"> is fully faithful and left adjoint to <img src="https://latex.codecogs.com/png.latex?R."> If <img src="https://latex.codecogs.com/png.latex?D"> has finite products, then there’s always an induced monoidal structure on <img src="https://latex.codecogs.com/png.latex?D"> given by <img src="https://latex.codecogs.com/png.latex?(A,B)%5Cmapsto%20iR(A%5Ctimes%20B)"> and with <img src="https://latex.codecogs.com/png.latex?iR(1)"> as the unit. That is, take the product, and then hit it with the idempotent comonad associated to the coreflective subcategory.<sup>3</sup></p>
<p>In our case, the construction above can be modeled by defining the <em>abstraction functor</em> that sends a varacset <img src="https://latex.codecogs.com/png.latex?X"> on schema <img src="https://latex.codecogs.com/png.latex?S"> with typing <img src="https://latex.codecogs.com/png.latex?K"> to the copresheaf <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7Babs%7D(X)"> on <img src="https://latex.codecogs.com/png.latex?%7CS%7C"> that coincides with <img src="https://latex.codecogs.com/png.latex?X"> over <img src="https://latex.codecogs.com/png.latex?S_0"> and such that, on <img src="https://latex.codecogs.com/png.latex?A%5Cin%20S_1,"> we have <img src="https://latex.codecogs.com/png.latex?X'(A)=%5Csum_%7BT%7D%5Csum_%7Ba:S(T,A)%7D%0Aa(X(T))."> That is, over an attribute type, <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7Babs%7D(X)"> has one combinatorial piece of data for each value of that attribute achieved by some element of <img src="https://latex.codecogs.com/png.latex?X."></p>
<p>Note that <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7Babs%7D(X)"> always lacks <em>wandering variables</em>. And in fact, while abstraction is not a right adjoint when valued in <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSet%7D%5E%7B%7CS%7C%7D">, it <em>is</em> a right adjoint when we take the codomain <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSet%7D%5E%7B%7CS%7C%7D_w"> to be the full subcategory spanned by those copresheaves with no wandering variables. (Limits in this subcategory take limits in <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSet%7D%5E%7B%7CS%7C%7D"> and then throw away wandering variables.) The left adjoint to abstraction simply sends <img src="https://latex.codecogs.com/png.latex?Y"> to <img src="https://latex.codecogs.com/png.latex?Y%5Ccup%20K."> This is fully faithful (but only because <img src="https://latex.codecogs.com/png.latex?Y"> lacks wandering variables!) and so we’re in the situation of the previous paragraph.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2023/06/varacsets/Abstraction.png" class="img-fluid figure-img"></p>
<figcaption>The abstraction adjunction</figcaption>
</figure>
</div>
<p>That is, to summarize, we have an idempotent comonad on the category of varacsets on <img src="https://latex.codecogs.com/png.latex?S"> with typing <img src="https://latex.codecogs.com/png.latex?K,"> sending <img src="https://latex.codecogs.com/png.latex?X"> to the varacset <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7Babs%7D(X)"> with the same set of constants as <img src="https://latex.codecogs.com/png.latex?X"> at every attribute type, but with all the attribute <em>values</em> from <img src="https://latex.codecogs.com/png.latex?X"> replaced with new variables. Then the faux product defined above is precisely <img src="https://latex.codecogs.com/png.latex?(X,Y)%5Cmapsto%20%5Coverline%0A%7B%5Cmathrm%7Babs%7D(X%5Ctimes%20Y)%7D."> <sup>4</sup></p>
</section>
</section>
</section>
<section id="conclusion" class="level1">
<h1>Conclusion</h1>
<p>Varacsets, originally born out of practical engineering demands for rewriting with attributes, are put on much more stable footing by working out the above theoretical considerations. Just as acsets were not implemented as a slice category, varacsets demonstrate that the right mathematical model doesn’t have to be isomorphic to your implementation: understanding varacsets as a coslice (despite implementing them as a database) is helpful for informing us which operations make sense or do not make sense to perform on varacsets.</p>
<p>Although we focused on rewriting rules in this post, there are lots of other ways to apply attribute variables, e.g.&nbsp;when modeling systems in which some attribute data is unknown. This allows us to <img src="https://latex.codecogs.com/png.latex?%5CSigma">-migrate data with attributes (via a <a href="https://blog.algebraicjulia.org/post/2022/06/chase/">left Kan extension</a>), as variables give us a universal way to assign attribute values to new data. We’re excited to push varacsets in other directions like this in the future!</p>



</section>


<div id="quarto-appendix" class="default"><section class="quarto-appendix-contents" id="quarto-bibliography"><h2 class="anchored quarto-appendix-heading">References</h2><div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="0">
<div id="ref-2106.04703" class="csl-entry">
Patterson, Evan, Owen Lynch, and James Fairbanks. 2021. <span>“Categorical Data Structures for Technical Computing.”</span> <a href="https://doi.org/10.32408/compositionality-4-5">https://doi.org/10.32408/compositionality-4-5</a>.
</div>
</div></section><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>

<ol>
<li id="fn1"><p>Note that the length of an edge must equal the Euclidean distance between its source and target to give a semantically valid instance of this schema. This can only be handled perfectly via a Cartesian schema, so we’ll ignore the constraints for now.↩︎</p></li>
<li id="fn2"><p>I really just mean to say the forgetful functor is monadic, which is easy to check from the monadicity theorem. But you can explicitly realize such a theory by augmenting <img src="https://latex.codecogs.com/png.latex?S,"> seen as a theory in the sad logic of a plain category (so only unary operations), with a terminal object and maps from it giving nullary operations for every element of <img src="https://latex.codecogs.com/png.latex?K.">↩︎</p></li>
<li id="fn3"><p>That this is a monoidal structure follows from the natural isomorphism <img src="https://latex.codecogs.com/png.latex?iR(iR(x)%5Ctimes%20y)%5Cto%20iR(x%5Ctimes%20y).">↩︎</p></li>
<li id="fn4"><p>Limits of other shapes can be constructed in an entirely analogous way: abstract the diagram, take the limit in <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSet%7D%5E%7B%7CS%7C%7D_w,"> and then apply the adjoint of abstraction to get your typing functor <img src="https://latex.codecogs.com/png.latex?K"> back.↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>algebra</category>
  <category>logic</category>
  <guid>https://blog.algebraicjulia.org/post/2023/06/varacsets/</guid>
  <pubDate>Tue, 20 Jun 2023 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Symbolic presentations of dynamical systems</title>
  <dc:creator>Owen Lynch</dc:creator>
  <link>https://blog.algebraicjulia.org/post/2023/05/algebraic-geometry-2/</link>
  <description><![CDATA[ 





<div class="hidden">
<p>$$ <!-- Number systems --> </p>
<!-- Categories -->
<!-- Graphs -->
<!-- Double categories -->
<!-- Acsets -->
<!-- Wiring diagrams -->
<!-- Dynamical systems -->
<p>$$</p>
</div>
<section id="part-1-open-dynamical-systems" class="level1">
<h1>Part 1: Open dynamical systems</h1>
<p>We begin this post by talking about open dynamical systems. Open dynamical systems have been studied extensively within applied category theory (see <span class="citation" data-cites="myers_categorical_2022">Myers (2022)</span>), and additionally have been a part of AlgebraicJulia for a while, with <a href="https://github.com/AlgebraicJulia/AlgebraicDynamics.jl">AlgebraicDynamics</a>, <a href="../../../../post/2021/01/machines/">accompanying blog post</a>.</p>
<p>In this post, I sketch out an approach to doing open dynamical systems <em>symbolically</em>. This means that the vector fields for open dynamical systems are given by symbolic expressions, rather than arbitrary Julia functions.</p>
<p>This has the following advantages.</p>
<ol type="1">
<li>Expressions can be serialized and stored in a database.</li>
<li>Expressions can be compared for equality modulo the laws of a theory.</li>
<li>The execution of expressions can be optimized in different ways, or translated into other formats.</li>
<li>Expressions can have metadata attached.</li>
<li>Expressions can be input from non-Julia programs.</li>
<li>Expressions can be displayed in a nice format to the user.</li>
</ol>
<p>In <a href="../../../../post/2023/03/algebraic-geometry-1/">my previous blog post</a>, I lay out the mathematics behind symbolic representation of functions between spaces. Here I now apply that theory to the specific case of open dynamical systems.</p>
<p>We start out by reviewing open dynamical systems.</p>
<p>In this section we use the word “space” and don’t define what a space is. This is because in a certain sense, we are agnostic as to the exact definition of space. All we really care is that the space supports some notion of derivative, as we are doing continuous-time dynamical systems. In order of increasing generality, a space could mean:</p>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D%5En"> for some <img src="https://latex.codecogs.com/png.latex?n"></li>
<li>open subsets of <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D%5En"></li>
<li>a manifold</li>
<li>a <a href="https://ncatlab.org/nlab/show/C%5E%E2%88%9E-ring"><img src="https://latex.codecogs.com/png.latex?C%5E%5Cinfty"> ring</a></li>
<li>an object of any <a href="https://ncatlab.org/nlab/show/tangent+bundle+category">tangent bundle category</a></li>
</ul>
<p>Pick whichever level of generality you are comfortable with, and mentally replace every time I say “space” with that choice. I’ll generally give examples with <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D%5En">; if you know about the more general types of spaces then you should know enough to generalize what I am saying.</p>
<p>The important thing is that any space <img src="https://latex.codecogs.com/png.latex?X"> supports a notion of <em>tangent space at a point <img src="https://latex.codecogs.com/png.latex?x"></em>, denoted by <img src="https://latex.codecogs.com/png.latex?T_x%20X">, and <em>tangent bundle</em> denoted by <img src="https://latex.codecogs.com/png.latex?T%20X">. The tangent bundle consists of all of the tangent spaces put together, i.e.&nbsp;as sets</p>
<p><img src="https://latex.codecogs.com/png.latex?%20TX%20=%20%5Csum_%7Bx%20%5Cin%20X%7D%20T_x%20X%20"></p>
<p>If <img src="https://latex.codecogs.com/png.latex?X%20=%20%5Cmathbb%7BR%7D%5En">, then <img src="https://latex.codecogs.com/png.latex?T_x%20X%20%5Ccong%20%5Cmathbb%7BR%7D%5En"> and <img src="https://latex.codecogs.com/png.latex?T%20X%20%5Ccong%20%5Cmathbb%7BR%7D%5En%20%5Ctimes%20%5Cmathbb%7BR%7D%5En">.</p>
<p>A <strong>vector field</strong> on a space <img src="https://latex.codecogs.com/png.latex?X"> consists of a <strong>section of the tangent bundle</strong> <img src="https://latex.codecogs.com/png.latex?v%20%5Ccolon%20X%20%5Cto%20T%20X">, i.e.&nbsp;a function <img src="https://latex.codecogs.com/png.latex?v"> such that <img src="https://latex.codecogs.com/png.latex?v(x)%20%5Cin%20T_x%20X"> for all <img src="https://latex.codecogs.com/png.latex?x%20%5Cin%20X">. This gives a tangent vector at each point; you can visualize this by <a href="https://www.google.com/search?tbm=isch&amp;q=vector%20field&amp;tbs=imgo:1">searching “vector field” in google images</a>.</p>
<p>Finally, I will behave like a physicist in that I will not overburden myself with saying precisely how differentiable all my functions are. If a function needs to be differentiable, then you can assume that it is.</p>
<p>With these preliminaries out of the way, we can start talking about dynamical systems.</p>
<div id="def-closed-dynamical-system" class="theorem definition">
<p><span class="theorem-title"><strong>Definition 1</strong></span> A <strong>closed dynamical system</strong> consists of:</p>
<ol type="1">
<li>A space <img src="https://latex.codecogs.com/png.latex?X">, called the <strong>state space</strong></li>
<li>A vector field <img src="https://latex.codecogs.com/png.latex?v%20%5Ccolon%20X%20%5Cto%20T%20X">, with <img src="https://latex.codecogs.com/png.latex?v(x)%20%5Cin%20T_x%20X"> for all <img src="https://latex.codecogs.com/png.latex?x%20%5Cin%20X">.</li>
</ol>
</div>
<p>We often refer to <img src="https://latex.codecogs.com/png.latex?v"> as the “dynamics” of the system. Applied mathematicians and physicists might be more used to seeing such a system written using the equation</p>
<p><img src="https://latex.codecogs.com/png.latex?%20%5Cdot%7Bx%7D%20=%20v(x)%20"></p>
<p>However, as a mathematical object, the “data” of this equation is simply the function <img src="https://latex.codecogs.com/png.latex?v">.</p>
<div id="exm-petri-closed" class="theorem example">
<p><span class="theorem-title"><strong>Example 1</strong></span> Given any Petri net <img src="https://latex.codecogs.com/png.latex?P"> (where <img src="https://latex.codecogs.com/png.latex?P(S)"> is the set of species and <img src="https://latex.codecogs.com/png.latex?P(T)"> is the set of transitions), with fixed positive rates <img src="https://latex.codecogs.com/png.latex?r%20%5Cin%20%5Cmathbb%7BR%7D%5E%7BP(T)%7D_%7B%3E0%7D">, there is a closed dynamical system <img src="https://latex.codecogs.com/png.latex?(X_P,%20v_P)">, where</p>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?X_P%20=%20%5Cmathbb%7BR%7D%5E%7BP(S)%7D_%7B%3E0%7D"></li>
<li><img src="https://latex.codecogs.com/png.latex?v_P%20%5Ccolon%20X_P%20%5Cto%20T%20X_P"> is given by the mass action formula</li>
</ul>
</div>
<p>In the real world, systems are rarely closed; other parts of the world have influence on the system. Classically, we might capture this with the equation</p>
<p><img src="https://latex.codecogs.com/png.latex?%20%5Cdot%7Bx%7D%20=%20v(x,%20u)%20"></p>
<p>where <img src="https://latex.codecogs.com/png.latex?u"> is some other variable. However, this only captures part of “openness”; this system might also affect other systems, or we may only observe some part of a system. So we also have an “output” equation</p>
<p><img src="https://latex.codecogs.com/png.latex?%20y%20=%20f(x)%20"></p>
<p>Our system might affect other systems through <img src="https://latex.codecogs.com/png.latex?y">.</p>
<p>We now state this more formally.</p>
<div id="def-open-dynamical-system" class="theorem definition">
<p><span class="theorem-title"><strong>Definition 2</strong></span> An <strong>open dynamical system</strong> consists of three spaces and two functions. The spaces are:</p>
<ul>
<li>A <strong>state space</strong> <img src="https://latex.codecogs.com/png.latex?X"></li>
<li>An <strong>input space</strong> <img src="https://latex.codecogs.com/png.latex?I"></li>
<li>An <strong>output space</strong> <img src="https://latex.codecogs.com/png.latex?O"></li>
</ul>
<p>The functions are:</p>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?v%20%5Ccolon%20X%20%5Ctimes%20I%20%5Cto%20T%20X">, such that <img src="https://latex.codecogs.com/png.latex?v(x,u)%20%5Cin%20T_x%20X">.</li>
<li><img src="https://latex.codecogs.com/png.latex?f%20%5Ccolon%20X%20%5Cto%20O"></li>
</ul>
</div>
<div id="exm-petri-open" class="theorem example">
<p><span class="theorem-title"><strong>Example 2</strong></span> Given a Petri net <img src="https://latex.codecogs.com/png.latex?P">, there is an open system with</p>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?X_P%20=%20%5Cmathbb%7BR%7D%5E%7BP(S)%7D_%7B%3E0%7D"></li>
<li><img src="https://latex.codecogs.com/png.latex?I_P%20=%20%5Cmathbb%7BR%7D%5E%7BP(T)%7D_%7B%3E0%7D"></li>
<li><img src="https://latex.codecogs.com/png.latex?O_P%20=%20%5Cmathbb%7BR%7D%5E%7BP(S)%7D_%7B%3E0%7D"></li>
</ul>
<p>and</p>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?v_P%20%5Ccolon%20X_P%20%5Ctimes%20I_P%20%5Cto%20T%20X_P"> given by mass action with rate parameters <img src="https://latex.codecogs.com/png.latex?u%20%5Cin%20I_P"></li>
<li><img src="https://latex.codecogs.com/png.latex?f_P%20%5Ccolon%20X_P%20%5Cto%20O_P"> given by the identity</li>
</ul>
</div>
<div id="exm-open-closed" class="theorem example">
<p><span class="theorem-title"><strong>Example 3</strong></span> An open dynamical system with <img src="https://latex.codecogs.com/png.latex?I=1">, <img src="https://latex.codecogs.com/png.latex?O=1"> is a closed dynamical system.</p>
</div>
</section>
<section id="part-2-composition-of-dynamical-systems" class="level1">
<h1>Part 2: Composition of dynamical systems</h1>
<p>In this section, we learn about how to compose dynamical systems with a construction from category theory called <em>lenses</em>. If you have learned about lenses before from functional programming, you may have some preconceived notion that lens are a way of accessing nested fields in a data structure. However, here we are using lens in a very different way; it might be useful to just think about “lens” as a new word. The two uses of lenses are formally the same, but have a different feel.</p>
<p>Lenses are morphisms in a certain category, so before we can define lenses we have to define the objects in that category.</p>
<div id="def-arena" class="theorem definition">
<p><span class="theorem-title"><strong>Definition 3</strong></span> An <strong>arena</strong> consists of a space <img src="https://latex.codecogs.com/png.latex?X"> and a <strong>bundle</strong> over it, which is a space <img src="https://latex.codecogs.com/png.latex?E"> and a map <img src="https://latex.codecogs.com/png.latex?p%20%5Ccolon%20E%20%5Cto%20X">.<sup>1</sup></p>
</div>
<p>We think about an arena as a generalized specification of the inputs/outputs of a system. At each output <img src="https://latex.codecogs.com/png.latex?x%20%5Cin%20X">, there are allowed inputs <img src="https://latex.codecogs.com/png.latex?E_x%20:=%20p%5E%7B-1%7D(x)">. We write an arena as <img src="https://latex.codecogs.com/png.latex?%5Cbegin%7Bpmatrix%7DE%20%5C%5C%20X%5Cend%7Bpmatrix%7D">. In a special case, the “output” of a system is its state, and the “input” is the direction that you tell it to go in, i.e.&nbsp;a tangent vector.</p>
<div id="exm-tangent-bundle-arena" class="theorem example">
<p><span class="theorem-title"><strong>Example 4</strong></span> Given any space <img src="https://latex.codecogs.com/png.latex?X">, there is an arena <img src="https://latex.codecogs.com/png.latex?%5Cbegin%7Bpmatrix%7DTX%20%5C%5C%20X%5Cend%7Bpmatrix%7D">, where <img src="https://latex.codecogs.com/png.latex?p%20%5Ccolon%20TX%20%5Cto%20X"> sends <img src="https://latex.codecogs.com/png.latex?v%20%5Cin%20T_x%20X"> to <img src="https://latex.codecogs.com/png.latex?x"> (recall that <img src="https://latex.codecogs.com/png.latex?T%20X%20=%20%5Csum_%7Bx%20%5Cin%20X%7D%20T_x%20X">).</p>
</div>
<div id="exm-simple-arena" class="theorem example">
<p><span class="theorem-title"><strong>Example 5</strong></span> Given any two spaces <img src="https://latex.codecogs.com/png.latex?O"> and <img src="https://latex.codecogs.com/png.latex?I">, there is an arena <img src="https://latex.codecogs.com/png.latex?%5Cbegin%7Bpmatrix%7DO%20%5Ctimes%20I%20%5C%5C%20O%5Cend%7Bpmatrix%7D">, where <img src="https://latex.codecogs.com/png.latex?p%20%5Ccolon%20O%20%5Ctimes%20I%20%5Cto%20O"> is the projection <img src="https://latex.codecogs.com/png.latex?(y,%20u)%20%5Cmapsto%20y">. This is known as a <strong>simple arena</strong>, because the inputs don’t depend on the outputs at all; they are the same everywhere. A lens between two simple arenas is known as a <strong>simple lens</strong>.</p>
</div>
<p>Lenses are then a way of mapping <em>outputs forward</em> and <em>inputs backward</em>.</p>
<div id="def-lens" class="theorem definition">
<p><span class="theorem-title"><strong>Definition 4</strong></span> Suppose that <img src="https://latex.codecogs.com/png.latex?%5Cbegin%7Bpmatrix%7DB%20%5C%5C%20A%5Cend%7Bpmatrix%7D"> and <img src="https://latex.codecogs.com/png.latex?%5Cbegin%7Bpmatrix%7DD%20%5C%5C%20C%5Cend%7Bpmatrix%7D"> are arenas. Then a <strong>lens</strong> between them consists of a function <img src="https://latex.codecogs.com/png.latex?f%20%5Ccolon%20A%20%5Cto%20C">, and then for every <img src="https://latex.codecogs.com/png.latex?x%20%5Cin%20A">, a function <img src="https://latex.codecogs.com/png.latex?f%5E%7B%5Csharp%7D_x%20%5Ccolon%20D_%7Bf(x)%7D%20%5Cto%20B_x">. We visualize this as</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2023/05/algebraic-geometry-2/_svgs/0bf6aa843f00b17747f57cd37f5506cde6b3ff73.svg" class="img-fluid">
</div>
</div>
<div id="exm-open-as-lens" class="theorem example">
<p><span class="theorem-title"><strong>Example 6</strong></span> An open dynamical system is a lens of the form</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2023/05/algebraic-geometry-2/_svgs/1434937a4902f24a0e9b88377aaaec97a726be43.svg" class="img-fluid">
</div>
<p>It takes a bit of unpacking here to see exactly why this is true. The forwards map <img src="https://latex.codecogs.com/png.latex?f%20%5Ccolon%20X%20%5Cto%20O"> is the same, but the backwards map is in a slightly different form. Namely, if we unpack the definition of a lens, then we have for every <img src="https://latex.codecogs.com/png.latex?x%20%5Cin%20X">, <img src="https://latex.codecogs.com/png.latex?v_x%20%5Ccolon%20(O%20%5Ctimes%20I)_%7Bf(x)%7D%20%5Cto%20T_x%20X">. This looks different from our earlier definition of open dynamical system, but we recover that earlier definition when we recall that <img src="https://latex.codecogs.com/png.latex?(O%20%5Ctimes%20I)_%7Bf(x)%7D%20=%20I">, because <img src="https://latex.codecogs.com/png.latex?%5Cbegin%7Bpmatrix%7DO%20%5Ctimes%20I%20%5C%5C%20O%5Cend%7Bpmatrix%7D"> is a trivial bundle. Thus, for every <img src="https://latex.codecogs.com/png.latex?x"> we have a map <img src="https://latex.codecogs.com/png.latex?v_x%20%5Ccolon%20I%20%5Cto%20T_x%20X">. We can then rearrange the parameters to get <img src="https://latex.codecogs.com/png.latex?v%20%5Ccolon%20X%20%5Ctimes%20I%20%5Cto%20T%20X">, with the additional condition that <img src="https://latex.codecogs.com/png.latex?v(x,u)%20%5Cin%20T_x%20X">, which is precisely what we said an open dynamical system was!</p>
</div>
<p>There are two ways of composing lenses: composing in parallel and in series. We start with composition in parallel, because that has a more immediate application in terms of open dynamical systems.</p>
<div id="def-arena-tensor" class="theorem definition">
<p><span class="theorem-title"><strong>Definition 5</strong></span> Given two arenas <img src="https://latex.codecogs.com/png.latex?%5Cbegin%7Bpmatrix%7DB%20%5C%5C%20A%5Cend%7Bpmatrix%7D"> and <img src="https://latex.codecogs.com/png.latex?%5Cbegin%7Bpmatrix%7DB'%20%5C%5C%20A'%5Cend%7Bpmatrix%7D"> (with projections <img src="https://latex.codecogs.com/png.latex?p"> and <img src="https://latex.codecogs.com/png.latex?p'">), there is an arena <img src="https://latex.codecogs.com/png.latex?%5Cbegin%7Bpmatrix%7DB%20%5C%5C%20A%5Cend%7Bpmatrix%7D%20%5Cotimes%20%5Cbegin%7Bpmatrix%7DB'%20%5C%5C%20A'%5Cend%7Bpmatrix%7D"> defined by</p>
<p><img src="https://latex.codecogs.com/png.latex?%20%5Cbegin%7Bpmatrix%7DB%20%5C%5C%20A%5Cend%7Bpmatrix%7D%20%5Cotimes%20%5Cbegin%7Bpmatrix%7DB'%20%5C%5C%20A'%5Cend%7Bpmatrix%7D%20=%20%5Cbegin%7Bpmatrix%7DB%20%5Ctimes%20B'%20%5C%5C%20A%20%5Ctimes%20A'%5Cend%7Bpmatrix%7D%20"></p>
<p>where the map <img src="https://latex.codecogs.com/png.latex?p%20%5Ctimes%20p'%20%5Ccolon%20B%20%5Ctimes%20B'%20%5Cto%20A%20%5Ctimes%20A'"> is defined by <img src="https://latex.codecogs.com/png.latex?(p%20%5Ctimes%20p')(b,b')%20=%20(p(b),%20p(b'))">.</p>
</div>
<div id="def-lens-tensor" class="theorem definition">
<p><span class="theorem-title"><strong>Definition 6</strong></span> Given two lenses</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2023/05/algebraic-geometry-2/_svgs/f140e1757ab9b78286e040bd243a2f50f3d51cd8.svg" class="img-fluid">
</div>
<p>their <strong>parallel composite</strong> is given by the following lens.</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2023/05/algebraic-geometry-2/_svgs/da118d8a95a14ee675fe0d9462803317c5a840f8.svg" class="img-fluid">
</div>
<p>The functions <img src="https://latex.codecogs.com/png.latex?f%20%5Ctimes%20g"> and <img src="https://latex.codecogs.com/png.latex?f%5E%5Csharp%20%5Ctimes%20g%5E%5Csharp"> have types</p>
<p><img src="https://latex.codecogs.com/png.latex?%20f%20%5Ctimes%20g%20%5Ccolon%20A%20%5Ctimes%20A'%20%5Cto%20C%20%5Ctimes%20C'%20"></p>
<p><img src="https://latex.codecogs.com/png.latex?%20(f%5E%5Csharp%20%5Ctimes%20g%5E%5Csharp)_%7Bx,x'%7D%20%5Ccolon%20D_%7Bf(x)%7D%20%5Ctimes%20D'_%7Bg(x')%7D%20%5Cto%20B_x%20%5Ctimes%20B'_%7Bx'%7D%20"></p>
<p>and are defined via</p>
<p><img src="https://latex.codecogs.com/png.latex?%20(f%20%5Ctimes%20g)(x,x')%20=%20(f(x),%20g(x))%20"></p>
<p><img src="https://latex.codecogs.com/png.latex?%20(f%5E%5Csharp%20%5Ctimes%20g%5E%5Csharp)_%7Bx,x'%7D(u,u')%20=%20(f%5E%5Csharp_x(u),%20g%5E%5Csharp_%7Bx'%7D(u'))%20"></p>
</div>
<div id="exm-run-systems-in-parallel" class="theorem example">
<p><span class="theorem-title"><strong>Example 7</strong></span> We can use parallel composites to take two open dynamical systems and “run them in parallel”. That is, suppose that we have open dynamical systems</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2023/05/algebraic-geometry-2/_svgs/c0de41b23c1233c1f68cd621122a11aa4b75eb06.svg" class="img-fluid">
</div>
<p>Then we can make an open dynamical system</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2023/05/algebraic-geometry-2/_svgs/3ce8ad597286752cc69c6fe5ec61cced34fb54b0.svg" class="img-fluid">
</div>
<p>This corresponds to the ODE consisting of two equations:</p>
<p><img src="https://latex.codecogs.com/png.latex?%20%5Cdot%7Bx%7D%20=%20v(x,u)%20"> <img src="https://latex.codecogs.com/png.latex?%20%5Cdot%7Bx%7D'%20=%20v'(x',%20u')%20"></p>
<p>and output <img src="https://latex.codecogs.com/png.latex?y%20=%20f(x)">, <img src="https://latex.codecogs.com/png.latex?y'%20=%20f'(x')">. This may seem like a “trivial” operation, but the first step to making two open dynamical systems interact is to produce this parallel composite; we then use serial composition to make the systems interact.</p>
</div>
<p>Serial composition of lenses, roughly speaking “just composes the backwards and forwards maps”. But let’s spell that out in more detail.</p>
<div id="def-serial-composition" class="theorem definition">
<p><span class="theorem-title"><strong>Definition 7</strong></span> Suppose that we have the following setup of arenas and lenses:</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2023/05/algebraic-geometry-2/_svgs/a6656ef701074c7bc2424cf2897e7fc6d2841e33.svg" class="img-fluid">
</div>
<p>We can compose them to form</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2023/05/algebraic-geometry-2/_svgs/9f53ae7cf9776b1f45f3a3e338561e0051df7121.svg" class="img-fluid">
</div>
<p>On the bottom, the function <img src="https://latex.codecogs.com/png.latex?g%20%5Ccirc%20f%20%5Ccolon%20A%20%5Cto%20E"> is just the composite of <img src="https://latex.codecogs.com/png.latex?f"> and <img src="https://latex.codecogs.com/png.latex?g">. Then on top, we have</p>
<p><img src="https://latex.codecogs.com/png.latex?%20(f%5E%5Csharp%20%5Ccirc%20g%5E%5Csharp)_x%20=%20F_%7Bg(f(x))%7D%20%5Cxrightarrow%7Bg%5E%7B%5Csharp%7D_%7Bf(x)%7D%7D%20D_%7Bf(x)%7D%20%5Cxrightarrow%7Bf%5E%5Csharp_x%7D%20B_x%20"></p>
</div>
<div id="exm-compose-serial-parallel" class="theorem example">
<p><span class="theorem-title"><strong>Example 8</strong></span> Let <img src="https://latex.codecogs.com/png.latex?A">, <img src="https://latex.codecogs.com/png.latex?B">, <img src="https://latex.codecogs.com/png.latex?X">, <img src="https://latex.codecogs.com/png.latex?X'"> be spaces, and suppose that we have two open dynamical systems</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2023/05/algebraic-geometry-2/_svgs/730617c157d6bd9bede3fd48dcf9dd2256e5114d.svg" class="img-fluid">
</div>
<p>We can then make a lens</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2023/05/algebraic-geometry-2/_svgs/2454e3d05f366ef3ec129623ab02d34183275d37.svg" class="img-fluid">
</div>
<p>where <img src="https://latex.codecogs.com/png.latex?g%20%5Ccolon%20A%20%5Ctimes%20B%20%5Cto%201"> sends <img src="https://latex.codecogs.com/png.latex?(a,b)"> to the single element <img src="https://latex.codecogs.com/png.latex?%5Cast%20%5Cin%201">, and <img src="https://latex.codecogs.com/png.latex?w_%7Ba,b%7D%20%5Ccolon%201%20%5Cto%20A%20%5Ctimes%20B%20%5Ctimes%20B%20%5Ctimes%20A"> sends the single element <img src="https://latex.codecogs.com/png.latex?%5Cast%20%5Cin%201"> to <img src="https://latex.codecogs.com/png.latex?(a,b,b,a)">.</p>
<p>When we compose <img src="https://latex.codecogs.com/png.latex?(v,f)"> and <img src="https://latex.codecogs.com/png.latex?(v',%20f')"> in parallel, and then compose in series with <img src="https://latex.codecogs.com/png.latex?(w,g)">, we get</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2023/05/algebraic-geometry-2/_svgs/c85b73806b1969f6c0ec9b3bc3d0be09d81365ed.svg" class="img-fluid">
</div>
<p>This is a closed dynamical system, which can be written as a pair of coupled ODEs in the following way:</p>
<p><img src="https://latex.codecogs.com/png.latex?%20%5Cdot%7Bx%7D%20=%20v(x,%20f'(x'))%20"> <img src="https://latex.codecogs.com/png.latex?%20%5Cdot%7Bx%7D'%20=%20v'(x',%20f(x))%20"></p>
<p>The point is that after composing in parallel, composing with further lenses can couple two systems together.</p>
</div>
</section>
<section id="part-3-symbolic-lenses" class="level1">
<h1>Part 3: Symbolic lenses</h1>
<p>In the <a href="https://blog.algebraicjulia.org/post/2023/03/algebraic-geometry-1/">first blog post</a> in this series, we learned how to make a “symbolic category of spaces” via algebraic theories, and the mantra “algebra is dual to geometry”.</p>
<p>We are now going to use this to build symbolic models of dynamical systems. Essentially, this boils down to “do the constructions of the above section starting from a symbolic category of spaces”, but there’s some elaboration that should take place.</p>
<p>Let’s start by taking the simplest algebraic theory: the theory with one type and no operations. The category of finitely presented algebras of this theory is just <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BFinSet%7D">. So then the question become, what are lenses in <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BFinSet%7D%5E%5Cmathrm%7Bop%7D">?</p>
<p>For the sake of brevity, we will only cover simple lenses. This will suffice to do dynamical systems with basic state spaces, because <img src="https://latex.codecogs.com/png.latex?T%20%5Cmathbb%7BR%7D%5En%20%5Ccong%20%5Cmathbb%7BR%7D%5En%20%5Ctimes%20%5Cmathbb%7BR%7D%5En">.</p>
<p>A simple arena is something of the form <img src="https://latex.codecogs.com/png.latex?%5Cbegin%7Bpmatrix%7DX%20+%20Y%20%5C%5C%20X%5Cend%7Bpmatrix%7D">, with the injection map <img src="https://latex.codecogs.com/png.latex?X%20%5Cto%20X+Y">. This is because the product and projection of lenses become coproduct and injection when we dualize.</p>
<p>Then, when we dualize our recipe for a simple lens, we get that a simple lens in <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BFinSet%7D%5E%5Cmathrm%7Bop%7D"> from <img src="https://latex.codecogs.com/png.latex?%5Cbegin%7Bpmatrix%7DX%20+%20Y%20%5C%5C%20X%5Cend%7Bpmatrix%7D"> to <img src="https://latex.codecogs.com/png.latex?%5Cbegin%7Bpmatrix%7DA%20+%20B%20%5C%5C%20A%5Cend%7Bpmatrix%7D"> consists of a function <img src="https://latex.codecogs.com/png.latex?f%20%5Ccolon%20A%20%5Cto%20X"> along with a function <img src="https://latex.codecogs.com/png.latex?f%5E%5Csharp%20%5Ccolon%20Y%20%5Cto%20B%20+%20X">.</p>
<p>Such a lens is also known as a <strong>wiring diagram with one box</strong>.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2023/05/algebraic-geometry-2/wiring_diagram.svg" class="img-fluid figure-img"></p>
<figcaption>A wiring diagram</figcaption>
</figure>
</div>
<p>In this wiring diagram:</p>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?X"> is the set of output ports for the inner box</li>
<li><img src="https://latex.codecogs.com/png.latex?Y"> is the set of input ports for the inner box</li>
<li><img src="https://latex.codecogs.com/png.latex?A"> is the set of output ports for the outer box</li>
<li><img src="https://latex.codecogs.com/png.latex?B"> is the set of input ports for the outer box</li>
</ul>
<p>We can see that each element of <img src="https://latex.codecogs.com/png.latex?A"> (there is only one in this case) is assigned an element in <img src="https://latex.codecogs.com/png.latex?X">, and each element of <img src="https://latex.codecogs.com/png.latex?Y"> is assigned an element in <img src="https://latex.codecogs.com/png.latex?X%20+%20B">.</p>
<p>A model of this algebraic theory is just a set. Suppose that <img src="https://latex.codecogs.com/png.latex?Q"> is such a model, i.e.&nbsp;a set. Then from a lens in <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BFinSet%7D%5E%7B%5Cmathrm%7Bop%7D%7D">,</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2023/05/algebraic-geometry-2/_svgs/e4e8ae4215835185c920def79c54944a00e1cae5.svg" class="img-fluid">
</div>
<p>where <img src="https://latex.codecogs.com/png.latex?f%20%5Ccolon%20A%20%5Cto%20X">, <img src="https://latex.codecogs.com/png.latex?f%5E%5Csharp%20%5Ccolon%20Y%20%5Cto%20B%20+%20X">, we get a lens in <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSet%7D"></p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2023/05/algebraic-geometry-2/_svgs/f11089576040020f018e9f247f030331187c0780.svg" class="img-fluid">
</div>
<p>where <img src="https://latex.codecogs.com/png.latex?Q%5Ef%20%5Ccolon%20Q%5EX%20%5Cto%20Q%5EA">, and <img src="https://latex.codecogs.com/png.latex?Q%5E%7Bf%5E%5Csharp%7D%20%5Ccolon%20Q%5EX%20%5Ctimes%20Q%5EB%20%5Cto%20Q%5EY"> are given by precomposition.</p>
<p>Now suppose that we work in a richer algebraic theory. For example, suppose that we work with the theory of <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebras. For simplicity, let’s just consider free <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebras. The category of finitely generated free <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebras has as objects finite sets, and a morphism <img src="https://latex.codecogs.com/png.latex?f"> from <img src="https://latex.codecogs.com/png.latex?X"> to <img src="https://latex.codecogs.com/png.latex?Y"> consists of a polynomial <img src="https://latex.codecogs.com/png.latex?f_x%20%5Cin%20%5Cmathbb%7BR%7D%5BY%5D"> for each <img src="https://latex.codecogs.com/png.latex?x%20%5Cin%20X">.</p>
<p>A lens <img src="https://latex.codecogs.com/png.latex?(f,f%5E%5Csharp)"> in the dual category to this from <img src="https://latex.codecogs.com/png.latex?%5Cbegin%7Bpmatrix%7DX+Y%20%5C%5C%20X%5Cend%7Bpmatrix%7D"> to <img src="https://latex.codecogs.com/png.latex?%5Cbegin%7Bpmatrix%7DA+B%20%5C%5C%20A%5Cend%7Bpmatrix%7D"> consists of a polynomial <img src="https://latex.codecogs.com/png.latex?f_a%20%5Cin%20%5Cmathbb%7BR%7D%5BX%5D"> for every <img src="https://latex.codecogs.com/png.latex?a%20%5Cin%20A">, and a polynomial <img src="https://latex.codecogs.com/png.latex?f_y%5E%5Csharp%20%5Cin%20%5Cmathbb%7BR%7D%5BX+B%5D"> for every <img src="https://latex.codecogs.com/png.latex?y%20%5Cin%20Y">. You can think of <img src="https://latex.codecogs.com/png.latex?f_a"> as a description of “how to compute” the variable <img src="https://latex.codecogs.com/png.latex?a">, given values for all the variables in <img src="https://latex.codecogs.com/png.latex?X">, i.e.&nbsp;it’s a dual map <img src="https://latex.codecogs.com/png.latex?X%20%5Cto%20A">. Likewise <img src="https://latex.codecogs.com/png.latex?f_y%5E%5Csharp"> is a description of “how to compute” the variable <img src="https://latex.codecogs.com/png.latex?y">, given values for the variables in <img src="https://latex.codecogs.com/png.latex?X"> and the variables in <img src="https://latex.codecogs.com/png.latex?B">, i.e.&nbsp;it’s a dual map <img src="https://latex.codecogs.com/png.latex?X%20%5Ctimes%20B%20%5Cto%20Y">.</p>
<div id="exm-petri-as-symbolic" class="theorem example">
<p><span class="theorem-title"><strong>Example 9</strong></span> The lens for mass-action semantics corresponding to a Petri net can be written in such a form, because the ODEs corresponding to mass-action semantics have polynomial right hand sides.</p>
</div>
<p>Just like with wiring diagrams, if we take any model of the theory of <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebras, for instance <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">, then we can turn any lens in the opposite category of free <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebras into an actual geometric lens, by interpreting a map <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D%5Bx_1,%5Cldots,x_n%5D%20%5Cto%20%5Cmathbb%7BR%7D%5By_1,%5Cldots,y_m%5D"> as a map <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D%5Em%20%5Cto%20%5Cmathbb%7BR%7D%5En"> to get:</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2023/05/algebraic-geometry-2/_svgs/56a3acd8cb2c44c0f46f8058d447859189d731ec.svg" class="img-fluid">
</div>
<p>It is no great stretch from here to consider similar constructions where we allow more operations than just multiplication, addition, and scalar multiplication. For instance, we could also allow <img src="https://latex.codecogs.com/png.latex?%5Csin,%20%5Ccos,%20%5Cexp">. The most extreme extension of this is to allow any smooth function <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D%5En%20%5Cto%20%5Cmathbb%7BR%7D"> as an operation; models of such a theory are known as <img src="https://latex.codecogs.com/png.latex?C%5E%5Cinfty">-rings, and are very nice from a mathematical standpoint (though completely impractical to represent on a computer).</p>
<p>The complications start to come when we consider</p>
<ul>
<li>Non-free finitely presented algebras, such as <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D%5Bx,y,z%5D/(x%5E2+y%5E2+z%5E2-1)">, which allow us to look at spaces that are not just Euclidian space</li>
<li>Dependent lenses, where the map in the arena is not just a projection. This allows us to look at non-trivial vector bundles.</li>
</ul>
<p>This delves farther into algebraic geometry than we wish to go in this blog post, but the interested reader is encouraged to look into the subject themselves.</p>
</section>
<section id="take-aways" class="level1">
<h1>Take-aways</h1>
<p>One thing I want to emphasize in this post is that there were very few “choices” to make. It was some work to make this all fit together and work out the details, but starting from the premise of “I want to do symbolic dynamical systems” and knowing the two slogans</p>
<ul>
<li>algebra is dual to geometry</li>
<li>open dynamical systems are lenses</li>
</ul>
<p>was sufficient to come up with this. This is one of the things I like about category theory; sometimes it really can feel like discovery not invention, because once you know what you are looking for, there’s often a canonical way of doing things.</p>
<p>I’m excited to be working on implementing this, and I hope to talk about that in a future post where I will talk about Gatlab, a rewrite of the core of Catlab to be more “morphism-first” with respect to computer algebra.</p>



</section>


<div id="quarto-appendix" class="default"><section class="quarto-appendix-contents" id="quarto-bibliography"><h2 class="anchored quarto-appendix-heading">References</h2><div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="0">
<div id="ref-myers_categorical_2022" class="csl-entry">
Myers, David Jaz. 2022. <em>Categorical Systems Theory</em>. <a href="https://github.com/DavidJaz/DynamicalSystemsBook">https://github.com/DavidJaz/DynamicalSystemsBook</a>.
</div>
</div></section><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>

<ol>
<li id="fn1"><p>There is also an additional technical requirement on arenas which is that the bundle is <strong>locally trivial</strong>. This requirement will not be relevant for the level of detail we work in here, so we will not go into precisely what this means.↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>algebra</category>
  <category>logic</category>
  <guid>https://blog.algebraicjulia.org/post/2023/05/algebraic-geometry-2/</guid>
  <pubDate>Mon, 08 May 2023 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Algebraic geometry for the working programmer</title>
  <dc:creator>Owen Lynch</dc:creator>
  <link>https://blog.algebraicjulia.org/post/2023/03/algebraic-geometry-1/</link>
  <description><![CDATA[ 





<div class="hidden">
<p>$$ <!-- Number systems --> </p>
<!-- Categories -->
<!-- Graphs -->
<!-- Double categories -->
<!-- Acsets -->
<!-- Wiring diagrams -->
<!-- Dynamical systems -->
<p>$$</p>
</div>
<section id="purpose" class="level1">
<h1>Purpose</h1>
<p>A traditional approach to algebraic geometry requires a course in commutative algebra, a great deal of patience for abstract nonsense, and then an innate love for elliptic curves. However, once one has scaled these imposing walls of what seems like pure math for its own sake, one finds a subject which has a great deal of algorithmic and philosophical merits.</p>
<p>Algebraic geometry is both the seed of the revolution in category theory developed by Grothendieck, and also is at the core of the algorithms in computer algebra that power systems like Mathematica, SAGE, or Macaulay2.</p>
<p>In this post, I aim to “pull back the curtain” on some of the things behind this wall of commutative algebra, and show why it is worth studying even if you don’t really care about elliptic curves or toric varieties or any of the other strange creatures that typically pull people into algebraic geometry from pure math. I will instead motivate the development of algebraic geometry from the perspective of someone trying to develop a symbolic algebra system.</p>
<p>There is also a point to all of this apart from pedagogy; this is a warmup for some new ideas for which a background in algebraic geometry is needed.</p>
</section>
<section id="expressions-and-evaluation" class="level1">
<h1>Expressions and evaluation</h1>
<p>Computer algebra as generally construed is centered around the manipulation of syntactic expressions that are intended to represent mathematical formulas.</p>
<p>We might represent such an expression with a <em>tree</em>, where each node is either a function symbol, a variable, or a constant. For instance, the expression <img src="https://latex.codecogs.com/png.latex?a%5E2%20+%204b"> would be represented as:</p>
<div id="fig-expr-tree" class="quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-expr-tree-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2023/03/algebraic-geometry-1/_svgs/dcc0421f72b7850da39e5d805f7f1ba879eb5924.svg" class="img-fluid figure-img">
</div>
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-expr-tree-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1: An expression represented as a tree
</figcaption>
</figure>
</div>
<p>In a lisp, we would write down this tree as</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource scheme number-lines code-with-copy"><code class="sourceCode scheme"><span id="cb1-1">(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> (<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> a a) (<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span> b))</span></code></pre></div>
<p>In this notation, each matched pair of paretheses denotes a subtree, where the value at the root at the subtree is the first thing in the parentheses, called the <strong>head</strong>, and the rest of the parentheses denotes the subtrees attached to that root, called the <strong>arguments</strong>. We also allow numbers and symbols as arguments, which are the leaf nodes of the tree. We can express this in Julia with the following data structure.</p>
<div id="2" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb2-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> SymExpr</span>
<span id="cb2-2">  head<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Any</span></span>
<span id="cb2-3">  args<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Vector{Union{SymExpr, Symbol}}</span></span>
<span id="cb2-4">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SymExpr</span>(head, args<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>SymExpr[])</span>
<span id="cb2-5">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">new</span>(head, args)</span>
<span id="cb2-6">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb2-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb2-8"></span>
<span id="cb2-9">ex <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SymExpr</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:+</span>, [<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SymExpr</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:*</span>, [<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>a, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>a]), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SymExpr</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:*</span>, [<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SymExpr</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>), <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>b])])</span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre><code>SymExpr(:+, Union{Symbol, SymExpr}[SymExpr(:*, Union{Symbol, SymExpr}[:a, :a]), SymExpr(:*, Union{Symbol, SymExpr}[SymExpr(4, Union{Symbol, SymExpr}[]), :b])])</code></pre>
</div>
</div>
<p>Disclaimer: the code in this post will be optimized for brevity and clarity, not necessarily maintainability or usability. If you want to use the techniques in this post, there is a substantial amount of work to get something production-quality, including but not limited to parsing a nicer syntax and error-checking all computations.</p>
<p>Now, there are a great number of meaningless expressions that one can write down using the previous data structure. Generally, the first thing one would want to know about an expression is “does this make sense”? Of course, sense-making is relative. So the real question is “does this expression make sense relative to a certain signature”, and in order to answer that, we must define what a signature is. The rest of this section is based on a field of math called “universal algebra”, a good reference for which is <span class="citation" data-cites="goguen_theorem_2021">Goguen (2021)</span>.</p>
<div class="rmenv" title="Definition">
<p>A (single-sorted) <strong>algebraic signature</strong> consists of a set <img src="https://latex.codecogs.com/png.latex?F">, along with a function <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7Barity%7D%20%5Ccolon%20F%20%5Cto%20%5Cmathbb%7BN%7D">. We call the elements of <img src="https://latex.codecogs.com/png.latex?F"> <strong>function symbols</strong>.</p>
</div>
<div class="rmenv" title="Example">
<p>The signature of <strong>rings</strong> consists of <img src="https://latex.codecogs.com/png.latex?F%20=%20%5C%7B+,%5Ccdot,0,1%5C%7D">, with <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7Barity%7D(+)%20=%202">, <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7Barity%7D(%5Ccdot)%20=%202">, <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7Barity%7D(0)%20=%200">, <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7Barity%7D(1)%20=%200">.</p>
</div>
<p>We say that an expression <img src="https://latex.codecogs.com/png.latex?e"> is well-formed with respect to the signature <img src="https://latex.codecogs.com/png.latex?(F,%20%5Cmathrm%7Barity%7D)"> if the head of <img src="https://latex.codecogs.com/png.latex?e"> is <img src="https://latex.codecogs.com/png.latex?f%20%5Cin%20F">, <img src="https://latex.codecogs.com/png.latex?e"> has <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7Barity%7D(f)"> arguments, and all of those arguments are also well-formed, or if <img src="https://latex.codecogs.com/png.latex?e"> is just a symbol, representing a variable. The tree in Figure&nbsp;1 is <em>not</em> well-formed with respect to <img src="https://latex.codecogs.com/png.latex?F"> because there are numbers in it, however the left subtree is.</p>
<p>In order to deal with numbers, we add a nullary function symbol for every number.</p>
<div class="rmenv" title="Example">
<p>The signature of <strong><img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebras</strong> consists of <img src="https://latex.codecogs.com/png.latex?F%20=%20%5C%7B+,%5Ccdot%5C%7D%20%5Csqcup%20%5Cmathbb%7BR%7D">, and <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7Barity%7D(x)%20=%200"> for <img src="https://latex.codecogs.com/png.latex?x%20%5Cin%20%5Cmathbb%7BR%7D">, <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7Barity%7D(f)%20=%202"> for <img src="https://latex.codecogs.com/png.latex?f%20%5Cin%20%5C%7B+,%5Ccdot%5C%7D">.</p>
</div>
<p>With this signature, Figure&nbsp;1 is well-formed.</p>
<p>One of the most natural things that one might want to do with an expression is <em>evaluate it</em>. However, we have allowed variables in our expressions; what does it mean to evaluate a variable? The answer is that we must talk about evaluating an expression in a <strong>context</strong>, which is an assignment of variables to values. But what is a value? One definition for a value would simply be a real number. But we can be more general than that.</p>
<div class="rmenv" title="Definition">
<p>If <img src="https://latex.codecogs.com/png.latex?F"> is a signature, a <strong>model</strong> of <img src="https://latex.codecogs.com/png.latex?F"> consists of a set <img src="https://latex.codecogs.com/png.latex?M"> along with a function <img src="https://latex.codecogs.com/png.latex?%7Cf%7C_%7BM%7D%20%5Ccolon%20M%5E%7B%5Cmathrm%7Barity%7D(f)%7D%20%5Cto%20M"> for every <img src="https://latex.codecogs.com/png.latex?f%20%5Cin%20F">.</p>
</div>
<p>We can evaluate an expression in any model, if we have an assignment of the variables in that expression to values in that model.</p>
<div class="rmenv" title="Example">
<p>For a fixed <img src="https://latex.codecogs.com/png.latex?n">, the set of <img src="https://latex.codecogs.com/png.latex?n%20%5Ctimes%20n"> real matrices is a model of the signature of <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebras, where <img src="https://latex.codecogs.com/png.latex?+"> is interpreted as matrix addition, <img src="https://latex.codecogs.com/png.latex?%5Ccdot"> is interpreted as matrix multiplication, and <img src="https://latex.codecogs.com/png.latex?x%20%5Cin%20%5Cmathbb%7BR%7D"> is interpreted as the matrix <img src="https://latex.codecogs.com/png.latex?x%20I"> where <img src="https://latex.codecogs.com/png.latex?I"> is the identity matrix.</p>
</div>
<p>Evaluation is a recursive function, which is most naturally expressed with code.</p>
<div id="4" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb4-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">abstract type</span> Model{T} <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb4-2"></span>
<span id="cb4-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Whenever we have a Model, we assume that we have a function of type</span></span>
<span id="cb4-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># interpret(m::Model{T}, f, args::Vector{T})::T</span></span>
<span id="cb4-5"></span>
<span id="cb4-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># evaluating a symbol just looks it up in the context</span></span>
<span id="cb4-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">evaluate</span>(v<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Symbol</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Model{T}</span>, ctx<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Dict{Symbol, T}</span>) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> {T}</span>
<span id="cb4-8">  ctx[v]</span>
<span id="cb4-9"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb4-10"></span>
<span id="cb4-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># evaluating an expression first evaluates the arguments, and then applies the</span></span>
<span id="cb4-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># interpretation of the head to those arguments</span></span>
<span id="cb4-13"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">evaluate</span>(<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">SymExpr</span>, m<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Model{T}</span>, ctx<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Dict{Symbol, T}</span>) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> {T}</span>
<span id="cb4-14">  args <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map</span>(arg <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">evaluate</span>(arg, m, ctx), <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span>.args)</span>
<span id="cb4-15">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">interpret</span>(m, <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">e</span>.head, args)</span>
<span id="cb4-16"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb4-17"></span>
<span id="cb4-18"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> MatrixModel <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> Model{Matrix{Float64}}</span></span>
<span id="cb4-19">  n<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span></span>
<span id="cb4-20"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb4-21"></span>
<span id="cb4-22"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Here is the implementation of interpret for MatrixModel</span></span>
<span id="cb4-23"></span>
<span id="cb4-24"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">interpret</span>(m<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">MatrixModel</span>, f, args)</span>
<span id="cb4-25">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">typeof</span>(f) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> Number</span></span>
<span id="cb4-26">    f <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">identity</span>(m.n)</span>
<span id="cb4-27">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elseif</span> f <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:+</span></span>
<span id="cb4-28">    args[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> args[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]</span>
<span id="cb4-29">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elseif</span> f <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:*</span></span>
<span id="cb4-30">    args[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> args[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]</span>
<span id="cb4-31">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb4-32"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb4-33"></span>
<span id="cb4-34"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">evaluate</span>(ex, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">MatrixModel</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Dict</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>. <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>; <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>.; <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>. <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]))</span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre><code>2×2 Matrix{Float64}:
  4.0  8.0
 11.0  1.0</code></pre>
</div>
</div>
<p>We are now going to embark onto some category theory. But if you feel lost, know that the material that we are going to cover in the next sections is all just elaborations of the above 20 lines of code. If you understand what that code is doing, then just stare down the category theory until you can see that it’s doing the exact same thing.</p>
<p>We can get evaluation of expressions “for free” once we set up some categorical technology. We start by defining a category of models for a signature.</p>
<div class="rmenv" title="Definition">
<p>Given a signature <img src="https://latex.codecogs.com/png.latex?F">, there is a category <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BMdl%7D_F"> whose objects are models of <img src="https://latex.codecogs.com/png.latex?F"> and whose morphisms are functions <img src="https://latex.codecogs.com/png.latex?%5Cphi%20%5Ccolon%20M%20%5Cto%20N"> such that for each <img src="https://latex.codecogs.com/png.latex?f%20%5Cin%20F"> with <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7Barity%7D(f)%20=%20n"> and each <img src="https://latex.codecogs.com/png.latex?(x_%7B1%7D,%5Cldots,x_%7Bn%7D)%20%5Cin%20M%5En">,</p>
<p><img src="https://latex.codecogs.com/png.latex?%5Cphi(%7Cf%7C_%7BM%7D(x_%7B1%7D,%5Cldots,x_%7Bn%7D))%20=%20%7Cf%7C_%7BN%7D(%5Cphi(x_%7B1%7D),%20%5Cldots,%20%5Cphi(x_%7Bn%7D))"></p>
</div>
<p>There is a functor <img src="https://latex.codecogs.com/png.latex?U%20%5Ccolon%20%5Cmathsf%7BMdl%7D_F%20%5Cto%20%5Cmathsf%7BSet%7D"> that sends a model to its underlying set. This functor has a left adjoint <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7BExpr%7D_F%20%5Ccolon%20%5Cmathsf%7BSet%7D%5Cto%20%5Cmathsf%7BMdl%7D_F"> that sends a set <img src="https://latex.codecogs.com/png.latex?X"> to the model <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7BExpr%7D_F(X)"> of <img src="https://latex.codecogs.com/png.latex?F">, where an element of <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7BExpr%7D_F(X)"> is a well-formed expression with respect to <img src="https://latex.codecogs.com/png.latex?F"> with variables only from the set <img src="https://latex.codecogs.com/png.latex?X">.</p>
<p>The adjointness condition is that for any model <img src="https://latex.codecogs.com/png.latex?M">, maps <img src="https://latex.codecogs.com/png.latex?X%20%5Cto%20U(M)"> in <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSet%7D"> correspond bijectively to morphisms <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7BExpr%7D_F(X)%20%5Cto%20M"> in <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BMdl%7D_F">. A map <img src="https://latex.codecogs.com/png.latex?c%20%5Ccolon%20X%20%5Cto%20U(M)"> is what we called a context before; it assigns elements of <img src="https://latex.codecogs.com/png.latex?X"> to values in <img src="https://latex.codecogs.com/png.latex?M">. Then the map <img src="https://latex.codecogs.com/png.latex?c%5E%7B%5Cast%7D%20%5Ccolon%20%5Cmathrm%7BExpr%7D_F(X)%20%5Cto%20M"> simply sends an expression with free variables in <img src="https://latex.codecogs.com/png.latex?X"> to its evaluation with context <img src="https://latex.codecogs.com/png.latex?c">.</p>
<p>Thus, evaluation is given by the adjoint transpose!</p>
<p>Now, whenever you have an adjunction there is a monad and comonad associated with it. In this case, we care about the monad, which is given by <img src="https://latex.codecogs.com/png.latex?T_F%20=%20U%20%5Cmathrm%7BExpr%7D_F">. This monad takes a set <img src="https://latex.codecogs.com/png.latex?X"> and returns the set of well-formed expressions <img src="https://latex.codecogs.com/png.latex?T_F%20X">.</p>
<div class="rmenv" title="Definition">
<p>If <img src="https://latex.codecogs.com/png.latex?(T,%5Ceta,%5Cmu)"> is a monad on a category <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">, then a <strong>monad algebra</strong><sup>1</sup> of <img src="https://latex.codecogs.com/png.latex?T"> consists of an element <img src="https://latex.codecogs.com/png.latex?c%20%5Cin%20%5Cmathsf%7BC%7D"> and a morphism <img src="https://latex.codecogs.com/png.latex?%5Calpha%20%5Ccolon%20T%20c%20%5Cto%20c">, such that the following diagrams commute</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2023/03/algebraic-geometry-1/_svgs/c405c07e8f8a68953dc74c9b65fc7f91471a1b9a.svg" class="img-fluid">
</div>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2023/03/algebraic-geometry-1/_svgs/26e7b7469bf1e5de67df7581ad69e421a74fcf88.svg" class="img-fluid">
</div>
<p>The algebras of <img src="https://latex.codecogs.com/png.latex?T"> form a category <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BAlg%7D_T">, where a morphism from <img src="https://latex.codecogs.com/png.latex?%5Calpha%20%5Ccolon%20T%20c%20%5Cto%20c"> to <img src="https://latex.codecogs.com/png.latex?%5Cbeta%20%5Ccolon%20T%20d%20%5Cto%20d"> is a map <img src="https://latex.codecogs.com/png.latex?f%20%5Ccolon%20c%20%5Cto%20d"> such that the following commutes.</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2023/03/algebraic-geometry-1/_svgs/a1e3bfbc8c6774b3b3049b332998de1b0e24dc47.svg" class="img-fluid">
</div>
</div>
<p>Whenever you have a monad <img src="https://latex.codecogs.com/png.latex?T%20=%20UF"> coming from an adjunction <img src="https://latex.codecogs.com/png.latex?F%20%5Ccolon%20%5Cmathsf%7BC%7D%5Cleftrightarrows%20%5Cmathsf%7BD%7D%5Ccolon%20U">, there is a functor from <img src="https://latex.codecogs.com/png.latex?D"> to <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BAlg%7D_T"> which sends <img src="https://latex.codecogs.com/png.latex?d%20%5Cin%20%5Cmathsf%7BD%7D"> to the algebra <img src="https://latex.codecogs.com/png.latex?U%20%5Cmu%20%5Ccolon%20UFUd%20%5Cto%20Ud">, where <img src="https://latex.codecogs.com/png.latex?%5Cmu"> is the map given by applying the adjoint transpose to the identity <img src="https://latex.codecogs.com/png.latex?U%20d%20%5Cto%20U%20d">.</p>
<p>In the case of our monad <img src="https://latex.codecogs.com/png.latex?T_F%20=%20U%20%5Cmathrm%7BExpr%7D_F">, this says that for any model <img src="https://latex.codecogs.com/png.latex?M"> there is a function <img src="https://latex.codecogs.com/png.latex?U%20%5Cmathrm%7BExpr%7D_F%20U%20M%20%5Cto%20U%20M">. That is, we can take an expression where the “variables” are elements of <img src="https://latex.codecogs.com/png.latex?M">, and evaluate that expression directly.</p>
<p>This gives another way of evaluating an expression with variables. We can take an expression <img src="https://latex.codecogs.com/png.latex?e%20%5Cin%20%5Cmathrm%7BExpr%7D_F(X)">, then use functorality of <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7BExpr%7D_F"> to map <img src="https://latex.codecogs.com/png.latex?c%20%5Ccolon%20X%20%5Cto%20M"> across it and get an expression <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7BExpr%7D_F(c)(e)%20%5Cin%20%5Cmathrm%7BExpr%7D_F(M)">, and then evaluate this to get an element of <img src="https://latex.codecogs.com/png.latex?M">.</p>
<p>If we have an arbitrary <img src="https://latex.codecogs.com/png.latex?T_F">-algebra, then we can use a similar trick to evaluate expressions in a context as well. This implies that <img src="https://latex.codecogs.com/png.latex?T_F">-algebras are like models of <img src="https://latex.codecogs.com/png.latex?F">, and in fact this is exactly right! The functor from <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BMdl%7D_F"> to <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BAlg%7D_%7BT_%7BF%7D%7D"> is an equivalence. <img src="https://latex.codecogs.com/png.latex?M"> being a model of <img src="https://latex.codecogs.com/png.latex?F"> is equivalent to being able to evaluate well-formed expressions with respect to <img src="https://latex.codecogs.com/png.latex?F"> in <img src="https://latex.codecogs.com/png.latex?M">. This is because the monad algebra laws ensure that the algebra is determined solely by its action on the expressions which are non-recursive, i.e.&nbsp;which consist of a function symbol applied to values.</p>
<p>It turns out that there are general conditions under which this is true; that for an adjunction <img src="https://latex.codecogs.com/png.latex?F%20%5Ccolon%20%5Cmathsf%7BC%7D%5Crightleftarrows%20%5Cmathsf%7BD%7D%5Ccolon%20U">, <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BD%7D"> is equivalent to the category of <img src="https://latex.codecogs.com/png.latex?UF"> algebras; this is known as a <a href="https://ncatlab.org/nlab/show/monadicity+theorem">monadicity theorem</a>.</p>
<p>We’re now going to move on, and return to the computer algebra story. But the main takeaway that you should get from this section is that “models of a theory” and “algebras of a monad” are intimately connected; “models of a theory” tell you how to evaluate the function symbols, and “algebras of a monad” tell you how to evaluate arbitrary expressions, but the monad laws say that this evaluation is “generated” by just looking at the function symbols.</p>
</section>
<section id="symbolic-functions" class="level1">
<h1>Symbolic functions</h1>
<p>Now that we can evaluate expressions, the next thing one might want to do is construct functions using these expressions.</p>
<p>Suppose that one has an expression <img src="https://latex.codecogs.com/png.latex?e"> in signature <img src="https://latex.codecogs.com/png.latex?F"> with free variables contained in the set <img src="https://latex.codecogs.com/png.latex?X">, and that <img src="https://latex.codecogs.com/png.latex?M"> is a model of <img src="https://latex.codecogs.com/png.latex?F">. Then given a context <img src="https://latex.codecogs.com/png.latex?c%20%5Ccolon%20X%20%5Cto%20M">, or in other words, an element of <img src="https://latex.codecogs.com/png.latex?M%5EX">, we can evaluate <img src="https://latex.codecogs.com/png.latex?e"> with context <img src="https://latex.codecogs.com/png.latex?c"> to get an element of <img src="https://latex.codecogs.com/png.latex?M">.</p>
<p>Thus, there is a function from <img src="https://latex.codecogs.com/png.latex?T_F(X)"> to <img src="https://latex.codecogs.com/png.latex?M%5EX%20%5Cto%20M"> for any model <img src="https://latex.codecogs.com/png.latex?M">. We can therefore think of an expression in variables <img src="https://latex.codecogs.com/png.latex?x_1,%5Cldots,x_n">as a “symbolic <img src="https://latex.codecogs.com/png.latex?n">-ary” operation.</p>
<p>But what if we want to consider functions <img src="https://latex.codecogs.com/png.latex?M%5EX%20%5Cto%20M%5EY">? This is the same as <img src="https://latex.codecogs.com/png.latex?Y"> many maps <img src="https://latex.codecogs.com/png.latex?M%5Ex%20%5Cto%20M">. Thus, we need an expression in <img src="https://latex.codecogs.com/png.latex?T_F(X)"> for every element of <img src="https://latex.codecogs.com/png.latex?Y">, i.e.&nbsp;a function <img src="https://latex.codecogs.com/png.latex?Y%20%5Cto%20T_F(X)">. It’s counterintuitive that the morphism is going in the opposite direction, but it comes directly from how we might write down such a function. I.e., if <img src="https://latex.codecogs.com/png.latex?y%20=%20f(x)">, then</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Balign*%7D%0A%20%20y_%7B1%7D%20&amp;=%20f_%7B1%7D(x_%7B1%7D,%5Cldots,x_%7Bn%7D)%20%5C%5C%0A%20%20%5Cvdots%20%5C%5C%0A%20%20y_%7Bm%7D%20&amp;=%20f_%7Bm%7D(x_%7B1%7D,%5Cldots,x_%7Bm%7D)%0A%5Cend%7Balign*%7D%0A"></p>
<p>Thus, the <em>dual</em> of the Kleisli category of <img src="https://latex.codecogs.com/png.latex?T_F"> is the category of multivariate symbolic functions for a signature <img src="https://latex.codecogs.com/png.latex?F">. Let’s unpack that. The Kleisli category of <img src="https://latex.codecogs.com/png.latex?T_F"> has as objects sets, and a morphism from <img src="https://latex.codecogs.com/png.latex?Y"> to <img src="https://latex.codecogs.com/png.latex?X"> is a function <img src="https://latex.codecogs.com/png.latex?Y%20%5Cto%20T_F(X)">. So the dual has as objects sets, and a morphism from <img src="https://latex.codecogs.com/png.latex?X"> to <img src="https://latex.codecogs.com/png.latex?Y"> is a function <img src="https://latex.codecogs.com/png.latex?Y%20%5Cto%20T_F(X)">. By what we showed earlier, for any model <img src="https://latex.codecogs.com/png.latex?M"> of <img src="https://latex.codecogs.com/png.latex?F">, there is a functor from <img src="https://latex.codecogs.com/png.latex?%5Coperatorname%7BKl%7D_%7BT_%7BF%7D%7D(%5Cmathsf%7BSet%7D)%5E%7B%5Cmathrm%7Bop%7D%7D"> to <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSet%7D">, which sends <img src="https://latex.codecogs.com/png.latex?f%20%5Ccolon%20Y%20%5Cto%20T_F(X)"> to the map <img src="https://latex.codecogs.com/png.latex?M%5EX%20%5Cto%20M%5EY"> given by evaluating each expression for each <img src="https://latex.codecogs.com/png.latex?y%20%5Cin%20Y"> with context <img src="https://latex.codecogs.com/png.latex?c%20%5Cin%20M%5EX">.</p>
<p>Composition in this Kleisli category corresponds to <em>substitution</em>. I.e., if</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Balign*%7D%0A%20%20y_%7B1%7D%20&amp;=%20f_%7B1%7D(x_%7B1%7D,%5Cldots,x_%7Bn%7D)%20%5C%5C%0A%20%20%5Cvdots%20%5C%5C%0A%20%20y_%7Bm%7D%20&amp;=%20f_%7Bm%7D(x_%7B1%7D,%5Cldots,x_%7Bm%7D)%0A%5Cend%7Balign*%7D%0A"></p>
<p>and</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Balign*%7D%0A%20%20z_%7B1%7D%20&amp;=%20g_%7B1%7D(y_%7B1%7D,%5Cldots,y_%7Bm%7D)%20%5C%5C%0A%20%20%5Cvdots%20%5C%5C%0A%20%20z_%7Bk%7D%20&amp;=%20g_%7Bk%7D(y_%7B1%7D,%5Cldots,y_%7Bm%7D)%0A%5Cend%7Balign*%7D%0A"></p>
<p>then the composite is defined by</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Balign*%7D%0A%20%20z_%7B1%7D%20&amp;=%20g_%7B1%7D(f_%7B1%7D(x_%7B1%7D,%5Cldots,x_%7Bn%7D),%5Cldots,f_%7Bm%7D(x_%7B1%7D,%5Cldots,x_%7Bn%7D))%20%5C%5C%0A%20%20%5Cvdots%20%5C%5C%0A%20%20z_%7Bk%7D%20&amp;=%20g_%7Bk%7D(f_%7B1%7D(x_%7B1%7D,%5Cldots,x_%7Bn%7D),%5Cldots,f_%7Bm%7D(x_%7B1%7D,%5Cldots,x_%7Bn%7D))%0A%5Cend%7Balign*%7D%0A"></p>
<p>So, for instance, if <img src="https://latex.codecogs.com/png.latex?F"> is the signature of <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebras, then there is a functor from <img src="https://latex.codecogs.com/png.latex?%5Coperatorname%7BKl%7D_%7BT_%7BF%7D%7D(%5Cmathsf%7BSet%7D)%5E%7B%5Cmathrm%7Bop%7D%7D"> to <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSet%7D">, which sends <img src="https://latex.codecogs.com/png.latex?X"> to <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D%5EX">. This turns symbolic functions into real functions.</p>
<p>What are the advantages of working with symbolic functions instead of regular functions? Well, for one, they make it possible in the first place to work with functions at all! Ultimately, we are never working with “real functions” on a computer; we’re always working implicitly with symbolic functions.</p>
<p>Explicitly working with symbolic functions has other benefits however. Classically, one benefit is that we can compute the derivative of symbolic functions easily. Note that we can do this not just with polynomials; we can throw in function symbols <img src="https://latex.codecogs.com/png.latex?%5Csin">, <img src="https://latex.codecogs.com/png.latex?%5Ccos">, <img src="https://latex.codecogs.com/png.latex?%5Cexp"> into our signature, and do all the exact same tricks as we’ve developed up until now! It might annoy algebraists, but who cares.</p>
<p>But the main benefit is that we might be able to find simpler representations of our functions, “canceling out” a large chunk of unnecessary computation so that our functions run faster in less memory.</p>
<p>In order to talk about this, however, we need to add <em>laws</em> to the picture.</p>
<div class="rmenv" title="Definition">
<p>An <strong>algebraic theory</strong> consists of a signature <img src="https://latex.codecogs.com/png.latex?F"> along with a collection <img src="https://latex.codecogs.com/png.latex?L"> of tuples <img src="https://latex.codecogs.com/png.latex?(X,%20l%20%5Cin%20E_%7BF%7D(X),%20r%20%5Cin%20E_%7BF%7D(X))"> which we call <strong>laws</strong>.</p>
</div>
<div class="rmenv" title="Definition">
<p>The theory of monoids has a signature <img src="https://latex.codecogs.com/png.latex?F%20=%20%5C%7Be,%20%5Ccdot%5C%7D"> with <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7Barity%7D(%5Ccdot)%20=%202"> and <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7Barity%7D(e)%20=%200">, along with laws</p>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?(%5C%7Ba,b,c%5C%7D,%20a%20%5Ccdot%20(b%20%5Ccdot%20c),%20(a%20%5Ccdot%20b)%20%5Ccdot%20c)"></li>
<li><img src="https://latex.codecogs.com/png.latex?(%5C%7Ba%5C%7D,%20a%20%5Ccdot%20e,%20a)"></li>
<li><img src="https://latex.codecogs.com/png.latex?(%5C%7Ba%5C%7D,%20e%20%5Ccdot%20a,%20a)"></li>
</ul>
</div>
<div class="rmenv" title="Definition">
<p>A <strong>model</strong> of a theory <img src="https://latex.codecogs.com/png.latex?(F,L)"> consists of a model <img src="https://latex.codecogs.com/png.latex?M"> of the signature <img src="https://latex.codecogs.com/png.latex?F">, such that for all <img src="https://latex.codecogs.com/png.latex?(X,%20l,%20r)%20%5Cin%20L">, for all <img src="https://latex.codecogs.com/png.latex?c%20%5Ccolon%20X%20%5Cto%20M">, the evaluation of <img src="https://latex.codecogs.com/png.latex?l"> with context <img src="https://latex.codecogs.com/png.latex?c"> is the same as the evaluation of <img src="https://latex.codecogs.com/png.latex?r"> with context <img src="https://latex.codecogs.com/png.latex?c">.</p>
</div>
<p>Other examples of algebraic theories include the algebraic theories of groups and the algebraic theory of rings. Additionally, for any ring <img src="https://latex.codecogs.com/png.latex?R">, there is an algebraic theory of rings <img src="https://latex.codecogs.com/png.latex?S"> along with maps <img src="https://latex.codecogs.com/png.latex?R%20%5Cto%20S">, which is given by adding a nullary function symbol for every element of <img src="https://latex.codecogs.com/png.latex?R">, along with appropriate laws about how those elements add and multiply with each other.</p>
<p>A similar trick can be done to get an algebraic theory of <em>modules</em> over a ring <img src="https://latex.codecogs.com/png.latex?R">; take the theory of abelian groups, and then add a unary function symbol for every element of <img src="https://latex.codecogs.com/png.latex?R"> representing scalar multiplication by that element. If <img src="https://latex.codecogs.com/png.latex?R"> happens to be a field, then we get an algebraic theory of vector spaces. Note that there is no algebraic theory of fields, because multiplicative inverse is not defined on zero; but there is an algebraic theory of vector spaces, because we don’t need to worry about universally quantifying division; it is just implicit in how the unary function symbols interact.</p>
<p>The exact same story that we told for signatures can be told for theories. I.e., there is an adjunction between the category of models for a theory and <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSet%7D">, and this adjunction induces a monad on <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSet%7D">. The left adjoint sends a set <img src="https://latex.codecogs.com/png.latex?X"> to the <em>free model</em> on that set. This is given by taking the model of the signature given by the well-formed expressions with variables taken from <img src="https://latex.codecogs.com/png.latex?X">, and then essentially just quotienting out until the laws hold. This models our ability to “rewrite” terms in a theory; the term <img src="https://latex.codecogs.com/png.latex?(x%20+%201)(x%20+%201)"> can be rewritten to <img src="https://latex.codecogs.com/png.latex?x%5E2%20+%202x%20+%201">. We might prefer the first one if we are trying to minimize multiplications, and the second one if we are trying to “normalize”.</p>
<p>In the case of <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebras, the free functor sends a set <img src="https://latex.codecogs.com/png.latex?X"> to a <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebra which is easy to describe; it sends it to the <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebra <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D%5BX%5D"> of polynomials with variables taken from <img src="https://latex.codecogs.com/png.latex?X"> and coefficients in <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">.</p>
<p>The canonical <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebra is just <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">. Thus, we can think of a map <img src="https://latex.codecogs.com/png.latex?Y%20%5Cto%20%5Cmathbb%7BR%7D%5BX%5D"> as a “symbolic” map from <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D%5EX"> to <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D%5EY">. In this particular case, it is just a polynomial map, but I say symbolic to emphasize that in the more general case when we aren’t talking about <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebras, we think about this as a symbolic map.</p>
<p>But by the adjunction, a map <img src="https://latex.codecogs.com/png.latex?Y%20%5Cto%20%5Cmathbb%7BR%7D%5BX%5D"> is the same as a map <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D%5BY%5D%20%5Cto%20%5Cmathbb%7BR%7D%5BX%5D">. We now arrive at the punchline of this section: maps of <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebras from <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D%5Bx_%7B1%7D,%5Cldots,x_%7Bn%7D%5D"> to <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D%5By_%7B1%7D,%5Cldots,y_%7Bm%7D%5D"> can be thought of as symbolic maps from <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D%5Em"> to <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D%5En">.</p>
<p>Thus, the <em>dual</em> of the category of free <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebras can be understood as the category of multivariate symbolic functions. We can see that this result should be interpreted more generally; the dual of the category of free models of an algebraic theory can be understood as a category of multivariate symbolic functions.</p>
<p>But why stop at free models? What about more general models? How might we interpret the dual of the category of algebraic theories as a category of “spaces and symbolic functions between them”? That is the subject of the next section.</p>
</section>
<section id="algebraic-spaces" class="level1">
<h1>Algebraic Spaces</h1>
<p>In this section, we discuss symbolic functions between spaces which are more interesting than just <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D%5En">. For the sake of concreteness, we will continue to work with <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebras, because these are more traditional than other algebraic theories, but a similar story could be told with other algebraic theories.</p>
<p>This is more traditional algebraic geometry material, and thus there are a wealth of references which cover similar material. For a classical algebraic geometry approach, the reader can refer to <span class="citation" data-cites="eisenbud_geometry_2000">Eisenbud and Harris (2000)</span>, and a more modern approach relying more heavily on category theory can be found in <span class="citation" data-cites="vakil_rising_2017">Vakil (2017)</span>.</p>
<div class="rmenv" title="Definition">
<p>The zero set of a function <img src="https://latex.codecogs.com/png.latex?f%20%5Ccolon%20%5Cmathbb%7BR%7D%5En%20%5Cto%20%5Cmathbb%7BR%7D%5Ek"> is the set</p>
<p><img src="https://latex.codecogs.com/png.latex?%20%5C%7Bx%20%5Cin%20%5Cmathbb%7BR%7D%5En%20%5Cmid%20f(x)%20=%200%20%5C%7D"></p>
</div>
<div class="rmenv" title="Example">
<p>The 2-sphere <img src="https://latex.codecogs.com/png.latex?S%5E2"> is the zero set of the function <img src="https://latex.codecogs.com/png.latex?f%20%5Ccolon%20%5Cmathbb%7BR%7D%5E3%20%5Cto%20%5Cmathbb%7BR%7D"> given by <img src="https://latex.codecogs.com/png.latex?f(x,y,z)%20=%20x%5E2%20+%20y%5E2%20+%20z%5E2%20-%201"></p>
</div>
<p>As a historical note, the definition of manifold in differential geometry used to be precisely zero sets of smooth functions.</p>
<p>Categorically speaking, a zero set of a function <img src="https://latex.codecogs.com/png.latex?f%20%5Ccolon%20%5Cmathbb%7BR%7D%5En%20%5Cto%20%5Cmathbb%7BR%7D%5Ek"> is given as the <em>equalizer</em> of the maps</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2023/03/algebraic-geometry-1/_svgs/8a3ac1a9d42ddf2bfa6a5825f484693b5f15e311.svg" class="img-fluid">
</div>
<p>Recall that the equalizer is the universal object <img src="https://latex.codecogs.com/png.latex?X"> with a map <img src="https://latex.codecogs.com/png.latex?X%20%5Cxrightarrow%7Bi%7D%20%5Cmathbb%7BR%7D%5En"> such that <img src="https://latex.codecogs.com/png.latex?f%20%5Ccirc%20i%20=%200%20%5Ccirc%20i%20=%200">. If we are working in a good category of spaces<sup>2</sup>, this is given precisely by the zero set of <img src="https://latex.codecogs.com/png.latex?f">, with appropriate structure.</p>
<p>Now, let’s compute this equalizer in our category of multivariate symbolic functions. A symbolic function <img src="https://latex.codecogs.com/png.latex?f%20%5Ccolon%20%5Cmathbb%7BR%7D%5En%20%5Cto%20%5Cmathbb%7BR%7D%5Ek"> is a <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebra homomorphism <img src="https://latex.codecogs.com/png.latex?f%20%5Ccolon%20%5Cmathbb%7BR%7D%5By_1,%5Cldots,y_k%5D%20%5Cto%20%5Cmathbb%7BR%7D%5Bx_1,%5Cldots,x_n%5D">. We want to compute the “equalizer” of that function with the zero function (quiz: what is the zero function symbolically?). Because algebra is dual to geometry, this turns into computing the coequalizer in the category of free <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebras. But this category doesn’t have all coequalizers! Fortunately, there’s a convenient category hanging around that <em>does</em> have coequalizers: the category of all <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebras.</p>
<p>The coequalizer of <img src="https://latex.codecogs.com/png.latex?f"> with <img src="https://latex.codecogs.com/png.latex?0"> in the category of all <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebras is the quotient</p>
<p><img src="https://latex.codecogs.com/png.latex?%20%5Cmathbb%7BR%7D%5Bx_1,%5Cldots,x_n%5D/(f(y_1),%5Cldots,f(y_n))%20"></p>
<p>This is the set of polynomials in <img src="https://latex.codecogs.com/png.latex?x_1,%5Cldots,x_n">, “modded out” by the equivalence relation that <img src="https://latex.codecogs.com/png.latex?p%20%5Csim%20q"> if there exist polynomials <img src="https://latex.codecogs.com/png.latex?r_1,%5Cldots,r_n"> such that</p>
<p><img src="https://latex.codecogs.com/png.latex?%20p%20=%20q%20+%20r_1%20f(y_1)%20+%20%5Ccdots%20+%20r_n%20f(y_n)%20"></p>
<p>Why does this make sense? Recall that <img src="https://latex.codecogs.com/png.latex?f(y_i)"> is an expression in <img src="https://latex.codecogs.com/png.latex?x_1,%5Cldots,x_n">. When we assign values to the <img src="https://latex.codecogs.com/png.latex?x_i"> such that <img src="https://latex.codecogs.com/png.latex?f(y_i)%20=%200">, then in fact, <img src="https://latex.codecogs.com/png.latex?p"> evaluates to <img src="https://latex.codecogs.com/png.latex?q">. So if we are staying in the zero set of <img src="https://latex.codecogs.com/png.latex?f">, it makes sense to rewrite <img src="https://latex.codecogs.com/png.latex?p"> to <img src="https://latex.codecogs.com/png.latex?q">.</p>
<div class="rmenv" title="Example">
<p>Consider the 2-sphere again. Following our construction, the <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebra that we would assign to the 2-sphere is <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D%5Bx,y,z%5D/(x%5E2%20+%20y%5E2%20+%20z%5E2%20-%201)">. In this <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebra, the polynomial <img src="https://latex.codecogs.com/png.latex?x%5E2"> is equal to <img src="https://latex.codecogs.com/png.latex?1%20-%20y%5E2%20-%20z%5E2">. This makes sense, because as functions on the 2-sphere, <img src="https://latex.codecogs.com/png.latex?x%5E2"> always has the same value as <img src="https://latex.codecogs.com/png.latex?1%20-%20y%5E2%20-%20z%5E2">, just like <img src="https://latex.codecogs.com/png.latex?2(x%20+%20y)"> always has the same value as <img src="https://latex.codecogs.com/png.latex?2%20x%20+%202%20y">. So modding out by <img src="https://latex.codecogs.com/png.latex?x%5E2%20+%20y%5E2%20+%20z%5E2%20-%201"> is basically stating the assumption that we are living on the zero-set of <img src="https://latex.codecogs.com/png.latex?x%5E2%20+%20y%5E2%20+%20z%5E2%20-%201">.</p>
</div>
<p>In general, models of algebraic theories can always be expressed as quotients of free models. So this gives us an interpretation of the dual of the category of all models; it represents subspaces of product spaces, and symbolic functions between them.</p>
<p>We will finish with an observation. In a category with a terminal object <img src="https://latex.codecogs.com/png.latex?1">, we think of maps <img src="https://latex.codecogs.com/png.latex?1%20%5Cto%20X"> as points of <img src="https://latex.codecogs.com/png.latex?X">. In the category of <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebras, there is an <em>initial object</em>, namely <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">. So for a general <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebra <img src="https://latex.codecogs.com/png.latex?S">, we might think of maps <img src="https://latex.codecogs.com/png.latex?S%20%5Cto%20%5Cmathbb%7BR%7D"> as “points” of <img src="https://latex.codecogs.com/png.latex?S">.</p>
<p>In the case of <img src="https://latex.codecogs.com/png.latex?S%20=%20%5Cmathbb%7BR%7D%5Bx_1,%5Cldots,x_n%5D">, a map <img src="https://latex.codecogs.com/png.latex?S%20%5Cto%20%5Cmathbb%7BR%7D"> is generated by where <img src="https://latex.codecogs.com/png.latex?x_1,%5Cldots,x_n"> are sent. So such a map is precisely an element of <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D%5En">. If we instead take <img src="https://latex.codecogs.com/png.latex?S%20=%20%5Cmathbb%7BR%7D%5Bx_1,%5Cldots,x_n%5D/(p_1,%5Cldots,p_k)">, then a map <img src="https://latex.codecogs.com/png.latex?S%20%5Cto%20%5Cmathbb%7BR%7D"> is again generated by where <img src="https://latex.codecogs.com/png.latex?x_1,%5Cldots,x_k"> are sent. However, we also need to send <img src="https://latex.codecogs.com/png.latex?p_1,%5Cldots,p_k"> to <img src="https://latex.codecogs.com/png.latex?0">. So such a map is precisely an element <img src="https://latex.codecogs.com/png.latex?v%20%5Cin%20R%5En">, where <img src="https://latex.codecogs.com/png.latex?p_1(v),%5Cldots,p_k(v)%20=%200">. That is, it is an element of the zero set of <img src="https://latex.codecogs.com/png.latex?p%20%5Ccolon%20%5Cmathbb%7BR%7D%5En%20%5Cto%20%5Cmathbb%7BR%7D%5Ek">. So the “points” of the “symbolic space” are just the points of the actual space!</p>
<p>The contravariant functor <img src="https://latex.codecogs.com/png.latex?%5Coperatorname%7BHom%7D(-,%20%5Cmathbb%7BR%7D)"> from the category of <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebras to <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSet%7D"> is called <img src="https://latex.codecogs.com/png.latex?%5Cmathrm%7BSpec%7D">; it takes an <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebra to the “set of points” in the space that the <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebra represents. This functor is contravariant because (once more, say it with me) algebra is dual to geometry!</p>



</section>


<div id="quarto-appendix" class="default"><section class="quarto-appendix-contents" id="quarto-bibliography"><h2 class="anchored quarto-appendix-heading">References</h2><div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="0">
<div id="ref-eisenbud_geometry_2000" class="csl-entry">
Eisenbud, David, and Joe Harris. 2000. <em>The Geometry of Schemes</em>. Vol. 197. Graduate Texts in Mathematics. New York: Springer-Verlag. <a href="https://doi.org/10.1007/b97680">https://doi.org/10.1007/b97680</a>.
</div>
<div id="ref-goguen_theorem_2021" class="csl-entry">
Goguen, Joseph A. 2021. <span>“Theorem Proving and Algebra.”</span> <em><span>arXiv</span>:2101.02690 [Cs]</em>, January. <a href="http://arxiv.org/abs/2101.02690">http://arxiv.org/abs/2101.02690</a>.
</div>
<div id="ref-vakil_rising_2017" class="csl-entry">
Vakil, Ravi. 2017. <span>“The Rising Sea.”</span> <a href="https://math.stanford.edu/~vakil/216blog/FOAGnov1817public.pdf">https://math.stanford.edu/~vakil/216blog/FOAGnov1817public.pdf</a>.
</div>
</div></section><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>

<ol>
<li id="fn1"><p>We defined the signature of <img src="https://latex.codecogs.com/png.latex?%5Cmathbb%7BR%7D">-algebras before. It turns out that these two uses of the word “algebra” are actually compatible in a certain sense, but we will not get into exactly why right now.↩︎</p></li>
<li id="fn2"><p>For reasons we won’t go into here, the category of manifolds is <em>not</em> good↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>algebra</category>
  <category>logic</category>
  <guid>https://blog.algebraicjulia.org/post/2023/03/algebraic-geometry-1/</guid>
  <pubDate>Thu, 23 Mar 2023 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Using categorical logic for AI planning</title>
  <dc:creator>Angeline Aguinaldo</dc:creator>
  <link>https://blog.algebraicjulia.org/post/2022/09/ai-planning-cset/</link>
  <description><![CDATA[ 





<div class="hidden">
<p>$$ <!-- Number systems --> </p>
<!-- Categories -->
<!-- Graphs -->
<!-- Double categories -->
<!-- Acsets -->
<!-- Wiring diagrams -->
<!-- Dynamical systems -->
<p>$$</p>
</div>
<p><em>This post is cross-posted at the <a href="https://topos.site/blog/2022/09/using-categorical-logic-for-ai-planning/">Topos Institute blog</a>.</em></p>
<blockquote class="blockquote">
<p>”Engineers are not the only professional designers. Everyone [or thing] designs who devises courses of action aimed at changing existing situations into preferred ones.” – Herbert Simon <span class="citation" data-cites="simon1988">(Simon 1988)</span></p>
</blockquote>
<p>It’s breakfast time! You wake up and walk to your kitchen and notice a loaf of bread, a knife, a raw egg (in its shell), a skillet, and a stove burner sitting on the counter. You’re hungry and your preferred state of existence is to, instead, have an egg sandwich sitting on your counter. You are saddened by the situation, but feel empowered to change it! You compare what you have and what you want, recall what cooking skills you have, and devise the following steps:</p>
<ol type="1">
<li>Slice the bread twice with a knife</li>
<li>Put the slices of bread on a plate</li>
<li>Put the skillet on the stove burner</li>
<li>Crack the egg on the skillet</li>
<li>Wait until the egg is cooked</li>
<li>Put the egg on a slice of bread</li>
<li>Close the bread</li>
</ol>
<p>In this example, and in all planning problems, you can notice three conceptual notions: a plan, a planner, and a planning problem. The plan is the sequence of steps you devised. The planner is your cognitive reasoning activity. And the planning problem is the comparison of the states and the knowledge of skills you have. Planning is fairly automatic for most everyday tasks, so much so that we rarely think about these distinctions or even acknowledge that we’re doing any planning. However, if we wish to transition this activity to a computer, making all three concepts computable is necessary.</p>
<p>Automated planning is the domain of artificial intelligence (AI) aimed at identifying a <em>sequence of actions</em>, or a <em>plan</em>, that changes the current state of the world to a preferred state, namely one that meets some goal criteria. A planner takes a planning problem and produces a plan. One choice, the most common, is to construct a language syntax that can accommodate the semantics of actions, action requirements, and action effects. It’s then up to the planner to devise its own syntax and semantics for how to interpret, manage this information, and present a plan. For example, in practice, architectures that involve planning usually call on a <a href="https://planning.wiki/">PDDL planner</a> <span class="citation" data-cites="ghallab1998">(Ghallab et al. 1998)</span> as an external service. The way they manage and update data about the world is handled independently by either translating the plan steps into database updates, or (more likely) re-sampling the world during or after the plan is executed. Evidently, having differing languages could result in conflicts and reduced inteoperability between planners, databases, and plan consumers.</p>
<p>Another choice would be to define a common abstraction, modeling for syntax and semantics, for the planner, planning problem, and the plan to reduce friction between representations. In this blog post, I will explain how a category-theoretic method called double-pushout (DPO) rewriting in the category of copresheaves can operationalize these concepts.</p>
<section id="the-anatomy-of-a-rewrite-rule" class="level1">
<h1>The anatomy of a rewrite rule</h1>
<p>Rewrite rules are the atomic operations that translate data from one state to another. A rewrite rule contains three parts: an <strong>input</strong>, a <strong>keep</strong>, and an <strong>output</strong>. The <strong>input</strong> portion describes the types of things and relationships that are required before the rule can be applied to a world state. The <strong>output</strong> portion describes the types of things and relationships that exist in the world after the rule has been applied. The <strong>keep</strong> portion describes the types of things that remain consistent between the input and the output. For example, if we want to design a rule about slicing a piece of bread, we might want an input to contain a loaf of bread and a knife. At the end of this action, what we would want is a loaf of bread, a slice of bread, and a knife. We also want to say that the loaf of bread and knife we end up with is the <em>same</em> loaf of bread and knife we started with.</p>
<p><img src="https://blog.algebraicjulia.org/post/2022/09/ai-planning-cset/Anatomy of a rule.png" class="img-fluid"></p>
<p>The terms “input” and “output” are intentionally reminiscent of pre-conditions and post-conditions/effects in the traditional planning literature. However, the term “keep” is a novel concept that was introduced to track entities that persist between the two states. “Why,” you might wonder, “can’t I just construct a map directly from the input to the output?” Interestingly, the <strong>keep</strong> portion gives us useful information about what elements have <em>permission</em> to disappear. If I had an element in the input that did not appear in the output, a map directly from the input to the output would force me to assign that element to something (assuming our maps are total) which would not be conceptually accurate. However, if it did not exist in my <strong>keep</strong>, then I would not need to account for it in my output state and it would be free to disappear. In automated planning, the <a href="https://en.wikipedia.org/wiki/Frame_problem">frame problem</a> is concerned with how to axiomatically account for information that remains unchanged. While this method does not exactly provide a set of axioms, it does provide a mechanism to declare what things remain unchanged when a rule is applied.</p>
<p>Now I’ve not said anything about the nature of the <strong>input</strong>, <strong>keep</strong>, and <strong>output</strong> portions of my rules. What are they? Graphs? Sets? Manifolds?! Well, formally, a rule is a span in the category of copresheaves, or <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets.</p>
<section id="what-are-mathsfc-sets" class="level2">
<h2 class="anchored" data-anchor-id="what-are-mathsfc-sets">What are <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets?</h2>
<p>Let <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D"> be a small category, which we think of as a <em>schema</em>. A <em><img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set</em>, also called a <em>copresheaf on <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D"></em>, is a functor from the schema <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D"> to the category <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSet%7D">. The schema is a category whose objects are types and whose morphisms describe “is-a” and other functional relationships between types. You can consider it to be a denotational semantics for ontologies. The category <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSet%7D"> is the category of sets and functions. Thus, a <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set is a functor that sends types to sets and type relationships to functions. <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets are a simple model of <em>categorical databases</em> <span class="citation" data-cites="1009.1166">(Spivak 2012)</span> and have a full-featured implementation in <a href="https://github.com/AlgebraicJulia/Catlab.jl">Catlab.jl</a> <span class="citation" data-cites="2106.04703">(Patterson, Lynch, and Fairbanks 2021)</span>.</p>
<p>Morphisms of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets are natural transformations between functors. With this definition, for any schema <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">, there is a category <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D%5Ctext%7B-%7D%5Cmathsf%7BSet%7D"> of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets and their homomorphisms.</p>
<p>To take an example, we can examine a rule that tells us what happens when we <code>:slice_bread</code>. More precisely, this block of code is constructing a span <img src="https://latex.codecogs.com/png.latex?(%5Cbullet%20%5Cleftarrow%20%5Cbullet%20%5Crightarrow%20%5Cbullet)"> of copresheaves by taking colimits of <a href="https://bartoszmilewski.com/2015/07/29/representable-functors/">representable functors</a>. A proof of this statement can be found in <span class="citation" data-cites="maclane1978">(Lane 1978, chap. III.7)</span>. The important thing to know is that a representable functor keeps track of all the morphisms that are involved with an object <img src="https://latex.codecogs.com/png.latex?a%20%5Cin%20%5Cmathsf%7BC%7D">, often where the functor is denoted as <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D(a,-)">.</p>
<p>In this code, you can see that there are three objects, <code>I</code>, <code>O</code>, and <code>K</code>, that define an assignment map between things like <code>Knife</code> and <code>knife</code> (note the difference in capitalization).</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb1-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>slice_bread <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@migration</span>(SchDB, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb1-2">    I <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@join</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb1-3">      loaf<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">BreadLoaf</span></span>
<span id="cb1-4">      knife<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Knife</span></span>
<span id="cb1-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb1-6">    O <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@join</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb1-7">      loaf<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">BreadLoaf</span></span>
<span id="cb1-8">      slice<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">BreadSlice</span></span>
<span id="cb1-9">      <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">food_in_on</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bread_slice_is_food</span>(slice)) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">food_in_on</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bread_loaf_is_food</span>(loaf))</span>
<span id="cb1-10">      knife<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Knife</span></span>
<span id="cb1-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb1-12">    K <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@join</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb1-13">      loaf<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">BreadLoaf</span></span>
<span id="cb1-14">      knife<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Knife</span></span>
<span id="cb1-15">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb1-16">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span>),</span></code></pre></div>
<p>In particular, we can see that for our input we have a functor <img src="https://latex.codecogs.com/png.latex?%5Ctexttt%7BI%7D:%20%5Cmathsf%7BC%7D%20%5Cto%20%5Cmathsf%7BSet%7D"> that sends the objects explicitly as follows: <img src="https://latex.codecogs.com/png.latex?%0A%5Ctexttt%7BBreadLoaf%7D%20%5Cmapsto%20%5Ctexttt%7Bloaf%7D%20%5C%5C%0A%5Ctexttt%7BKnife%7D%20%5Cmapsto%20%5Ctexttt%7Bknife%7D%0A"></p>
<p>The more useful aspect of this functor, however, is the implicit assignment of morphisms and other objects. <code>BreadLoaf</code> and <code>Knife</code> are involved in morphisms in <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D"> whose codomains involve other seemingly hidden objects like <code>Food</code>, <code>Kitchenware</code>, and <code>Entity</code> (described in <code>SchDB</code>). Being a representable functor, <code>I</code> has the important role of accounting for the assignments of these morphisms and objects in the target category, <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSet%7D">. Because of this, it can be seen that this feature automatically manages implicit inputs (pre-conditions) and outputs (effects) provided the schema sufficiently encoded relationships to other object. This handling of <em>implicit</em> pre-conditions and effects are termed as the <em>qualification problem</em> and the <em>ramification problem</em> of the frame problem, respectively <span class="citation" data-cites="ghallab2004">(Ghallab, Nau, and Traverso 2004)</span>.</p>
<p><img src="https://blog.algebraicjulia.org/post/2022/09/ai-planning-cset/I_cset.svg" class="img-fluid"></p>
<p>In this category, you also have the ability to glue things together by declaring objects as being equal, as is done in the line:</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb2-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">food_in_on</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bread_slice_is_food</span>(slice)) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">food_in_on</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bread_loaf_is_food</span>(loaf))</span></code></pre></div>
<p>The gluing can be thought of as a colimit in the category of copresheaves. The result of this particular gluing can be seen below.</p>
<p><img src="https://blog.algebraicjulia.org/post/2022/09/ai-planning-cset/O_cset.svg" class="img-fluid"></p>
</section>
</section>
<section id="applying-rules" class="level1">
<h1>Applying rules</h1>
<p>Now that we have a sense of how to construct rules, we can see how to use them to derive new world states.</p>
<section id="applicability-criteria" class="level2">
<h2 class="anchored" data-anchor-id="applicability-criteria">Applicability criteria</h2>
<p>As we’ve seen, rules are represented by spans in the category of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets. In the setting of automated planning, we think of these rules as actions in our plan that transform aspects of a world from one state to another. The <em>world state</em> is just another object in our category of copresheaves. In planning, an action can only be applied to the world if the pre-conditions, or inputs, are met in the world state. Therefore, in our framework, we consider a rule to be <em>applicable</em> if there exists a monomorphism from the rule input, <img src="https://latex.codecogs.com/png.latex?I">, to the world state in question, <img src="https://latex.codecogs.com/png.latex?Y">. The term <em>monomorphism</em> refers to a generalization of an injective function and is denoted by a hooked arrow.</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2022/09/ai-planning-cset/_svgs/aa101ef4303b46a4d3e742891870629caa8a3ad5.svg" class="img-fluid">
</div>
<p>This applicability criteria will be useful in deciding what rules should be considered when building out a task plan.</p>
</section>
<section id="mechanics-of-application" class="level2">
<h2 class="anchored" data-anchor-id="mechanics-of-application">Mechanics of application</h2>
<p>Once we’ve decided that a rule is applicable, how can we use it to induce changes in our world states? Well, we know that the rule is statement about what should be in the world after the rule is applied and what should remain consistent between the input world state and the resulting world state. We also know that the category of copresheaves is an elementary topos, which in particular gives us the freedom to take limits and colimits. This is a convenient fact given that we have been spent much of this exposition talking about spans. So to resolve changes in our world based on a rule, we can consider using the <strong>double pushout (DPO) rewriting</strong> method <span class="citation" data-cites="ehrig1973 2111.03784">(Ehrig, Pfender, and Schneider 1973; Brown et al. 2022)</span>.</p>
<p>The general procedure of DPO rewriting is</p>
<ol type="1">
<li>Find a pushout complement*</li>
<li>Complete the left pushout</li>
<li>Complete the right pushout</li>
</ol>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2022/09/ai-planning-cset/_svgs/c862e9523e6de7e2cb9a0fd4fa46221ca855074b.svg" class="img-fluid">
</div>
<blockquote class="blockquote">
<p>*<strong>A few notes on pushout complements</strong>: A <a href="https://ncatlab.org/nlab/show/pushout+complement">pushout complement</a> is a map that manages the deletion of entities that form the complement <img src="https://latex.codecogs.com/png.latex?K%20/%20I">. Because <img src="https://latex.codecogs.com/png.latex?i"> is a monomorphism, the pushout complement is unique up to isomorphism, if it exists. Extra conditions, the <em>identification</em> and <em>dangling</em> conditions, are needed to ensure that the pushout complement exists.</p>
</blockquote>
<p>Finding the map <img src="https://latex.codecogs.com/png.latex?f:%20I%20%5Chookrightarrow%20X"> that gives the <em>match</em> of the rule to the world state is done using backtracking search. More information about this procedure can be found in the Catlab <a href="https://algebraicjulia.github.io/Catlab.jl/latest/apis/categorical_algebra/#Catlab.CategoricalAlgebra.CSets.BacktrackingSearch">documentation</a> on finding <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set homomorphisms.</p>
<p>We can demonstrate what this might look like using our <code>:slice_bread</code> rule and our chosen world state (a well-equipped kitchen!) in the following cartoon.</p>
<p><img src="https://blog.algebraicjulia.org/post/2022/09/ai-planning-cset/Apply rule with starting frame.png" class="img-fluid"></p>
<p>You can see, in the top-left, a depiction of the information we have about our world and our rule. In our world, we have a refridgerator, a loaf of bread, a pear (?), a knife, a bowl, and a skillet. We want to take the action of <code>:slice_bread</code>. Using DPO, we can first identify a map from the rule-keep and the world-keep that is the pushout complement. Recall that a pushout glues the target objects of the span along its apex. Therefore, we can check that our chosen pushout complement produces our world-input. Once we’ve determined this is valid, we can construct the pushout on the right as normal. From this we get a world where there is now all the same entities with the addition of a slice of bread participating in some relationship (gray line) to the loaf of bread. Note: the abbreviated light blue maps in the image should send each entity to “itself” in the world-input and the world-output.</p>
</section>
</section>
<section id="time-to-plan-forward-with-backtracking" class="level1">
<h1>Time to plan (forward with backtracking)!</h1>
<p>Now that we know how to choose rules and apply rules, we can begin planning. Recall that a <em>plan</em> is a sequence of actions that change an initial world state to one that satisfies some goal criteria. To set up a planning problem in our framework, we need to point out two objects in the category of copresheaves that are the initial state and the goal state. We can then consider a plan to be a sequence of rules that when applied to the initial state constructs an object such that a monic map exists from the goal state to that object. We borrow from successful methods in the field of automated planning to implement a forward search algorithm with backtracking <span class="citation" data-cites="ghallab2004">(Ghallab, Nau, and Traverso 2004, chap. 4)</span>. The exit criteria involves checking whether a monic map exists from the goal into the current world state.</p>
<p><img src="https://blog.algebraicjulia.org/post/2022/09/ai-planning-cset/forward planning with rule limit.png" class="img-fluid"></p>
<p>Pseudocode this planning algorithm is as follows:</p>
<hr>
<p><strong>Algorithm</strong>: Forward Planning with Backtracking</p>
<p><strong>Procedure</strong>: ForwardPlan(<img src="https://latex.codecogs.com/png.latex?Y"> world, <img src="https://latex.codecogs.com/png.latex?G"> goal, <code>r</code> rules, <code>r_usage</code> rule usage, <code>r_limits</code> rule limits, <code>p</code> plan)</p>
<ol type="1">
<li><p>(<em>Exit criteria</em>) <strong>If</strong> monomorphism <img src="https://latex.codecogs.com/png.latex?G%20%5Chookrightarrow%20Y"> exists</p>
<p>1a. <strong>Return</strong> Plan <code>p</code></p></li>
<li><p>Initialize applicable rules list, <code>applicable</code></p></li>
<li><p><strong>For</strong> <code>rule</code> in <code>r</code> <strong>do</strong></p>
<p>3a. Get the input object of <code>rule</code>, <img src="https://latex.codecogs.com/png.latex?r_I"></p>
<p>3b. Check if monomorphism <img src="https://latex.codecogs.com/png.latex?r_I%20%5Chookrightarrow%20Y"> exists</p>
<p>3c. <strong>If</strong> exists, append <code>rule</code> to <code>applicable</code></p></li>
<li><p>(<em>Backtrack criteria</em>) <strong>If</strong> <code>applicable</code> is empty, “No applicable rules!” <strong>ThrowException</strong></p></li>
<li><p><strong>For</strong> <code>a</code> in <code>applicable</code> <strong>do</strong></p>
<p>5a. (<em>Backtrack criteria</em>) <strong>If</strong> <code>r_usage[a]</code> &gt;= <code>r_limits[a]</code>, “Rule limit reached!” <strong>continue</strong></p>
<p>5b. <img src="https://latex.codecogs.com/png.latex?Y"> = DPO(<img src="https://latex.codecogs.com/png.latex?Y">, representable(<code>a</code>))</p>
<p>5c. Append <code>a</code> to <code>p</code></p>
<p>5d. ForwardPlan(<img src="https://latex.codecogs.com/png.latex?Y">, <img src="https://latex.codecogs.com/png.latex?G">, <code>r</code>, <code>r_usage</code>, <code>r_limits</code>, <code>p</code>)</p></li>
</ol>
<hr>
<blockquote class="blockquote">
<p>The deliberate type-setting choice is made to show what data is mathematically rigorous, those in math notation, and what data is a heuristic or workaround not derived from the categorical formalism, those in verbatim font. In particular, we say that <img src="https://latex.codecogs.com/png.latex?Y">, <img src="https://latex.codecogs.com/png.latex?G">, and <img src="https://latex.codecogs.com/png.latex?r_I"> are objects in the category of copresheaves.</p>
</blockquote>
<p>As with other planning algorithms, this method is subject to issues related to cycles and non-termination. This occurs in scenarios where a rule might be applicable indefinitely if the world specification does not capture a way of destructing an object when a rule is applied. For example, in the present model, slicing the bread does not reduce the bread loaf in any manner which means our planner could potentially slice the bread loaf infinitely many times. The integration of attributed <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets, or “acsets”, is in the future of this framework which would allow users to specify attributes for each entity, such as <img src="https://latex.codecogs.com/png.latex?%5Ctexttt%7BBreadLoaf%7D%20%5Cto%20%5Ctexttt%7BNumSlices%7D">. This structure would provide a well-defined way to do arithmetic and other manipulations with the attributes which could help keep track of resource limits. For now, we use an ad hoc method, a <code>rule_limit</code> dictionary that specifies the maximum number of times a rule can be applied in a plan.</p>
</section>
<section id="why-the-categorical-abstraction" class="level1">
<h1>Why the categorical abstraction?</h1>
<p>You might be wondering what are the benefits of all this formalism when there already exist working systems for automated planning. In fact, the current practice suffers from a number of limitations that I think a categorical point of view can help address.</p>
<ul>
<li><strong>A method for propagating implicit pre-conditions and effects</strong>. As mentioned earlier, the frame problem is concerned with accounting for implicit world conditions in light of explicit ones. And, as we saw, tracking implicit effects (the so-called ramification problem) and implicit preconditions (the qualification problem) is taken care of because of our use of functors from <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D"> to Set. This gives rule designers to freedom to only model the changes are most important and trust that related changes will be dragged along.</li>
<li><strong>A common abstraction for actions and events</strong>. Existing planners are not able to handle external events. In this framework, actions and events are things of the same type, namely rewrite rules for categorical databases. This means that we can support two modes of operation within a dynamic planning environment: we can (a) apply a rewrite rule that captures some external event and update our current state of the world, or we can (b) search for a plan between the current world state and the goal. This shared abstraction gives us the ability to take in new information and conduct planning without having to state a new planning problem.</li>
<li><strong>A more structured language than first-order logic</strong>. For practioners trying to use automated planning in applications, expressing your planning problem in terms of first-order logic formulas may feel awkward and unstructured. The propositional atoms that comprise these formulas require careful modeling of the semantics with little guidance. For example, some example atoms could be <code>breadloaf_on_table=True</code>, <code>slice_on_table=False</code>, and <code>knife_in_hand=True</code>; however, they could also be <code>breadloaf_sitting_on_table=True</code> and <code>knife_in_left_hand=True</code> which could serve an equivalent purpose depending on how my actions use these atoms. The ability to capture knowledge under the guidance of an ontology, or schema, provides a more natural way of expressing conditions of the world for planning problems.</li>
<li><strong>A way to handle hierarchy and concurrency</strong>. There is currently no way to handle equivalences between permutations of actions that are independent of each other. Forward and backward planning assume totally ordered sequence of actions. Plan-space planning allows a partially ordered set of plans, but does not handle actions that depend on one another. Current planners also do not have ways of dealing with simultaneously occurring actions <span class="citation" data-cites="brachman2004">(Brachman and Levesque 2004, sec. 15.3.1)</span>. Expressing a plan, planner, and planning problem using a categorical lanugage would provide a gateway to other structures like operads (hierarchy) and monoidal categories (concurrency).</li>
</ul>
<p>Despite these benefits, significant work for us remains. This post described a way of stating a planning problem in a categorical way and adapting an existing planning algorithm to work with this abstraction. However, we have still not explained how to describe a plan in a more structured way, beyond just a sequence of rules. Furthermore, we would like to investigate how category theory could help in devising planning algorithms, in particular hierarchical planners. If you have any ideas, please feel free to share your thoughts below!</p>



</section>

<div id="quarto-appendix" class="default"><section class="quarto-appendix-contents" id="quarto-bibliography"><h2 class="anchored quarto-appendix-heading">References</h2><div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="0">
<div id="ref-brachman2004" class="csl-entry">
Brachman, Ronald, and Hector Levesque. 2004. <em>Knowledge Representation and Reasoning</em>. Elsevier. <a href="https://doi.org/10.1016/b978-1-55860-932-7.x5083-3">https://doi.org/10.1016/b978-1-55860-932-7.x5083-3</a>.
</div>
<div id="ref-2111.03784" class="csl-entry">
Brown, Kristopher, Evan Patterson, Tyler Hanks, and James Fairbanks. 2022. <span>“Computational Category-Theoretic Rewriting.”</span> In <em>Graph Transformation</em>, 155–72. Springer International Publishing. <a href="https://doi.org/10.1007/978-3-031-09843-7_9">https://doi.org/10.1007/978-3-031-09843-7_9</a>.
</div>
<div id="ref-ehrig1973" class="csl-entry">
Ehrig, H., M. Pfender, and H. J. Schneider. 1973. <span>“Graph-Grammars: An Algebraic Approach.”</span> In <em>14th Annual Symposium on Switching and Automata Theory (Swat 1973)</em>. <span>IEEE</span>. <a href="https://doi.org/10.1109/swat.1973.11">https://doi.org/10.1109/swat.1973.11</a>.
</div>
<div id="ref-ghallab1998" class="csl-entry">
Ghallab, Malik, Adele E. Howe, Craig A. Knoblock, Drew McDermott, Ashwin Ram, Manuela M. Veloso, Daniel S. Weld, and David E. Wilkins. 1998. <span>“PDDL-the Planning Domain Definition Language.”</span> In.
</div>
<div id="ref-ghallab2004" class="csl-entry">
Ghallab, Malik, Dana Nau, and Paolo Traverso. 2004. <em>Automated Planning</em>. Elsevier. <a href="https://doi.org/10.1016/b978-1-55860-856-6.x5000-5">https://doi.org/10.1016/b978-1-55860-856-6.x5000-5</a>.
</div>
<div id="ref-maclane1978" class="csl-entry">
Lane, Saunders Mac. 1978. <em>Categories for the Working Mathematician</em>. Springer New York. <a href="https://doi.org/10.1007/978-1-4757-4721-8">https://doi.org/10.1007/978-1-4757-4721-8</a>.
</div>
<div id="ref-2106.04703" class="csl-entry">
Patterson, Evan, Owen Lynch, and James Fairbanks. 2021. <span>“Categorical Data Structures for Technical Computing.”</span> <a href="https://doi.org/10.32408/compositionality-4-5">https://doi.org/10.32408/compositionality-4-5</a>.
</div>
<div id="ref-simon1988" class="csl-entry">
Simon, Herbert A. 1988. <span>“The Science of Design: Creating the Artificial.”</span> <em>Design Issues</em> 4 (1/2): 67. <a href="https://doi.org/10.2307/1511391">https://doi.org/10.2307/1511391</a>.
</div>
<div id="ref-1009.1166" class="csl-entry">
Spivak, David I. 2012. <span>“Functorial Data Migration.”</span> <em>Information and Computation</em> 217 (August): 31–51. <a href="https://doi.org/10.1016/j.ic.2012.05.001">https://doi.org/10.1016/j.ic.2012.05.001</a>.
</div>
</div></section></div> ]]></description>
  <category>planning</category>
  <category>rewriting</category>
  <category>c-sets</category>
  <guid>https://blog.algebraicjulia.org/post/2022/09/ai-planning-cset/</guid>
  <pubDate>Wed, 21 Sep 2022 00:00:00 GMT</pubDate>
</item>
<item>
  <title>The chase: data repair and logical reasoning</title>
  <dc:creator>Kris Brown</dc:creator>
  <link>https://blog.algebraicjulia.org/post/2022/06/chase/</link>
  <description><![CDATA[ 





<div class="hidden">
<p>$$ <!-- Number systems --> </p>
<!-- Categories -->
<!-- Graphs -->
<!-- Double categories -->
<!-- Acsets -->
<!-- Wiring diagrams -->
<!-- Dynamical systems -->
<p>$$</p>
</div>
<p>One can view the task of modeling as trying to capture a phenomenon in terms of structure (<em>what</em> exists) as well as properties that hold of that structure, expressed in form of logical constraints. <a href="https://en.wikipedia.org/wiki/Chase_(algorithm)">The chase</a> is an algorithm which enforces logical constraints that trades off well for expressivity and computational tractability. We will give a description of the algorithm at a high level, explore the language of constraints it allows us to enforce, and describe the details of its implementation in <a href="https://github.com/AlgebraicJulia/Catlab.jl">Catlab.jl</a>. The applications below will show that this tradeoff is well-suited for tasks in scientific computing and knowledge representation.</p>
<section id="introduction" class="level1">
<h1>Introduction</h1>
<p>Let’s create a simple model of chemistry with atoms, molecules, and bonds. Atoms have a functional relationship to molecules, <img src="https://latex.codecogs.com/png.latex?molecule:%20%7B%5Crm%20Atom%7D%20%5Crightarrow%20%7B%5Crm%20Molecule%7D">, i.e.&nbsp;every <img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Atom%7D"> relates to exactly one <img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Molecule%7D"> (<img src="https://latex.codecogs.com/png.latex?molecule"> can be thought of as a <em>function</em> from <img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Bond%7D"> to <img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Molecule%7D">) . Bonds are a kind of entity that can exist between pairs of atoms. We can relate a bond to its two atoms via functional relationships <img src="https://latex.codecogs.com/png.latex?bond_1,%20bond_2:%20%7B%5Crm%20Bond%7D%20%E2%9F%B6%20%7B%5Crm%20Atom%7D">. If we write <img src="https://latex.codecogs.com/png.latex?%7Bb=bond(x,y)%7D">, then implicitly we mean that there exists a bond <img src="https://latex.codecogs.com/png.latex?b"> and atoms <img src="https://latex.codecogs.com/png.latex?x"> and <img src="https://latex.codecogs.com/png.latex?y"> such that <img src="https://latex.codecogs.com/png.latex?bond_1(b)=x"> and <img src="https://latex.codecogs.com/png.latex?bond_2(b)=y">. Intuitively, bonds ought satisfy the following properties: - Bonds are symmetric, expressed as <img src="https://latex.codecogs.com/png.latex?%7B%E2%88%80%20x,y%20%5Cin%20%7B%5Crm%20Atom%7D,%5C%20bond(x,y)%20%5Cimplies%20bond(y,x)%7D">. - Atoms in different molecules can’t be bonded: <img src="https://latex.codecogs.com/png.latex?%7B%5Cforall%20x,y%20%5Cin%20%7B%5Crm%20Atom%7D,%20bond(x,y)%20%5Cimplies%20molecule(x)%20=%20molecule(y)%7D">.</p>
<p>So far we have <em>entities</em> (e.g.&nbsp;<img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Atom%7D">, <img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Bond%7D">, <img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Molecule%7D">) and <em>functional relationships</em> (e.g.&nbsp;<img src="https://latex.codecogs.com/png.latex?molecule">). <a href="https://en.wikipedia.org/wiki/Relational_database">Relational databases</a> are an ubiquitous technology that has been heavily optimized to work with data of this form. In the language of relational databases, entities are viewed as <em>tables</em>, with their functional relationships viewed as <em>columns</em> (also called <em>foreign keys</em>). The structure of a model that is implemented as a relational database is given by a <em>schema</em> which lists the entities and functional relationships. This specification of schemas is typically handled by <a href="https://en.wikipedia.org/wiki/SQL">SQL</a>, which has been incredibly successful in many domains; however, this framework leaves something to be desired in terms of declaring and enforcing properties of our model. <em>Ologs</em> (ontology logs), on the other hand, are a category-theoretic interpretation of knowledge bases, which are structurally identical to relational databases yet have a rich logic of constraints that can further encode knowledge <span class="citation" data-cites="spivak2012">(Spivak and Kent 2012)</span>. Being able to enforce these constraints in a computationally tractable way is a difference between databases and knowledge bases.</p>
<p>For example: supposing we have a database of atoms, bonds, and molecules along with a set of constraints (hereafter referred to as <img src="https://latex.codecogs.com/png.latex?%5CSigma">), we can ask whether the database satisfies <img src="https://latex.codecogs.com/png.latex?%5CSigma">. If not, we can imagine there being the best or nearest-relative of the database that <em>does</em> satisfy <img src="https://latex.codecogs.com/png.latex?%5CSigma">. The <em>chase</em> is an algorithm that repairs our data to find this other database <span class="citation" data-cites="benedikt2017">(Benedikt et al. 2017)</span>. The next two sections respectively show how to define this notion of a “best” relative and describe the language in which constraints for the chase are specified.</p>
<p>Given a chase engine, what practical things can we <em>do</em>? Firstly, we have a general means of propagating information implied by the properties of a model, allowing for databases to be used as <em>ologs</em>. This will be described at the end of the post, along with other applications such as model enumeration (exploring logically-constrained search spaces). A future post will describe applications to <a href="https://docs.rs/egg/0.6.0/egg/tutorials/_01_background/index.html">e-graphs</a> (equational reasoning that can be used for program optimization).</p>
<section id="data-repair-defining-a-best-possible-repaired-database" class="level2">
<h2 class="anchored" data-anchor-id="data-repair-defining-a-best-possible-repaired-database">Data repair: defining a ‘best possible’ repaired database</h2>
<p>In AlgebraicJulia, we represent relational databases as <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets.<sup>1</sup> <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set <a href="https://www.algebraicjulia.org/blog/post/2021/04/cset-graphs-3/#morphisms_of_mathsf$\cat%7BC%7D$-sets">homomorphisms</a> (also called morphisms) are a natural relation to consider between two <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets with the same schema. In the special cases of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets that correspond to the categories of sets and directed graphs, the notion of a <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set homomorphism lines up precisely with the notions of function and graph homomorphism, respectively. Viewing <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets as databases, these morphisms also correspond to database homomorphisms as studied in the literature.</p>
<p>At a high level, a morphism <img src="https://latex.codecogs.com/png.latex?I%5Crightarrow%20J"> is a particular way of locating <img src="https://latex.codecogs.com/png.latex?I"> <em>within</em> <img src="https://latex.codecogs.com/png.latex?J">. If a morphism exists, it is like saying there is a match of pattern <img src="https://latex.codecogs.com/png.latex?I"> within <img src="https://latex.codecogs.com/png.latex?J">, and the morphism itself contains the data for how to locate <img src="https://latex.codecogs.com/png.latex?I">. Elements of <img src="https://latex.codecogs.com/png.latex?I"> may be merged together when located within <img src="https://latex.codecogs.com/png.latex?J">, but connections may never be split apart. Consider the following visualizations of two <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets with schema <img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Bond%7D%20%5Coverset%7Bb_1%7D%7B%5Cunderset%7Bb_2%7D%7B%5Crightrightarrows%7D%7D%20%7B%5Crm%20Atom%7D%20%5Cxrightarrow%7Bmol%7D%20%7B%5Crm%20Molecule%7D">.<sup>2</sup></p>
<p><img src="https://blog.algebraicjulia.org/post/2022/06/chase/twocsets.png" class="img-fluid"></p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab.Theories</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab.CategoricalAlgebra</span></span>
<span id="cb1-2"></span>
<span id="cb1-3"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@present</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SchChem</span>(FreeSchema) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb1-4">  (Molecule, Atom, Bond)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span></span>
<span id="cb1-5">  (b₁, b₂)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(Bond, Atom)</span>
<span id="cb1-6">  mol<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(Atom, Molecule)</span>
<span id="cb1-7"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb1-8"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@acset_type</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Chem</span>(SchChem)</span>
<span id="cb1-9"></span>
<span id="cb1-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Initialize empty C-sets</span></span>
<span id="cb1-11">c₁, c₂, monotomic, diatomic, triatomic  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Chem</span>() for _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>]</span>
<span id="cb1-12">mols <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [monotomic, diatomic, triatomic]</span>
<span id="cb1-13"></span>
<span id="cb1-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Create 1, 2, and 3 atom molecules</span></span>
<span id="cb1-15">[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_part!</span>(x, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>Molecule) for x <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> mols]</span>
<span id="cb1-16">[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_parts!</span>(x, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>Atom, i, mol<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) for (i, x) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">enumerate</span>(mols)]</span>
<span id="cb1-17"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_parts!</span>(diatomic, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>Bond, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, b₁<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>], b₂<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])</span>
<span id="cb1-18"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_parts!</span>(triatomic, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>Bond, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>, b₁<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>], b₂<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>])</span>
<span id="cb1-19"></span>
<span id="cb1-20"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Create the left C-set</span></span>
<span id="cb1-21">[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">copy_parts!</span>(c₁, diatomic) for _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]</span>
<span id="cb1-22"></span>
<span id="cb1-23"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Create the right C-set</span></span>
<span id="cb1-24">[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">copy_parts!</span>(c₂, x) for x <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> [triatomic, monotomic]]</span></code></pre></div>
<p>There are <img src="https://latex.codecogs.com/png.latex?(3%5Ccdot%202)%5E2=36"> homomorphisms<sup>3</sup> from the left <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set (domain) to the right (codomain), one of which is indicated by coloring here:</p>
<p><img src="https://blog.algebraicjulia.org/post/2022/06/chase/yesmorphism.png" class="img-fluid"></p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb2-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@assert</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">homomorphisms</span>(c₁, c₂)) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">36</span></span></code></pre></div>
<p>However, there is no homomorphism in the opposite direction. If we try to do this, we find that we require for there to be an atom with a bond to itself in the domain (otherwise, there is nowhere to send B₃₄ that satisfies the homomorphism constraint).</p>
<p><img src="https://blog.algebraicjulia.org/post/2022/06/chase/nomorphism.png" class="img-fluid"></p>
<div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb3-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@assert</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">homomorphisms</span>(c₂, c₁)) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span></code></pre></div>
<p>If there exists a homomorphism from <img src="https://latex.codecogs.com/png.latex?I"> to <img src="https://latex.codecogs.com/png.latex?J">, one might say that <img src="https://latex.codecogs.com/png.latex?I"> can be interpreted within <img src="https://latex.codecogs.com/png.latex?J">. For this reason, the binary relation <img src="https://latex.codecogs.com/png.latex?I%20%5Crightarrow%20J"> (that there exists some homomorphism from <img src="https://latex.codecogs.com/png.latex?I"> to <img src="https://latex.codecogs.com/png.latex?J">) is crucial in defining a notion of a “best” or “closest” <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set instance, in the context of data repair: we want to consider all databases which can both interpret our starting instance (all <img src="https://latex.codecogs.com/png.latex?J">’s for which <img src="https://latex.codecogs.com/png.latex?I%20%5Crightarrow%20J">) as well as satisfy <img src="https://latex.codecogs.com/png.latex?%5CSigma">. Call this set of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets <img src="https://latex.codecogs.com/png.latex?J_%5CSigma">. Which element <img src="https://latex.codecogs.com/png.latex?U%20%5Cin%20J_%5CSigma"> is the <em>universal</em> (or best) one, if any? It would have to be one such that, for all <img src="https://latex.codecogs.com/png.latex?J%20%5Cin%20J_%5CSigma">, it is also the case that <img src="https://latex.codecogs.com/png.latex?U%20%5Crightarrow%20J">. Put another way, <img src="https://latex.codecogs.com/png.latex?U"> is the minimal way of getting <img src="https://latex.codecogs.com/png.latex?I"> to satisfy <img src="https://latex.codecogs.com/png.latex?%5CSigma">: <em>any</em> modification to <img src="https://latex.codecogs.com/png.latex?I"> to make it satisfy <img src="https://latex.codecogs.com/png.latex?%5CSigma"> will have to make <em>at least</em> the modifications one makes to get <img src="https://latex.codecogs.com/png.latex?U">.</p>
<p><img src="https://blog.algebraicjulia.org/post/2022/06/chase/universal.png" class="img-fluid"></p>
<p>As an example, consider the instance on the far left below that doesn’t adhere to the original constraints we provided (notably, this means we must draw bonds as directed):</p>
<p><img src="https://blog.algebraicjulia.org/post/2022/06/chase/repair.png" class="img-fluid"></p>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb4-1">I <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Chem</span>()</span>
<span id="cb4-2">[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">copy_parts!</span>(I, monotomic) for _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]</span>
<span id="cb4-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_part!</span>(I, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>Bond, b₁<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, b₂<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb4-4"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@assert</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nparts</span>(I, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>Atom) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb4-5"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@assert</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nparts</span>(I, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>Bond) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb4-6"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@assert</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nparts</span>(I, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>Molecule) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb4-7"></span>
<span id="cb4-8">U <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">chase</span>(I, Σ) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Σ will be described in the following section</span></span>
<span id="cb4-9"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@assert</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nparts</span>(U, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>Atom) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb4-10"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@assert</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nparts</span>(U, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>Bond) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb4-11"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@assert</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nparts</span>(U, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>Molecule) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span></code></pre></div>
<p>Chasing the original instance with the symmetry rule produces the first homomorphism, and then further chasing that result with our second rule (that states bonded atoms are in the same molecule) produces the second homomorphism. Although we could push further with homomorphisms (e.g.&nbsp;merging the two atoms together, embedding this molecule in the context of other molecules), those further transformations would not be <em>universal</em> with respect to the original instance and <img src="https://latex.codecogs.com/png.latex?%5CSigma">.</p>
</section>
<section id="regular-logic-the-logic-of-mathsfc-set-homomorphisms" class="level2">
<h2 class="anchored" data-anchor-id="regular-logic-the-logic-of-mathsfc-set-homomorphisms">Regular logic: the logic of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set homomorphisms</h2>
<p>We cannot put arbitrary logical expressions as constraints for the chase. Rather, we are limited to expressions of the form <img src="https://latex.codecogs.com/png.latex?%7B%5Cforall%20x,%20%5Cphi(x)%20%5Cimplies%20%5Cpsi(x)%7D">, where <img src="https://latex.codecogs.com/png.latex?%5Cphi"> and <img src="https://latex.codecogs.com/png.latex?%5Cpsi"> can contain <img src="https://latex.codecogs.com/png.latex?%5Ctop">, <img src="https://latex.codecogs.com/png.latex?%5Cland">, <img src="https://latex.codecogs.com/png.latex?%5Cexists">, <img src="https://latex.codecogs.com/png.latex?=">, and atomic formulas. This is called <a href="https://ncatlab.org/nlab/show/regular+logic">regular logic</a> <sup>4</sup>. Interestingly, these are precisely the constraints which can be encoded as homomorphisms between a source <img src="https://latex.codecogs.com/png.latex?S"> and target <img src="https://latex.codecogs.com/png.latex?T">, as we have only the ability to merge things together (with <img src="https://latex.codecogs.com/png.latex?=">) or to add new things (with <img src="https://latex.codecogs.com/png.latex?%5Cexists">), which are the restrictions we have with homomorphisms. To demonstrate this correspondance, we will show five constraints expressed as logical formulas as well as homomorphisms.</p>
<section id="there-exists-at-least-one-atom" class="level3">
<h3 class="anchored" data-anchor-id="there-exists-at-least-one-atom">There exists at least one atom</h3>
<ul>
<li>Our formula is: <img src="https://latex.codecogs.com/png.latex?%5Ctop%20%5Cimplies%20%5Cexists%20m%20%5Cin%20%7B%5Crm%20Molecule%7D"> <img src="https://blog.algebraicjulia.org/post/2022/06/chase/atleastonemol.png" class="img-fluid"></li>
</ul>
</section>
<section id="there-exists-no-more-than-one-molecule" class="level3">
<h3 class="anchored" data-anchor-id="there-exists-no-more-than-one-molecule">There exists no more than one molecule</h3>
<ul>
<li>Our formula is: <img src="https://latex.codecogs.com/png.latex?%5Cforall%20m_1,m_2%20%5Cin%20%7B%5Crm%20Molecule%7D,%20%5Ctop%20%5Cimplies%20m_1=m_2"> <img src="https://blog.algebraicjulia.org/post/2022/06/chase/onemol.png" class="img-fluid"></li>
</ul>
</section>
<section id="the-bondpair-morphism-is-injective" class="level3">
<h3 class="anchored" data-anchor-id="the-bondpair-morphism-is-injective">The <img src="https://latex.codecogs.com/png.latex?bondpair"> morphism is injective</h3>
<ul>
<li>Let us temporarily add to the schema and say there is a functional relationship <img src="https://latex.codecogs.com/png.latex?%7Bbondpair:%20%7B%5Crm%20Bond%7D%20%5Crightarrow%20%7B%5Crm%20Bond%7D%7D"> which points from any bond <img src="https://latex.codecogs.com/png.latex?x%20%5Crightarrow%20y"> to its symmetric dual <img src="https://latex.codecogs.com/png.latex?y%5Crightarrow%20x">.</li>
<li>We can prevent atoms being <a href="https://en.wikipedia.org/wiki/Dangling_bond">bonded to themselves</a> by asserting that this is injective.</li>
<li>The formula that asserts that <img src="https://latex.codecogs.com/png.latex?bondpair"> is injective is: <img src="https://latex.codecogs.com/png.latex?%7B%5Cforall%20b_1,b_2%20%5Cin%20%7B%5Crm%20Bond%7D,%20bondpair(b_1)=bondpair(b_2)%20%5Cimplies%20b_1=b_2%7D"> <img src="https://blog.algebraicjulia.org/post/2022/06/chase/inj.png" class="img-fluid"></li>
</ul>
</section>
<section id="the-bondpair-morphism-is-surjective" class="level3">
<h3 class="anchored" data-anchor-id="the-bondpair-morphism-is-surjective">The <img src="https://latex.codecogs.com/png.latex?bondpair"> morphism is surjective</h3>
<ul>
<li>Our formula is: <img src="https://latex.codecogs.com/png.latex?%7B%5Cforall%20b%20%5Cin%20%7B%5Crm%20Bond%7D,%20%5Ctop%20%5Cimplies%20%5Cexists%20b'%20%5Cin%20%7B%5Crm%20Bond%7D,%5C%20%20bondpair(b')=b%7D"> <img src="https://blog.algebraicjulia.org/post/2022/06/chase/surj.png" class="img-fluid"></li>
</ul>
</section>
<section id="the-rm-selfbond-object-is-a-limit" class="level3">
<h3 class="anchored" data-anchor-id="the-rm-selfbond-object-is-a-limit">The <img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Selfbond%7D"> object is a limit</h3>
<ul>
<li>Again, we temporarily add to the schema an entity <img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Selfbond%7D"> whose <em>meaning</em> is to identify all of the elements of <img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Bond%7D"> that have the same source and target.</li>
<li>The <em>structure</em> is an entity with one functional relationship <img src="https://latex.codecogs.com/png.latex?sb:%20%7B%5Crm%20Selfbond%7D%20%5Crightarrow%20%7B%5Crm%20Bond%7D"></li>
<li>The <em>property</em> is <img src="https://latex.codecogs.com/png.latex?%5Cforall%20b%20%5Cin%20%7B%5Crm%20Bond%7D,%5C%20bond%E2%82%81(b)=bond%E2%82%82(b)%20%5Cimplies%20%5Cexists%20s%20%E2%88%88%20%7B%5Crm%20Selfbond%7D,%5C%20sb(s)=b"></li>
<li>Visually, each element of <img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Selfbond%7D"> will be a square and the bond that it picks out as a self bond will be indicated with an arrow labeled <img src="https://latex.codecogs.com/png.latex?sb">.</li>
<li>Once we further constrain <img src="https://latex.codecogs.com/png.latex?sb"> to be injective, <img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Selfbond%7D"> becomes a <a href="https://ncatlab.org/nlab/show/limit">limit</a> for the diagram of a bond with the same source and target. <img src="https://blog.algebraicjulia.org/post/2022/06/chase/pullb.png" class="img-fluid"></li>
</ul>
<p>This correspondance is not a mere curiosity, as it has rather practical consequences. The language of the constraints can be implemented in the language of the model, so a chemist can express their knowledge in terms of molecules and atoms rather than adding a new flavor of logic to their vocabulary. More profoundly, although expressing knowledge in a logical syntax is incredibly powerful and general, this actually makes it <em>harder</em> to reason about and more challenging to process in an automatic way. When the same information is encoded in combinatorial (or graph-like) data, we can easily perform analyses and manipulations that are not feasible to automate for arbitrary logical formulas, mathematical expressions, or code. Some example manipulations: 1.) if the <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D"> of our <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets changes because our model of the world updates, functorial data migration can faithfully migrate constraints into our new perspective when they are expressed as morphisms, 2.) the morphism representation is more clearly visualizable, further raising the accessibility and transparency of constraints as well as making a GUI for constraints possible, 3.) as will be discussed in the next section, the chase algorithm itself can be implemented in a few lines of code when thinking of constraints as morphisms, whereas it is a tedious and error-prone process to implement when working with the syntax of logical formulas.</p>
</section>
</section>
<section id="mathematical-specification-how-the-chase-works" class="level2">
<h2 class="anchored" data-anchor-id="mathematical-specification-how-the-chase-works">Mathematical specification: how the chase works</h2>
<p>In the database literature, logical constraints are known as “embedded dependencies” (EDs). Viewed as homomorphisms <img src="https://latex.codecogs.com/png.latex?S%20%5Crightarrow%20T">, each ED’s domain <img src="https://latex.codecogs.com/png.latex?S"> is thought of as a potential <em>trigger</em>: it is a pattern that, if matched, obligates us to do something in order to be consistent with the constraint (either merging elements together or adding new elements). If the work to be done has not yet been done, we call the trigger <em>active</em>. At a high level, then, the chase merely scans for triggers, and ‘fires’ the active triggers to update the database. This process continues iteratively until there are no active triggers, if it terminates at all.</p>
<p><img src="https://blog.algebraicjulia.org/post/2022/06/chase/meme.png" class="img-fluid"></p>
<p>One strategy for computing the chase derives from Quillen’s small object argument, which is a general strategy for solving <em>lifting problems</em>, of which the chase is a special case. Given a trigger <img src="https://latex.codecogs.com/png.latex?S%20%5Crightarrow%20I">, whether or not it is active depends on whether or not there exists a homomorphism <img src="https://latex.codecogs.com/png.latex?T%5Crightarrow%20I"> that makes the following triangle commute:</p>
<!-- https://q.uiver.app/?q=WzAsMyxbMCwwLCJTIl0sWzAsMSwiVCJdLFsxLDAsIkkiXSxbMCwxLCJFRCIsMl0sWzEsMiwiPyIsMix7InN0eWxlIjp7ImJvZHkiOnsibmFtZSI6ImRhc2hlZCJ9fX1dLFswLDIsIm1hdGNoIl1d -->
<p><img src="https://blog.algebraicjulia.org/post/2022/06/chase/match.png" class="img-fluid"></p>
<p>Our goal is to make the triangle commute and assume no more than necessary to make this happen; this corresponds to a categorical operation called a <em>pushout</em>, which produces the best possible <img src="https://latex.codecogs.com/png.latex?I'"> for which the trigger will no longer be active; however, the new material in <img src="https://latex.codecogs.com/png.latex?I'"> may have activated other triggers which then need to be fired. Thus, the chase can be implemented as an iteration of chase steps, each of which has the following sequence: 1. Compute <em>all</em> triggers of all dependencies, filtering the inactive triggers 2. Terminate the chase, if no triggers are active. 3. Construct maps from union of active triggers into the current database instance as well as into the union of trigger codomains. 4. Construct the next database instance via pushout.</p>
<p>Pushouts are a type of colimit that generalize unions of sets, providing a notion of “gluing pieces together along a common interface”. In this case, the interface is the top left corner of the square, which is used to connect the current database to the consequents of all triggers that fired in order to yield the next iteration of the database.</p>
<!-- https://q.uiver.app/?q=WzAsNCxbMCwwLCJcXHN1bVxcIFMiXSxbMCwxLCJcXHN1bVxcIFQiXSxbMSwwLCJJX24iXSxbMSwxLCJJX3tuKzF9Il0sWzEsMywiIiwwLHsic3R5bGUiOnsiYm9keSI6eyJuYW1lIjoiZG90dGVkIn19fV0sWzIsMywiIiwyLHsic3R5bGUiOnsiYm9keSI6eyJuYW1lIjoiZG90dGVkIn19fV0sWzAsMV0sWzAsMl1d -->
<p><img src="https://blog.algebraicjulia.org/post/2022/06/chase/push.png" class="img-fluid"></p>
<p>Given Catlab’s preexisting implementations for homomorphism finding and colimits, the code required to implement the chase matches closely to the mathematics.</p>
</section>
</section>
<section id="applications" class="level1">
<h1>Applications</h1>
<section id="ologs" class="level2">
<h2 class="anchored" data-anchor-id="ologs">Ologs</h2>
<p>In scientific practice, data is usually recorded, whereas <em>knowledge</em> that ties data together and contextualizes it is consistently represented only informally through documentation, publications, file names, or within the behavior of obscure code. Ologs are a model of explicit knowledge representation that can be viewed in many ways (as database schemas, as ontologies, as categories). It is worthwhile to consider the pros and cons of adding formality to one’s knowledge representation. Cons are generally related to the tedium of constructing and maintaining the representation over time, whereas the pros are related to the sorts of knowledge-based tasks that can be automated in virtue of the formalization.</p>
<p>For example, we ask questions such as “Which reactions in my reaction network rapidly produce some molecule with a carboxyl group, according to all of the simulation software we’ve tested so far?”. How do we represent the procedure which retrieves this information? A benefit of formally-structured knowledge is that this this procedure can be written in a declarative query language, which is much more interpretable than the alternative if the data were informally distributed throughout a file system. In that case, the ‘query’ would likely be an imperative function in a scripting language - this is adequate only when limited to personal use and low-complexity scenarios.</p>
<p>Let’s consider a specific example that extends the schema of molecules we saw earlier into a much larger olog of simulations of chemical kinetics. Below the dotted line we give examples of elements that might live in the sets corresponding to each type in the schema. The internal triangles and squares all happen to commute, emphasized by the green checkmarks.</p>
<p><img src="https://blog.algebraicjulia.org/post/2022/06/chase/olog.png" class="img-fluid"></p>
<p>Many subtle distinctions were made at the discretion of the author of this olog, such as H<img src="https://latex.codecogs.com/png.latex?_2"> considered as a part of a particular reaction (has a well-defined coefficient, but doesn’t have a well-defined concentration) vs H<img src="https://latex.codecogs.com/png.latex?_2"> considered as a species that appears somewhere in a chemical reaction network that has been simulated (well-defined concentration, no well-defined coefficient).</p>
<p>The pullback constraint in the upper right corner insists that there is precisely one reaction rate corresponding to each pair of a simulation and reaction that appears in that simulation. More complicated constraints can be built from these building blocks, and the explicit (i.e.&nbsp;machine enforceable, via the chase as described above) nature of these constraints is powerful. This means that if one were to add a new simulation for reaction network <strong>Rxns</strong>, we can automatically add elements to the reaction rate table with their foreign keys correctly filled out. It also means we can be automatically notified of a conflict if there are two reaction rates for the same reaction and simulation pair.</p>
<p>Here, the chase is alleviating the general formalized knowledge problem of a scientist who is afraid to interact with their model out of fear of invalidating some subtle or intricate assumptions. As AlgebraicJulia continues to build tools to facilitate working with categories and leveraging them for scientific computing, the pros of formalization become stronger and cons become weaker.</p>
</section>
<section id="model-enumeration" class="level2">
<h2 class="anchored" data-anchor-id="model-enumeration">Model enumeration</h2>
<p>Model enumeration computes queries of the form “Show me all Petri nets up to such-and-such size” or “Show me all molecules up to such-and-such size”. This can be difficult when there are many equations at play: enumerating all <em>groups</em> of order 10 is difficult if we want to be more efficient than filtering a list with <img src="https://latex.codecogs.com/png.latex?10%5E%7B100%7D"> possible binary functions (after all, there are only two such groups, <img src="https://latex.codecogs.com/png.latex?D_%7B10%7D"> and <img src="https://latex.codecogs.com/png.latex?C_%7B10%7D">). Why might we be interested in such queries? - Gaining evidence for a conjecture by showing it holds for <em>all</em> cases up to a fixed size. - Finding a counterexample in the context of property-based software test suites - Gaining intuition of complex structures through their simplest <em>nontrivial</em> examples. (e.g.&nbsp;the five simplest <a href="https://ncatlab.org/nlab/show/Kan+extension">Kan extensions</a>) - Exploring scientific model spaces: finding a model that best fits some data within a logically-constrained space.</p>
<p>By modifying one aspect of the chase, we can obtain an algorithm for model enumeration. In order for the instance <img src="https://latex.codecogs.com/png.latex?U"> that the chase computes to be universal, when functional relationships force us to introduce a new object, it must be completely unconstrained. For example, if we fire an ED that introduces a new <img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Bond%7D">, then the fact that <img src="https://latex.codecogs.com/png.latex?b_1,b_2"> are functional relationships to <img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Atom%7D"> means that there are two additional atoms that must be added, too. Normally, we pick fresh IDs for these atoms (<img src="https://latex.codecogs.com/png.latex?(n+1,%20n+2)">, if there are <img src="https://latex.codecogs.com/png.latex?n"> atoms already). During model enumeration, we can also consider <img src="https://latex.codecogs.com/png.latex?(n+1)%5E2"> other possibilities, where we try all <img src="https://latex.codecogs.com/png.latex?%5C%7B(i,j)%5C%20%7C%5C%201%20%5Cleq%20i,j%20%5Cleq%20n+1%5C%7D">. Some of these new choices will <em>not</em> satisfy the axioms we seek to satisfy, but future chase steps will work towards correcting these. Ultimately, although we are searching through a combinatorial space of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets (which are merely <em>premodels</em> with no notion of EDs), the fact we are using the chase to navigate this space allows us to spend effort finding models rather than enumerating the much larger set of premodels.</p>
<table class="caption-top table">
<colgroup>
<col style="width: 55%">
<col style="width: 7%">
<col style="width: 7%">
<col style="width: 8%">
<col style="width: 10%">
<col style="width: 10%">
</colgroup>
<thead>
<tr class="header">
<th><strong>Semigroup order</strong></th>
<th style="text-align: center;"><strong>1</strong></th>
<th style="text-align: center;"><strong>2</strong></th>
<th style="text-align: center;"><strong>3</strong></th>
<th style="text-align: center;"><strong>4</strong></th>
<th style="text-align: center;"><strong>5</strong></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td># of binary operations</td>
<td style="text-align: center;">1</td>
<td style="text-align: center;">16</td>
<td style="text-align: center;">19,683</td>
<td style="text-align: center;">4.3×10⁹</td>
<td style="text-align: center;">3.0×10¹⁷</td>
</tr>
<tr class="even">
<td># of semigroups</td>
<td style="text-align: center;">1</td>
<td style="text-align: center;">8</td>
<td style="text-align: center;">113</td>
<td style="text-align: center;">3,492</td>
<td style="text-align: center;">183,732</td>
</tr>
<tr class="odd">
<td># of semigroups (up to isomorphism)</td>
<td style="text-align: center;">1</td>
<td style="text-align: center;">5</td>
<td style="text-align: center;">24</td>
<td style="text-align: center;">188</td>
<td style="text-align: center;">1,915</td>
</tr>
<tr class="even">
<td># of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets explored to enumerate them all</td>
<td style="text-align: center;">1</td>
<td style="text-align: center;">7</td>
<td style="text-align: center;">399</td>
<td style="text-align: center;">6,420</td>
<td style="text-align: center;">109,151</td>
</tr>
</tbody>
</table>
<p>This preliminary data from our unoptimized <a href="https://github.com/kris-brown/ModelEnumeration.jl">prototype implementation</a> shows that search space of possible <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets can be massively pruned using this modified chase. Being able to work with <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets <a href="https://www.algebraicjulia.org/blog/post/2022/01/cset-automorphisms/">up to isomorphism</a> is essential for this strategy to avoid duplicating work.</p>
</section>
</section>
<section id="conclusion" class="level1">
<h1>Conclusion</h1>
<p>Regular logic is both a computationally simple and yet expressive subset of first order logic. It is deeply connected to <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set homomorphisms, allowing us to perform the chase in a broad array of modeling settings and to represent properties of our models as transparent combinatorial data.</p>
<p>Many scientists do not presently work with formal representations for their models of their domain, opting for a mix of text files, Python scripts, and spreadsheets distributed through a filesystem, only linked into a coherent whole within the mind of the scientist. This can be convenient for the individual, but, at a larger scale, science benefits from these <a href="https://topos.institute/model-based-computing">models being explicit</a>. This can be challenging work, thus there is no incentive for scientists to do this without tooling that allows individuals to reap benefits from this work investment. An important step along this path involves allowing scientists to take their formally-stated properties computationally and make them tractable to enforce.</p>



</section>


<div id="quarto-appendix" class="default"><section class="quarto-appendix-contents" id="quarto-bibliography"><h2 class="anchored quarto-appendix-heading">References</h2><div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="0">
<div id="ref-benedikt2017" class="csl-entry">
Benedikt, Michael, George Konstantinidis, Giansalvatore Mecca, Boris Motik, Paolo Papotti, Donatello Santoro, and Efthymia Tsamoura. 2017. <span>“Benchmarking the Chase.”</span> In <em>Proceedings of the 36th <span>ACM</span> <span>SIGMOD</span>-<span>SIGACT</span>-<span>SIGAI</span> Symposium on Principles of Database Systems</em>. <span>ACM</span>. <a href="https://doi.org/10.1145/3034786.3034796">https://doi.org/10.1145/3034786.3034796</a>.
</div>
<div id="ref-2012.01847" class="csl-entry">
Bonchi, Filippo, Fabio Gadducci, Aleks Kissinger, Pawel Sobocinski, and Fabio Zanasi. 2020. <span>“String Diagram Rewrite Theory i: Rewriting with Frobenius Structure.”</span>
</div>
<div id="ref-spivak2012" class="csl-entry">
Spivak, David I., and Robert E. Kent. 2012. <span>“Ologs: A Categorical Framework for Knowledge Representation.”</span> Edited by Chris Mavergames. <em><span>PLoS</span> <span>ONE</span></em> 7 (1): e24274. <a href="https://doi.org/10.1371/journal.pone.0024274">https://doi.org/10.1371/journal.pone.0024274</a>.
</div>
</div></section><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>

<ol>
<li id="fn1"><p>Databases with attributes, such as <code>String</code> for <code>Float</code>-valued columns, are represented as <a href="https://www.algebraicjulia.org/blog/post/2020/10/acset-theory/">attributed <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets</a>. These are not covered in this post.↩︎</p></li>
<li id="fn2"><p>Because these bonds are symmetric, for brevity we can visually represent them as undirected.↩︎</p></li>
<li id="fn3"><p><img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Atom%7D"> 1 has three choices where to go (it is forced to go to <img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Molecule%7D"> 1 in the codomain) and for each of these choices, there are two choices for <img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Atom%7D"> 3. Each molecule in the domain is matched independently, thus the total number of morphisms will be the square of matching a single molecule.↩︎</p></li>
<li id="fn4"><p>This has limitations: we do not have the ability to state that bonds must occur between <em>different</em> atoms: <img src="https://latex.codecogs.com/png.latex?%7B%5Cforall%20b%20%5Cin%20%7B%5Crm%20Bond%7D,%5C%20bond_1(b)%20%5Cne%20bond_2(b)%7D">. Beyond inequalities, disjunctions are also not directly expressible. There is a computational justification for this limitation: if two things are <em>not</em> equal, it isn’t clear which one needs to change (and what it should change to). Likewise, if we merely know we must assign a value of <img src="https://latex.codecogs.com/png.latex?x"> <em>or</em> <img src="https://latex.codecogs.com/png.latex?y"> to something, we don’t have a straightforward automatic procedure that can pick which one we should use.↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>c-sets</category>
  <category>databases</category>
  <category>logic</category>
  <guid>https://blog.algebraicjulia.org/post/2022/06/chase/</guid>
  <pubDate>Thu, 30 Jun 2022 00:00:00 GMT</pubDate>
  <media:content url="https://blog.algebraicjulia.org/post/2022/06/chase/meme.png" medium="image" type="image/png" height="93" width="144"/>
</item>
<item>
  <title>Equality vs equivalence: computing isomorphism classes of C-sets</title>
  <dc:creator>Kris Brown</dc:creator>
  <link>https://blog.algebraicjulia.org/post/2022/01/cset-automorphisms/</link>
  <description><![CDATA[ 





<div class="hidden">
<p>$$ <!-- Number systems --> </p>
<!-- Categories -->
<!-- Graphs -->
<!-- Double categories -->
<!-- Acsets -->
<!-- Wiring diagrams -->
<!-- Dynamical systems -->
<p>$$</p>
</div>
<p>When is one thing equivalent to another? It turns out that answering this depends on a <em>context</em>, in some informal sense. Category theory offers a language by which this can be made precise, which has implications for a variety of technical challenges encountered in scientific computing.</p>
<p>Familiarity with <a href="https://www.algebraicjulia.org/blog/tag/c-sets/">C-sets</a> in <a href="(https://github.com/AlgebraicJulia/Catlab.jl)">Catlab</a> is helpful for understanding technical aspects later on in the post; however, readers new to AlgebraicJulia will benefit from reading about the motivation, the problem of graph equivalence, and the concluding thoughts.</p>
<section id="motivation" class="level1">
<h1>Motivation</h1>
<p>A common feature of both everyday conversation and esoteric arguments is the negotiation of whether or not two things can be called ‘the same’. These arguments are often fundamentally confused because it is difficult to be explicit about what we mean by ‘the same’. Consider these examples: - If Alice is in a political argument against Bob, she can charge Bob with hypocrisy for endorsing the <em>same</em> action as one he has previously condemned. Bob will then have to make a distinction (e.g.&nbsp;“that action is <em>different</em> in the context of miltary conflict!”), and the argument progresses from there. Likewise, Alice can defend herself by claiming her action is the <em>same</em> as that which Bob has previously endorsed. - Many debates are secretly about how to treat context: an artist taking a <a href="https://en.wikipedia.org/wiki/Classificatory_disputes_about_art#Generalized_definitions_of_art">urinal or a Brillo soap box</a> and presenting it <em>as art</em> will provoke controversy, given that one could argue that we have the <em>same</em> objects in our bathrooms (yet those are clearly not art). Likewise, one could argue about whether a novel written today that is word-for-word identical to <em>Don Quixote</em> could actually be a truly <a href="https://en.wikipedia.org/wiki/Pierre_Menard,_Author_of_the_Quixote"><em>different</em></a> work of art. And one could argue about whether a novel that is word-for-word identical to a meaningful work like <em>Hamlet</em> could actually be meaningless, in the context of a <a href="https://en.wikipedia.org/wiki/The_Library_of_Babel">library</a> that contains <em>every possible</em> book. - Does the Star Trek <a href="https://en.wikipedia.org/wiki/Teletransportation_paradox">teleporter</a> kill you? Is <a href="https://en.wikipedia.org/wiki/Ship_of_Theseus">Theseus’ ship</a> the same ship as before? It turns out questions of sameness and difference are also closely related to questions of <em>identity</em>: we often assert an identity of an object (e.g.&nbsp;a rock, <a href="https://en.wikipedia.org/wiki/Heraclitus#The_River">a river</a>, ourselves) across different moments in time, but we’re then forced to awkwardly say two things are “the same, but different”. This awkwardness and the ensuing confusion is the price paid in exchange for the brevity, clarity, and convenience we often gain by treating an equivalence relation <em>as if</em> it were an identity relation.</p>
<p>We also suffer when we are not explicit about what we mean by ‘the same’ while programming:</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb1-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">mutable struct</span> Color</span>
<span id="cb1-2">  name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">String</span></span>
<span id="cb1-3">  wavelength<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span></span>
<span id="cb1-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb1-5"></span>
<span id="cb1-6">my_blue  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Color</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"blue"</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">470</span>)</span>
<span id="cb1-7">my_green <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Color</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"green"</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">530</span>)</span>
<span id="cb1-8">my_blue <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> my_green <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># returns "false", as expected</span></span>
<span id="cb1-9"></span>
<span id="cb1-10">your_blue <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Color</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"blue"</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">470</span>)</span>
<span id="cb1-11">my_blue <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> your_blue <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># returns "false"!</span></span></code></pre></div>
<p>The computer is not taking a philosophical stance, but rather it was asked to tell whether two things were equal without being told <em>how</em> to compute this. It guessed, using a default <code>==</code> method that is unsatisfactory for our use case. Given that we actually <em>would</em> like to say these two blues are the same, we can manually define an equality test method to improve things:</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Ask yourself: is this reasonable?</span></span>
<span id="cb2-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Base</span>.<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span>)(x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Color</span>, y<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Color</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> x.wavelength <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> y.wavelength</span>
<span id="cb2-3"></span>
<span id="cb2-4">my_blue <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> your_blue <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># now returns "true" as desired</span></span>
<span id="cb2-5"></span>
<span id="cb2-6">aqua <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Color</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"aqua"</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>)</span>
<span id="cb2-7">cyan <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Color</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cyan"</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>)</span>
<span id="cb2-8">cyan <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> aqua <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># returns "true", but should it?</span></span>
<span id="cb2-9"></span>
<span id="cb2-10">grue <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Color</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"grue"</span>, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (CURRENT_YEAR <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2100</span>) <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">530</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">470</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span>)</span>
<span id="cb2-11">grue <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> my_green <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># returns "true", but should it?</span></span></code></pre></div>
<p>So even in technical situations, whether or not two entities are equal can be nebulous. The dilemma is this: providing explicit <code>==</code> algorithms is often undesirable because it feels tedious and mechanical, like something that <em>should</em> be automated; however, there is no unopinionated way to pick a default looking at the data alone. A solution to this dilemma is make it convenient to work with data <em>alongside</em> their contexts, which provide enough information for sameness to be determined algorithmically. Namely, when an entity is regarded as the object of a <em>category</em>, we obtain a formal notion of <em>equivalence</em> that, in many scenarios, captures what we intend by the <code>==</code> operator.<sup>1</sup></p>
<p>In <a href="https://github.com/AlgebraicJulia/Catlab.jl">Catlab.jl</a>, we use a data structure called an <a href="https://arxiv.org/abs/2106.04703">attributed C-set</a> (or ACSet) to manipulate data that is situated within a category. This generalizes a broad class of data structures, including many generalizations of graphs (e.g.&nbsp;<a href="https://www.algebraicjulia.org/blog/post/2020/09/cset-graphs-1/">directed</a>, <a href="https://www.algebraicjulia.org/blog/post/2020/09/cset-graphs-2">symmetric</a>, <a href="https://www.algebraicjulia.org/blog/post/2021/04/cset-graphs-3/">reflexive</a>), tabular data (e.g.&nbsp;<a href="https://pandas.pydata.org/pandas-docs/stable/user_guide/dsintro.html">data frames</a>), and combinations of the two (e.g.&nbsp;weighted graphs, <a href="https://en.wikiversity.org/wiki/Relational_Databases/Introduction">relational databases</a>). Here, we’ll discuss the benefits of working with <em>isomorphism classes</em> of ACSets, i.e.&nbsp;ACSets <a href="https://www.math3ma.com/blog/up-to-isomorphism">up to isomorphism</a>. A working implementation of the code presented below can be found at <a href="https://github.com/AlgebraicJulia/CSetAutomorphisms.jl">CSetAutomorphisms.jl</a>.</p>
<section id="equality-vs-equivalence-graphs" class="level2">
<h2 class="anchored" data-anchor-id="equality-vs-equivalence-graphs">Equality vs equivalence: graphs</h2>
<p>A key insight of modern mathematics is that equality is often more strict of a notion than what we want in practice. When reasoning about complex mathematical structures we need to shift our perspective to <em>interchangeable in this context</em>. Let’s consider directed graphs as an example:</p>
<!-- https://q.uiver.app/?q=WzAsMTcsWzAsMCwiXFxib3hlZHsxfSIsWzI0MCw2MCw2MCwxXV0sWzIsMCwiXFxib3hlZHs0fSIsWzAsNjAsNjAsMV1dLFswLDEsIlxcYm94ZWR7Mn0iLFszMDAsNjAsNjAsMV1dLFsyLDEsIlxcYm94ZWR7M30iLFsxMjAsNjAsNjAsMV1dLFs1LDAsIlxcYm94ZWR7Mn0iLFszMDAsNjAsNjAsMV1dLFs0LDEsIlxcYm94ZWR7MX0iLFsyNDAsNjAsNjAsMV1dLFs2LDAsIlxcYm94ZWR7NH0iLFswLDYwLDYwLDFdXSxbNiwxLCJcXGJveGVkezN9IixbMTIwLDYwLDYwLDFdXSxbNCwzLCJcXGJ1bGxldCJdLFswLDIsIlxcYnVsbGV0Il0sWzAsMywiXFxidWxsZXQiXSxbMiwzLCJcXGJ1bGxldCJdLFsyLDIsIlxcYnVsbGV0Il0sWzUsMiwiXFxidWxsZXQiXSxbNiwzLCJcXGJ1bGxldCJdLFs2LDIsIlxcYnVsbGV0Il0sWzQsMF0sWzAsMywiXFxmb290bm90ZXNpemUgMS0zIiwwLHsibGFiZWxfcG9zaXRpb24iOjEwfV0sWzMsMSwiXFxmb290bm90ZXNpemUgMy00IiwyXSxbMSwyLCJcXGZvb3Rub3Rlc2l6ZSA0LTIiLDIseyJsYWJlbF9wb3NpdGlvbiI6MTB9XSxbMiwzLCJcXGZvb3Rub3Rlc2l6ZSAyLTMiLDJdLFswLDIsIlxcZm9vdG5vdGVzaXplIDEtMiIsMl0sWzUsNywiXFxmb290bm90ZXNpemUxLTMiLDJdLFs1LDQsIlxcZm9vdG5vdGVzaXplIDEtMiJdLFs3LDYsIlxcZm9vdG5vdGVzaXplIDMtNCIsMl0sWzYsNCwiXFxmb290bm90ZXNpemUgMi00IiwyXSxbNCw3LCJcXGZvb3Rub3Rlc2l6ZSAyLTMiLDJdLFs4LDE0XSxbMTQsMTVdLFsxNSwxM10sWzEzLDE0XSxbOCwxM10sWzExLDEyXSxbMTAsMTFdLFs5LDEwXSxbOSwxMV0sWzEyLDEwXSxbMyw1LCIiLDAseyJjdXJ2ZSI6Mywic2hvcnRlbiI6eyJzb3VyY2UiOjMwLCJ0YXJnZXQiOjMwfSwibGV2ZWwiOjJ9XSxbMTYsMSwiIiwyLHsiY3VydmUiOjMsInNob3J0ZW4iOnsic291cmNlIjozMCwidGFyZ2V0IjozMH0sImxldmVsIjoyfV1d -->
<p><img src="https://blog.algebraicjulia.org/post/2022/01/cset-automorphisms/meme.jpeg" class="img-fluid"></p>
<p>Of course, the <em>pictures</em> of the graphs are different, but it’s crucial that graphs are different from <a href="https://en.wikipedia.org/wiki/The_Treachery_of_Images">images of graphs</a>. Mathematicians regard the two graphs above as equal in the <em>context</em> of graph theory because the graphs cannot be distinguished in the <em>language</em> of graph theory. However, a computer must go beyond this language by <em>labeling</em> vertices and edges in order to efficiently represent a graph:</p>
<div id="2" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2022/01/cset-automorphisms/index_files/figure-html/cell-2-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>The three edges of this graph can be represented by two vectors of length three: <nobr><code>src=[1,1,2], tgt=[2,3,3]</code>,</nobr> where the numbers within each list refer to vertex labels. It’s fair to ask if it should count as the same graph if we listed the arrows in a different order: <nobr><code>src=[2,1,1], tgt=[3,3,2]</code>.</nobr></p>
<div id="4" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2022/01/cset-automorphisms/index_files/figure-html/cell-3-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>And should it be the same graph if we keep the arrow order but identify the vertices differently? We want the answers to these questions to be <strong>yes</strong>.</p>
<p>However, this is harder than it seems at first; the computer has direct access <em>only</em> to the underlying vector representations, which are not strictly equal in the above cases. In general, it is a tough computational problem (<a href="https://en.wikipedia.org/wiki/Graph_isomorphism_problem">the graph isomorphism problem</a>) to answer whether two graphs are equal in this richer, more meaningful sense because it involves searching over all possible reorderings of the labels.</p>
<p>The problem is even worse if we are frequently searching whether a graph is contained in some database of 1,000,000 graphs: each time we query, we’d have to solve the graph isomorphism problem up to 1,000,000 times! A solution to this problem is to find a <em>canonical</em> labeling, i.e.&nbsp;a specific labeling (out of all isomorphic labelings of a given graph) which is designated to be the representative. Given a method to compute this, we turn a hard problem (are two graphs isomorphic?) into an easy one (are the graphs’ canonical labelings strictly equal?). This labeling can then be used as a fingerprint to quickly check if the graph of interest is in the database: at worst, 1,000,000 string equality tests. The only challenge is to compute the canonical labeling of just our <em>one</em> graph of interest.</p>
</section>
<section id="working-example-acset-for-chemical-reactions" class="level2">
<h2 class="anchored" data-anchor-id="working-example-acset-for-chemical-reactions">Working Example: ACSet for chemical reactions</h2>
<p>Much time and effort has been spent crafting efficient algorithms to solve the canonical graph labeling problem, with the most popular software being <a href="https://pallini.di.uniroma1.it/Introduction.html">Nauty</a> <span class="citation" data-cites="mckay2014">(McKay and Piperno 2014)</span>, written in C. Most high-level languages that solve this problem do so by constructing input that is passed to the original Nauty program. However, what should be done if we care about things that aren’t graphs? For example, an ACSet representing chemical reactions, specified by the following schema:<sup>2</sup></p>
<p><img src="https://blog.algebraicjulia.org/post/2022/01/cset-automorphisms/MolSchema.png" class="img-fluid"></p>
<p>This is the declaration in <a href="https://github.com/AlgebraicJulia/Catlab.jl">Catlab.jl</a> (full code in <a href="https://github.com/AlgebraicJulia/CSetAutomorphisms.jl/blob/main/test/example.jl">CSetAutomorphisms.jl</a>):</p>
<div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb3-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab.Theories</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab.CategoricalAlgebra</span></span>
<span id="cb3-2"></span>
<span id="cb3-3"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@present</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SchRxn</span>(FreeSchema) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb3-4">  (Molecule, Atom, Bond)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span></span>
<span id="cb3-5">  inv<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(Bond,Bond)</span>
<span id="cb3-6">  atom<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(Bond, Atom)</span>
<span id="cb3-7">  mol<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(Atom, Molecule)</span>
<span id="cb3-8"></span>
<span id="cb3-9">  (<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Float</span>, Num)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AttrType</span></span>
<span id="cb3-10">  atomic_number<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Attr</span>(Atom, Num)</span>
<span id="cb3-11">  coefficient<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Attr</span>(Molecule, <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Float</span>)</span>
<span id="cb3-12"></span>
<span id="cb3-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compose</span>(inv, inv) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">id</span>(Bond)</span>
<span id="cb3-14"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb3-15"></span>
<span id="cb3-16"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@ACSet_type</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">RxnGeneric</span>(SchRxn)</span>
<span id="cb3-17">Rxn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> RxnGeneric{<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Float64</span>, <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>}</span></code></pre></div>
<p>This ACSet schema defines a <em>category</em> of chemical reactions, and viewing a mathematical entity as the object of a category gives us a natural context for determining when things are equivalent. This particular category captures many domain-specific features of the data that are not captured by representing the reaction as a simple <code>struct</code> of various tuples and lists of data: - Neither the ordering in which atoms are labeled, the ordering of atoms within bonds, nor the ordering of bonds themselves is relevant to the identity of a molecule. - The ordering in which the reactant molecules or product molecules are listed is not relevant to the identity of the reaction: we want <img src="https://latex.codecogs.com/png.latex?2"> H<img src="https://latex.codecogs.com/png.latex?_2">O <img src="https://latex.codecogs.com/png.latex?%5Crightarrow"> 2 H<img src="https://latex.codecogs.com/png.latex?_2"> + O<img src="https://latex.codecogs.com/png.latex?_2"> to be <em>the same</em> as <img src="https://latex.codecogs.com/png.latex?2"> H<img src="https://latex.codecogs.com/png.latex?_2">O <img src="https://latex.codecogs.com/png.latex?%5Crightarrow"> O<img src="https://latex.codecogs.com/png.latex?_2"> + <img src="https://latex.codecogs.com/png.latex?2"> H<img src="https://latex.codecogs.com/png.latex?_2"> - The atomic numbers <em>are</em> relevant to molecule identity: CO<img src="https://latex.codecogs.com/png.latex?_2"> is not H<img src="https://latex.codecogs.com/png.latex?_2">O because atomic number is an <em>attribute</em> rather than a piece of combinatorial data. Likewise for the coefficients on the reactants and products. - Stoichiometric coefficients distinguish the reactants (negative coefficients) from the products (positive coefficients), which is particularly important if we wish to characterize reactions with properties such as exothermicity.</p>
<p>In Catlab, we can declare <em>both</em> <img src="https://latex.codecogs.com/png.latex?2"> H<img src="https://latex.codecogs.com/png.latex?_2">O <img src="https://latex.codecogs.com/png.latex?%5Crightarrow"> 2 H<img src="https://latex.codecogs.com/png.latex?_2"> + O<img src="https://latex.codecogs.com/png.latex?_2"> <em>and</em> <img src="https://latex.codecogs.com/png.latex?2"> H<img src="https://latex.codecogs.com/png.latex?_2">O <img src="https://latex.codecogs.com/png.latex?%5Crightarrow"> O<img src="https://latex.codecogs.com/png.latex?_2"> + <img src="https://latex.codecogs.com/png.latex?2"> H<img src="https://latex.codecogs.com/png.latex?_2"> with the following code:</p>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb4-1">H2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@ACSet</span> Rxn <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb4-2">  Molecule <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb4-3">  coefficient <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.0</span>]</span>
<span id="cb4-4">  Atom <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb4-5">  atomic_number <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb4-6">  mol  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb4-7">  Bond <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb4-8">  atom <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]</span>
<span id="cb4-9">  inv  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb4-10"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb4-11"></span>
<span id="cb4-12">O2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">deepcopy</span>(H2)</span>
<span id="cb4-13"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set_subpart!</span>(O2, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>coefficient, [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>])</span>
<span id="cb4-14"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set_subpart!</span>(O2, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>atomic_number, [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>])</span>
<span id="cb4-15"></span>
<span id="cb4-16">H2O <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@ACSet</span> Rxn <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb4-17">  Molecule <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb4-18">  coefficient <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.0</span>]</span>
<span id="cb4-19">  Atom <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span></span>
<span id="cb4-20">  atomic_number <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>]</span>
<span id="cb4-21">  mol  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb4-22">  Bond <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span></span>
<span id="cb4-23">  atom <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>]</span>
<span id="cb4-24">  inv  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>]</span>
<span id="cb4-25"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb4-26"></span>
<span id="cb4-27">rxn₁, rxn₂ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Rxn</span>(), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Rxn</span>()</span>
<span id="cb4-28">[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">copy_parts!</span>(rxn₁, x) for x <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> [H2O, O2, H2]]</span>
<span id="cb4-29">[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">copy_parts!</span>(rxn₂, x) for x <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> [H2O, H2, O2]]</span>
<span id="cb4-30"></span>
<span id="cb4-31"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">println</span>(rxn₁ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> rxn₂) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># false</span></span>
<span id="cb4-32"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">println</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is_isomorphic</span>(rxn₁, rxn₂)) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># true</span></span></code></pre></div>
<p>Catlab’s <code>is_isomorphic</code> function offers a solution to the graph isomorphism problem that works generically for any ACSet. However, returning to the paradigm use case for canonical isomorphisms, a scientist requires a canonical labeling in order to efficiently query a large database of reactions and see if a particular reaction is inside. This problem is addressed in <a href="https://github.com/AlgebraicJulia/CSetAutomorphisms.jl">CSetAutomorphisms.jl</a>, where we generalize the Nauty algorithm beyond graphs to ACSets. The brief summary below, as well as the implementation, are based on this lucid <a href="https://www.math.unl.edu/~aradcliffe1/Papers/Canonical.pdf">expository paper</a> <span class="citation" data-cites="hartke2009">(Hartke and Radcliffe 2009)</span> on the Nauty algorithm. Formal statements can be found there for aspects of the algorithm that are shown here only by example.</p>
</section>
<section id="generalized-nauty-algorithm" class="level2">
<h2 class="anchored" data-anchor-id="generalized-nauty-algorithm">Generalized Nauty Algorithm</h2>
<p>Considering data up to isomorphism is easy for a mathematician (it’s just forgetting information!) but difficult for a computer, requiring a complicated algorithm. This algorithm has three main ingredients: color saturation, search tree exploration, and automorphism pruning. These will be briefly explained and shown to require only minor modifications to generalize to arbitrary ACSets, with our earlier ACSet <code>rxn₁</code> as a running example. We ignore attributes, which are discussed later, meaning that we should now think of <code>rxn₁</code> not as <nobr>2 H₂O ⟶ 2 H₂ + O₂</nobr> but rather as <nobr><code>⬤-⬤-⬤ -&gt; ⬤-⬤ + ⬤-⬤</code>.</nobr></p>
<section id="overview" class="level3">
<h3 class="anchored" data-anchor-id="overview">Overview</h3>
<p>While one can think of vertex labels <code>1</code>,<code>2</code>,<code>3</code>,<code>4</code> as natural numbers, it can also be helpful to think of the labels as colors: 🔵, 🟢, 🟠, 🔴 (ordering could come from alphabetizing). This shift is helpful when thinking about labelings as <em>partitions</em> of a set. We can <em>refine</em> a partition by making it more specialized (splitting up colors, never merging colors).</p>
<!-- https://q.uiver.app/?q=WzAsMTIsWzAsMCwiXFxvdmVyc2V0ezF9XFxidWxsZXQiXSxbMSwwLCJcXG92ZXJzZXR7M31cXGJ1bGxldCJdLFswLDEsIlxcb3ZlcnNldHsyfVxcYnVsbGV0Il0sWzMsMCwiXFxodWdlIFxcYnVsbGV0IixbMTgwLDYwLDYwLDFdXSxbMywxLCJcXGh1Z2VcXGJ1bGxldCIsWzEyMCw2MCw2MCwxXV0sWzQsMCwiXFxodWdlIFxcYnVsbGV0IixbMjcwLDYwLDYwLDFdXSxbMSwxLCJcXG92ZXJzZXR7NH1cXGJ1bGxldCJdLFs0LDEsIlxcaHVnZSBcXGJ1bGxldCIsWzAsNjAsNjAsMV1dLFs2LDAsIlxcaHVnZSBcXGJ1bGxldCIsWzE4MCw2MCw2MCwxXV0sWzcsMCwiXFxodWdlIFxcYnVsbGV0IixbMTgwLDYwLDYwLDFdXSxbNiwxLCJcXGh1Z2UgXFxidWxsZXQiLFswLDYwLDYwLDFdXSxbNywxLCJcXGh1Z2UgXFxidWxsZXQiLFswLDYwLDYwLDFdXSxbMCwxXSxbMCwyXSxbMyw0XSxbMyw1XSxbMiw2XSxbMSw2XSxbNCw3LCJcXHRleHRjb2xvcnt3aGl0ZX1hXFxcXHNpbmdsZXRvbiAvIGRpc2NyZXRlIFxcXFxwYXJ0aXRpb24iLDJdLFs1LDddLFs4LDldLFs4LDEwXSxbOSwxMV0sWzEwLDExXSxbMTAsNywicmVmaW5lbWVudCIsMix7Im9mZnNldCI6NSwic2hvcnRlbiI6eyJzb3VyY2UiOjMwLCJ0YXJnZXQiOjIwfSwibGV2ZWwiOjJ9XSxbNiw0LCJlcXVpdmFsZW50IiwwLHsib2Zmc2V0IjotNSwic2hvcnRlbiI6eyJzb3VyY2UiOjMwLCJ0YXJnZXQiOjMwfSwibGV2ZWwiOjIsInN0eWxlIjp7InRhaWwiOnsibmFtZSI6ImFycm93aGVhZCJ9fX1dXQ== -->
<p><img src="https://blog.algebraicjulia.org/post/2022/01/cset-automorphisms/colors.png" class="img-fluid"></p>
<p>This refinement process can go no further when we reach a <em>singleton</em> partitioning (or <em>discrete</em> partitioning), where each element has its own color. Because such a coloring can be translated back into distinct natural numbers, it can be thought of as a <em>permutation</em>. While a permutation is an isomorphism of an object with itself in the category <strong>Set</strong>, we use the word <em>automorphism</em> to refer to the general case of an isomorphism from an object of some category to itself. When we are in an C-set category, the required data of an automorphism is a set permutation for each object in the indexing category.</p>
<p>Once we find all refinements that are automorphisms, we have identified the isomorphism class of our input C-set and can select a canonical element by taking the <em>lexicographic minimum</em>.<sup>3</sup></p>
<p>Below is a graphical depiction of <code>rxn₁</code>.<sup>4</sup> Our starting point has no information as to what the automorphisms are, which is reflected by the fact that all three partitions are as unrefined as possible.</p>
<p><img src="https://blog.algebraicjulia.org/post/2022/01/cset-automorphisms/acsetvis.png" class="img-fluid"></p>
</section>
<section id="color-saturation" class="level3">
<h3 class="anchored" data-anchor-id="color-saturation">Color saturation</h3>
<p>Color saturation is a method of refining colorings of a graph without ruling out automorphisms. For graphs, we first collect data on the “local environment” of each vertex (how many of each color is adjacent). Because we can canonically order local environment data, we can canonically recolor the vertices by their local environment. This procedure can be repeated until convergence. Color saturation brings us closer towards our goal of identifying all automorphisms, but it does not completely solve our problem (sometimes it cannot make progress at all, e.g.&nbsp;starting with a <a href="https://en.wikipedia.org/wiki/Complete_graph">complete graph</a>).</p>
<p>With C-sets, there is an analogy to the “local environment” of graphs, demonstrated for the green <img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Bond%7D"> box with the asterisk in the following figure:</p>
<p><img src="https://blog.algebraicjulia.org/post/2022/01/cset-automorphisms/colordata.png" class="img-fluid"></p>
<p>Each iteration of color saturation is a refinement. The refinement of <code>rxn₁</code> has three steps, as shown below.</p>
<p><img src="https://blog.algebraicjulia.org/post/2022/01/cset-automorphisms/crefine.png" class="img-fluid"></p>
<p>This is relatively cheap to compute and can greatly reduce the search space, so we color saturate not only at the beginning but also throughout the algorithm, each time we learn new information.</p>
</section>
<section id="search-tree-exploration" class="level3">
<h3 class="anchored" data-anchor-id="search-tree-exploration">Search tree exploration</h3>
<p>Suppose that color saturation has refined our partition as far as it can. How do we identify which subset of the singleton refinements are valid automorphisms? In theory, we must try all <img src="https://latex.codecogs.com/png.latex?%5Cdisplaystyle%20%5Cprod_%7Bc%5Cin%20Colors%7D%20%7Cc%7C!"> combinations of each individual color’s permutations. These are all possible ways of completely breaking each symmetry. To avoid this combinatorial explosion, the search tree approach breaks one symmetry at a time (branching on the possible ways to do this) and runs color saturation immediately, which allows us to take advantage of the graph’s connectivity structure to do most of the refinement heavy lifting.</p>
<p>More precisely, our tree has graph colorings as nodes and edges to children nodes are “artificial distinctions”: all possible refinements that break the symmetry of a <em>particular</em> color (which can be chosen canonically) that add <em>one</em> new color.<sup>5</sup> Finding all of the <em>leaves</em> of this tree is our goal: these are all possible singleton colorings that are valid automorphisms.</p>
<p>These ideas straightforwardly generalize to C-sets, where we maintain colorings for each component, rather than just for vertices. We still break symmetry for just one color (of a single component) when branching in the search tree.</p>
<p><img src="https://blog.algebraicjulia.org/post/2022/01/cset-automorphisms/Branch.png" class="img-fluid"></p>
</section>
<section id="automorphism-pruning" class="level3">
<h3 class="anchored" data-anchor-id="automorphism-pruning">Automorphism pruning</h3>
<p>The search tree can be extremely large, even when applying color saturation whenever possible. Thankfully, because we explore the search tree depth-first, we can use the leaves we’ve seen already to sometimes determine that there is no new information below a certain node, and thus its children do not need to be explored.</p>
<p>Referring to the previous figure for intuition: our initial split effectively differentiated the two diatomic molecules. In each branch remains much work remaining to be done in order to reach a singleton coloring; however, we have an intuition that there will be some redundant work if we consider these two branches as fully independent (after all, we know we’re making a distinction between two molecules that are truly interchangable). This intuition can be formalized by the following rule:</p>
<p><img src="https://blog.algebraicjulia.org/post/2022/01/cset-automorphisms/treee.png" class="img-fluid"></p>
<p>In this image, <img src="https://latex.codecogs.com/png.latex?a"> corresponds to our initial color saturation result, and <img src="https://latex.codecogs.com/png.latex?b"> and <img src="https://latex.codecogs.com/png.latex?c"> are the two results for our initial branching. In this scenario, we have fully explored the search tree beneath <img src="https://latex.codecogs.com/png.latex?b">. The black nodes have already been explored and we’re contemplating branching on node <img src="https://latex.codecogs.com/png.latex?c">. So far we have discovered automorphisms (leaf nodes) <img src="https://latex.codecogs.com/png.latex?%5Cpi"> and <img src="https://latex.codecogs.com/png.latex?%5Cgamma">. Despite the fact that there is an unexplored leaf node under <img src="https://latex.codecogs.com/png.latex?c"> (in blue), we can actually prune <img src="https://latex.codecogs.com/png.latex?c"> from the search tree <em>if</em> it turns out that <img src="https://latex.codecogs.com/png.latex?%5Cgamma"> preserves <img src="https://latex.codecogs.com/png.latex?a"> (the nearest ancestor of <img src="https://latex.codecogs.com/png.latex?b"> and <img src="https://latex.codecogs.com/png.latex?c">) and maps <img src="https://latex.codecogs.com/png.latex?b"> into <img src="https://latex.codecogs.com/png.latex?c">. This is the formal specification for our intuition that the two diatomic molecules being the same means we oughtn’t have to explore both branches: the subtree under <img src="https://latex.codecogs.com/png.latex?b"> is isomorphic to the subtree under <img src="https://latex.codecogs.com/png.latex?c"> if this property holds. Note that this reasoning is purely categorical - because it is purely defined in terms of morphisms, it works equally well in ACSet categories as it works in <strong>Grph</strong>.</p>
</section>
<section id="extending-from-c-sets-to-acsets" class="level3">
<h3 class="anchored" data-anchor-id="extending-from-c-sets-to-acsets">Extending from C-Sets to ACSets</h3>
<p>Attributes that come with an inherent ordering make this problem easier rather than harder, as the non-combinatorial data they provide can be used to distinguish elements during color saturation. All typical attributes have this property: <code>Int</code>, <code>Float</code>, <code>String</code>. In the color saturation example above, <img src="https://latex.codecogs.com/png.latex?atomic%5C_number"> would immediately allow us to distinguish the O<img src="https://latex.codecogs.com/png.latex?_2"> molecule from the H<img src="https://latex.codecogs.com/png.latex?_2"> molecule.</p>
<p><img src="https://blog.algebraicjulia.org/post/2022/01/cset-automorphisms/attr.png" class="img-fluid"></p>
<p>In the case of an attribute without an ordering to use, we can create a pseudo object with a number of elements equal to the number of distinct values found in the ACSet, e.g.&nbsp;if the datatype of <img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Coefficient%7D"> were hypothetically not inherently ordered, we could create a <img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Coefficient%7D"> object with three elements inside and then then run the algorithm as normal. This is less preferable because it requires computational work to come up with a canonical labeling of the pseudo C-set object.</p>
</section>
</section>
<section id="outlook" class="level2">
<h2 class="anchored" data-anchor-id="outlook">Outlook</h2>
<p>Viewing a particular piece of data in the context of a category provides us enough context to resolve tricky issues of determining what is effectively the same as what. Due to the generality of the applied category theory perspective, we automatically bypass the tedious process of defining <code>__eq__</code> and <code>__hash__</code> methods for each new data structure we invent.</p>
<p>This is an exciting development because it enables hashing C-sets, a crucial operation for many data structures (e.g.&nbsp;<code>Dict{ACSet, String}</code>) and algorithms. In particular, for dynamic programming algorithms, one can now incorporate C-sets into a state space and quickly check whether a state has already been seen. For example, suppose we have experimental data for H<img src="https://latex.codecogs.com/png.latex?_2">, O<img src="https://latex.codecogs.com/png.latex?_2">, and H<img src="https://latex.codecogs.com/png.latex?_2">O and hypothesize that <code>rxn₁</code> is right model for this. An iterative algorithm could evaluate the proposed reaction against the data and propose modifications to <code>rxn₁</code> that would improve the quality of fit. This yields a search space of <img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Rxn%7D"> objects with intersecting paths. In such a scenario, we can greatly reduce computations that need to be done by checking if a new <img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Rxn%7D"> is actually new when considered <em>up to isomorphism</em>.</p>
<!-- https://q.uiver.app/?q=WzAsOCxbMCwxLCJyeG5fMSJdLFsxLDAsInJ4bl8zIl0sWzEsMSwicnhuXzQiXSxbMSwyLCJyeG5fNSJdLFsyLDEsInJ4bl82Il0sWzIsMCwicnhuXzciXSxbMywwLCIuLi4iXSxbMywxLCIuLi4iXSxbMiw0XSxbMSw0XSxbMCwyXSxbMCwxXSxbMCwzXSxbNCw3XSxbNSw2XV0= -->
<p><img src="https://blog.algebraicjulia.org/post/2022/01/cset-automorphisms/rxngrph.png" class="img-fluid"></p>
<p>Furthermore, the notion of a ‘random’ C-set instance crucially depends on which notion of equality we consider: picking a random instance of the C-set data structure (in contrast to picking a random C-set isomorphism class) will heavily overrepresent isomorphism classes with many elements. Using the isomorphism class notion of randomness is important in <a href="https://github.com/AlgebraicJulia/CombinatorialChains.jl">statistical mechanics applications</a> and more closely matches what one means when discussing a random directed graph or a random Petri net.</p>
<p>As a final thought, the difficulty of implementing new algorithms often leads one to reduce one’s problem into the form of another problem which has a ready-made algorithm. Although the ACSet of reactions is a richer, more complex structure than a graph, it is possible to encode it <em>as a graph</em> such that existing Nauty code can be used to perform the computation. Call this “bringing the data to the algorithm”. This process takes time, can create large constant factors (by encoding rich structures in a simpler language), and prevents us from taking advantage of higher-order structure lost in the translation. We avoid these pitfalls by working at a higher level of abstraction: implementing an algorithm once for C-sets and letting Julia generate specialized code for each concrete data structure that is a C-set instance. In our experience, most graph algorithms (including complicated ones, such as Nauty) straightforwardly generalize to ACSets, making us optimistic about a future where we “bring the algorithm to the data”.</p>



</section>
</section>


<div id="quarto-appendix" class="default"><section class="quarto-appendix-contents" id="quarto-bibliography"><h2 class="anchored quarto-appendix-heading">References</h2><div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="0">
<div id="ref-hartke2009" class="csl-entry">
Hartke, Stephen G., and A. J. Radcliffe. 2009. <span>“<span>McKay</span>’s Canonical Graph Labeling Algorithm.”</span> American Mathematical Society. <a href="https://doi.org/10.1090/conm/479/09345">https://doi.org/10.1090/conm/479/09345</a>.
</div>
<div id="ref-mckay2014" class="csl-entry">
McKay, Brendan D., and Adolfo Piperno. 2014. <span>“Practical Graph Isomorphism, <span>II</span>.”</span> <em>Journal of Symbolic Computation</em> 60 (January): 94–112. <a href="https://doi.org/10.1016/j.jsc.2013.09.003">https://doi.org/10.1016/j.jsc.2013.09.003</a>.
</div>
</div></section><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>

<ol>
<li id="fn1"><p>We recommend referring to this context-sensitive equality as ‘equivalence’, in contrast to ‘literal’ or ‘strict’ equality. As Eugenia Cheng <a href="https://youtu.be/ho7oagHeqNc?t=1226">advocates</a>, “All equations are lies…or useless.”↩︎</p></li>
<li id="fn2"><p>The relation between bonds and atoms is taken from <a href="https://www.algebraicjulia.org/blog/post/2020/09/cset-graphs-2/">half-edge graphs</a>, which encode symmetric relationships and also allow for the representation of ‘dangling bonds’.↩︎</p></li>
<li id="fn3"><p>For example, the graph with two vertices and an arrow going between them has two elements in the automorphism class: <img src="https://latex.codecogs.com/png.latex?G_n:=(src=%5B1%5D,%5C%20tgt=%5B2%5D)"> and <img src="https://latex.codecogs.com/png.latex?G_m:=(src=%5B2%5D,%20tgt=%5B1%5D)">. Because the underlying data of a C-set is essentially of type <code>Dict{String, Vector{Int}}</code>, we require a method to tell whether two elements of this type are less than, greater, or equal to each other. One way to do this is to order the vectors (in this case, let’s use alphabetization to order the set <img src="https://latex.codecogs.com/png.latex?%5C%7Bsrc,%5C%20tgt%5C%7D">) in order to get two elements of type <code>Vector{Vector{Int}}</code> which we can compare to see that <img src="https://latex.codecogs.com/png.latex?G_n%20%5Clt%20G_m">.↩︎</p></li>
<li id="fn4"><p>Although the elements of <img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Molecule%7D"> (triangles), <img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Atom%7D"> (circles), and <img src="https://latex.codecogs.com/png.latex?%7B%5Crm%20Bond%7D"> (squares) live in different sets, we visualize them all in one graph via the <a href="https://ncatlab.org/nlab/show/category+of+elements">category of elements</a> construction.↩︎</p></li>
<li id="fn5"><p>For example, with 🔴🟡🟡🔴🟡🔴🔴, we branch on 🟡 and obtain three child nodes: <nobr>🔴🟢🟡🔴🟡🔴🔴, 🔴🟡🟢🔴🟡🔴🔴, and 🔴🟡🟡🔴🟢🔴🔴.</nobr>↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>c-sets</category>
  <category>attributed-c-sets</category>
  <category>databases</category>
  <guid>https://blog.algebraicjulia.org/post/2022/01/cset-automorphisms/</guid>
  <pubDate>Tue, 04 Jan 2022 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Graphs and C-sets IV: The propositional logic of subgraphs and sub-C-sets</title>
  <dc:creator>David Jaz Myers and Evan Patterson</dc:creator>
  <link>https://blog.algebraicjulia.org/post/2021/09/cset-graphs-4/</link>
  <description><![CDATA[ 





<div class="hidden">
<p>$$ <!-- Number systems --> </p>
<!-- Categories -->
<!-- Graphs -->
<!-- Double categories -->
<!-- Acsets -->
<!-- Wiring diagrams -->
<!-- Dynamical systems -->
<p>$$</p>
</div>
<p>Every proposition is either true or false. This famous tautology is called the <em>law of excluded middle</em>. As the words “tautology” and “law” suggest, the law of excluded middle is often taken to be obviously true and attempts to deny it as bizarre and esoteric. But it is easy enough to imagine everyday situations that challenge the obviousness of this principle. Suppose I loiter in the doorway of your office, with one foot in the room and the other in the hallway. Am I in your office, or not? The law of excluded middle says that we must regard exactly one of the two propositions as true, but the choice of which seems arbitrary. Such conundrums are typical of the “logic of space.”</p>
<p>In this post, we will see that any graph, and more generally any <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set, can serve as the domain of discourse of a logical system. Unless the schema <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D"> satisfies certain special conditions, the logic will be <a href="https://ncatlab.org/nlab/show/intuitionistic+logic">intuitionistic</a>, which means that the principle of excluded middle does not hold. Far from being paradoxical, such logics offer a natural and powerful language to reason about spaces whose parts are connected together.</p>
<p>To understand this post, it will helpful to know the definition of a <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set (<a href="../../../../post/2020/09/cset-graphs-1/">Part I</a>) and of a morphism of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets (<a href="../../../../post/2021/04/cset-graphs-3/">Part III</a>). The textbook by Reyes, Reyes, and Zolfaghari, now out of print but freely available online, is recommended for further reading <span class="citation" data-cites="reyes2004">(M. L. P. Reyes, Reyes, and Zolfaghari 2004)</span>. Complete code for similar examples is available in the <a href="https://algebraicjulia.github.io/Catlab.jl/stable/generated/graphs/subgraphs/">Catlab documentation</a>.</p>
<section id="propositions-as-subobjects" class="level2">
<h2 class="anchored" data-anchor-id="propositions-as-subobjects">Propositions as subobjects</h2>
<p>Logic supplies rules for arguing that certain propositions hold, given other propositions that are assumed to hold. But not all propositions concern all things; a person might be “good at baseball,” but cannot be “prime”, and a number can be “prime”, but cannot be “good at baseball”. Thus, propositions are understood relative to a <em>domain of discourse</em>, the set of things of which the proposition may be true or false. Each proposition determines a subset of the domain of discourse, namely the subset of things of which the proposition is true. Conversely, any subset of the domain determines a proposition, the proposition “is in the subset.” So, once we have chosen a domain of discourse, propositions become interchangeable with subsets of the domain. Logical connectives then translate into set-theoretic operations; for example, conjunction (“and”) and disjunction (“or”) of propositions become intersection and union of subsets.</p>
<p>A point of departure for categorical logic is to replace “set” or “domain” with “object in a category” and replace “subset” with “subobject.” What is a subobject? Given a category <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BS%7D">, a <strong>subobject</strong> of an object <img src="https://latex.codecogs.com/png.latex?X%20%5Cin%0A%5Cmathsf%7BS%7D"> is a monomorphism into <img src="https://latex.codecogs.com/png.latex?X">. A <a href="https://ncatlab.org/nlab/show/monomorphism">monomorphism</a> in a category <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BS%7D"> is, loosely speaking, a morphism in <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BS%7D"> that behaves like an injection in the category of sets. In particular, a subobject of a set <img src="https://latex.codecogs.com/png.latex?X"> is an injective function into <img src="https://latex.codecogs.com/png.latex?X">, whose image picks out a subset of <img src="https://latex.codecogs.com/png.latex?X">.<sup>1</sup></p>
<p>We can now begin to generalize propositional logic from sets to <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets, for any schema <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">. Fix a <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set <img src="https://latex.codecogs.com/png.latex?X">, which will serve as our domain of discourse. A <strong>sub-<img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set</strong> of <img src="https://latex.codecogs.com/png.latex?X"> is a subobject of <img src="https://latex.codecogs.com/png.latex?X">, i.e., a monomorphism into <img src="https://latex.codecogs.com/png.latex?X">. As one might expect, a morphism <img src="https://latex.codecogs.com/png.latex?%5Cphi:%20A%20%5Cto%20X"> of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets is monic if and only if every component <img src="https://latex.codecogs.com/png.latex?%5Cphi_c:%20A(c)%20%5Cto%20X(c)"> is an injective function. Sub-<img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets of <img src="https://latex.codecogs.com/png.latex?X"> define propositions relative to the domain of discourse <img src="https://latex.codecogs.com/png.latex?X">.</p>
<p>Taking <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D"> to be the terminal category <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7B1%7D%20=%20%5C%7B*%5C%7D"> recovers the classical world of sets, but other choices lead to less familiar logics. As usual, our running example will be graphs, where <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D%20=%20%5C%7BE%0A%5Crightrightarrows%20V%5C%7D"> is the schema for graphs. A monomorphism is then a graph homomorphism whose vertex and edge maps are injective, and a sub-<img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set is a <strong>subgraph</strong>.</p>
<p>Throughout the post, we will take the following graph to be our domain of discourse.</p>
<div id="2" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab.Theories</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab.CategoricalAlgebra</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab.Graphs</span></span>
<span id="cb1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab.Graphics</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># hide</span></span>
<span id="cb1-3"></span>
<span id="cb1-4">X <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cycle_graph</span>(Graph, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">⊕</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">path_graph</span>(Graph, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">⊕</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cycle_graph</span>(Graph, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb1-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_edge!</span>(X, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_vertex!</span>(X))</span>
<span id="cb1-6">X</span></code></pre></div>
</details>
</div>
<div id="4" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/09/cset-graphs-4/index_files/figure-html/cell-3-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>Here are two typical subgraphs, where membership in the subgraph is indicated by highlighting.</p>
<div id="6" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb2-1">A <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Subobject</span>(X, V<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, E<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>])</span></code></pre></div>
</details>
</div>
<div id="8" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/09/cset-graphs-4/index_files/figure-html/cell-5-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="10" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb3-1">B <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Subobject</span>(X, V<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>], E<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>])</span></code></pre></div>
</details>
</div>
<div id="12" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/09/cset-graphs-4/index_files/figure-html/cell-7-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>Notice that an edge can belong to a subgraph only if both its source and target vertices do.</p>
</section>
<section id="logical-connectives-as-adjoints" class="level2">
<h2 class="anchored" data-anchor-id="logical-connectives-as-adjoints">Logical connectives as adjoints</h2>
<p>We have claimed that a <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set can serve as a domain of discourse and sub-<img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets as propositions about the domain, but we won’t have a logical system until we have a few logical connectives, such as conjunction and disjunction. How should we go about defining them? In classical logic, the logical connectives are usually taken as primitive, given by something like pure intuition, but in our generalized logic, it is not as obvious how to proceed. It was the insight of Lawvere that logical operations can be derived systematically by taking adjoints of still more primitive operations. This procedure can be carried out in any category for which the needed adjoints exist.</p>
<p>To set this up, we need to explain how the subobjects of a given object form a preorder and how to compute adjoints in a preorder. Given an object <img src="https://latex.codecogs.com/png.latex?X"> in a category <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BS%7D">, let <img src="https://latex.codecogs.com/png.latex?%5Coperatorname%7BSub%7D(X)"> denote the set of all subobjects of <img src="https://latex.codecogs.com/png.latex?X">. A morphism from a subobject <img src="https://latex.codecogs.com/png.latex?A:%20%5Coperatorname%7Bdom%7DA%20%5Cto%20X"> to a subobject <img src="https://latex.codecogs.com/png.latex?B:%20%5Coperatorname%7Bdom%7DB%20%5Cto%20X"> is a morphism <img src="https://latex.codecogs.com/png.latex?f:%20%5Coperatorname%7Bdom%7DA%20%5Cto%20%5Coperatorname%7Bdom%7DB"> in <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BS%7D"> such that <img src="https://latex.codecogs.com/png.latex?f%20%5Coperatorname%7B%E2%A8%9F%7DB%20=%20A">. Since <img src="https://latex.codecogs.com/png.latex?B"> is monic, there exists at most one such morphism <img src="https://latex.codecogs.com/png.latex?f">, and since <img src="https://latex.codecogs.com/png.latex?A"> is monic, <img src="https://latex.codecogs.com/png.latex?f"> is monic when it exists. With this definition, <img src="https://latex.codecogs.com/png.latex?%5Coperatorname%7BSub%7D(X)"> becomes a <a href="https://ncatlab.org/nlab/show/thin+category">thin category</a> or <a href="https://ncatlab.org/nlab/show/preorder">preorder</a>.<sup>2</sup> We write <img src="https://latex.codecogs.com/png.latex?A%20%5Cleq%20B"> when there exists a (unique) morphism <img src="https://latex.codecogs.com/png.latex?A%20%5Cto%20B"> in <img src="https://latex.codecogs.com/png.latex?%5Coperatorname%7BSub%7D(X)">. The logical interpretation of <img src="https://latex.codecogs.com/png.latex?A%20%5Cleq%20B"> is that the proposition <img src="https://latex.codecogs.com/png.latex?A"> implies the proposition <img src="https://latex.codecogs.com/png.latex?B">.</p>
<p>Adjointness is a fundamental concept of category theory that is easily understood in the special case of preorders. An <strong>adjunction</strong> between two preorders <img src="https://latex.codecogs.com/png.latex?P"> and <img src="https://latex.codecogs.com/png.latex?Q"> consists of a pair of monotone maps <img src="https://latex.codecogs.com/png.latex?f:%20P%20%5Cto%20Q"> and <img src="https://latex.codecogs.com/png.latex?g:%20Q%0A%5Cto%20P"> such that for any objects <img src="https://latex.codecogs.com/png.latex?x%20%5Cin%20P"> and <img src="https://latex.codecogs.com/png.latex?y%20%5Cin%20Q">, one has <img src="https://latex.codecogs.com/png.latex?f(x)%20%5Cleq%20y"> if and only if <img src="https://latex.codecogs.com/png.latex?x%20%5Cleq%20g(y)">. The “if and only if” statement is sometimes denoted by a vertical bar:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Bmatrix%7D%0A%20%20f(x)%20%5Cleq%20y%20%5C%5C%20%5Chline%0A%20%20x%20%5Cleq%20g(y)%0A%5Cend%7Bmatrix%7D%0A"></p>
<p>One says that <img src="https://latex.codecogs.com/png.latex?f"> is <strong>left adjoint</strong> to <img src="https://latex.codecogs.com/png.latex?g">, or that <img src="https://latex.codecogs.com/png.latex?g"> is <strong>right adjoint</strong> to <img src="https://latex.codecogs.com/png.latex?f">, and writes <img src="https://latex.codecogs.com/png.latex?f%20%5Cdashv%20g">. Left and right adjoints are unique up to isomorphism when they exist; when <img src="https://latex.codecogs.com/png.latex?P"> is a poset, they are unique without qualification. For more about adjunctions in preorders and posets, <span class="citation" data-cites="1803.05316 reyes2004">(see Fong and Spivak 2018, chap. 1; M. L. P. Reyes, Reyes, and Zolfaghari 2004, chap. 7)</span>.</p>
<p>Any preorder <img src="https://latex.codecogs.com/png.latex?P"> whatsoever supports the basic operations of duplication and deletion. Let <img src="https://latex.codecogs.com/png.latex?P%20%5Ctimes%20P"> be the cartesian product of <img src="https://latex.codecogs.com/png.latex?P"> with itself, so that <img src="https://latex.codecogs.com/png.latex?(x,y)%20%5Cleq%20(x',y')"> if and only if <img src="https://latex.codecogs.com/png.latex?x%20%5Cleq%20x'"> and <img src="https://latex.codecogs.com/png.latex?y%20%5Cleq%20y'">, and let <img src="https://latex.codecogs.com/png.latex?1%20=%0A%5C%7B*%5C%7D"> be the unique preorder with a single element <img src="https://latex.codecogs.com/png.latex?*">. Then the <strong>diagonal</strong> or <strong>duplication</strong> map <img src="https://latex.codecogs.com/png.latex?%5CDelta_P:%20P%20%5Cto%20P%20%5Ctimes%20P"> is defined by <img src="https://latex.codecogs.com/png.latex?%5CDelta_P(x)%0A:=%20(x,x)">, and the <strong>deletion</strong> map <img src="https://latex.codecogs.com/png.latex?!_P:%20P%20%5Cto%201"> is defined by <img src="https://latex.codecogs.com/png.latex?!_P(x)%20:=%20*">. Starting from these seemingly trivial operations, we shall derive all the connectives of propositional logic.</p>
<p>Letting <img src="https://latex.codecogs.com/png.latex?P%20=%20%5Coperatorname%7BSub%7D(X)"> be the preorder of subobjects of <img src="https://latex.codecogs.com/png.latex?X">, <strong>conjunction</strong> of propositions, a binary operation <img src="https://latex.codecogs.com/png.latex?%5Cwedge:%20P%20%5Ctimes%20P%20%5Cto%20P">, is defined to be the right adjoint of the duplication map <img src="https://latex.codecogs.com/png.latex?%5CDelta_P:%20P%20%5Cto%20P%20%5Ctimes%20P">. For any subobjects <img src="https://latex.codecogs.com/png.latex?A">, <img src="https://latex.codecogs.com/png.latex?B">, <img src="https://latex.codecogs.com/png.latex?C">, we have the equivalences:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Bmatrix%7D%0A%20%20C%20%5Cleq%20A%20%5Cwedge%20B%20%5C%5C%20%5Chline%0A%20%20%5CDelta_P(C)%20%5Cleq%20(A,%20B)%20%5C%5C%20%5Chline%0A%20%20(C,%20C)%20%5Cleq%20(A,%20B)%20%20%5C%5C%20%5Chline%0A%20%20C%20%5Cleq%20A%20%5Ctext%7B%20and%20%7D%20C%20%5Cleq%20B%0A%5Cend%7Bmatrix%7D%0A"></p>
<p>So <img src="https://latex.codecogs.com/png.latex?A%20%5Cwedge%20B%20%5Cgeq%20C"> if and only if <img src="https://latex.codecogs.com/png.latex?C"> is a lower bound of <img src="https://latex.codecogs.com/png.latex?A"> and <img src="https://latex.codecogs.com/png.latex?B">, which means that <img src="https://latex.codecogs.com/png.latex?A%20%5Cwedge%20B"> is a <em>greatest lower bound</em> or <em>meet</em> of <img src="https://latex.codecogs.com/png.latex?A"> and <img src="https://latex.codecogs.com/png.latex?B">. In logical terms, the conjunction of <img src="https://latex.codecogs.com/png.latex?A"> and <img src="https://latex.codecogs.com/png.latex?B"> is weakest proposition that implies both <img src="https://latex.codecogs.com/png.latex?A"> and <img src="https://latex.codecogs.com/png.latex?B">.</p>
<p>The <strong>true</strong> proposition, a constant <img src="https://latex.codecogs.com/png.latex?%5Ctop:%201%20%5Cto%20P">, is defined to be the right adjoint of the deletion map <img src="https://latex.codecogs.com/png.latex?!_P:%20P%20%5Cto%201">. For any subobject <img src="https://latex.codecogs.com/png.latex?C">, we have:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Bmatrix%7D%0A%20%20C%20%5Cleq%20%5Ctop%20%5C%5C%20%5Chline%0A%20%20!_P(C)%20%5Cleq%20*%20%5C%5C%20%5Chline%0A%20%20*%20%5Cleq%20*%20%5C%5C%20%5Chline%0A%20%20%5Ctext%7Btrue%7D%0A%5Cend%7Bmatrix%7D%0A"></p>
<p>So any subobject <img src="https://latex.codecogs.com/png.latex?C"> is a lower bound of <img src="https://latex.codecogs.com/png.latex?%5Ctop">, meaning that <img src="https://latex.codecogs.com/png.latex?%5Ctop"> is a <em>maximal</em> or <em>top</em> element. In logical terms, <img src="https://latex.codecogs.com/png.latex?%5Ctop"> is the proposition that is always true, i.e., the weakest of all propositions.</p>
<p>Dually, <strong>disjunction</strong> of propositions and the <strong>false</strong> proposition are defined to be left adjoint to the duplication and deletion maps, respectively, making them the <em>least upper bound</em> or <em>join</em> and a <em>minimal</em> or <em>bottom</em> element. In logical terms, the disjunction of <img src="https://latex.codecogs.com/png.latex?A"> and <img src="https://latex.codecogs.com/png.latex?B"> is the strongest proposition that is implied by both <img src="https://latex.codecogs.com/png.latex?A"> and <img src="https://latex.codecogs.com/png.latex?B">, whereas <img src="https://latex.codecogs.com/png.latex?%5Cbot"> is the proposition that is always false, i.e., the strongest proposition.</p>
<p>In the logic of sub-<img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets, all four operations have simple formulas. For any <img src="https://latex.codecogs.com/png.latex?c%20%5Cin%20%5Cmathsf%7BC%7D"> and <img src="https://latex.codecogs.com/png.latex?x%20%5Cin%20X(c)">, conjunction and disjunction satisfy</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Baligned%7D%0A%20%20x%20%5Cin%20(A%20%5Cwedge%20B)(c)%20&amp;%5Cqquad%5Ctext%7Biff%7D%5Cqquad%0A%20%20%20%20x%20%5Cin%20A(c)%20%5Ctext%7B%20and%20%7D%20x%20%5Cin%20B(c)%20%5C%5C%0A%20%20x%20%5Cin%20(A%20%5Cvee%20B)(c)%20&amp;%5Cqquad%5Ctext%7Biff%7D%5Cqquad%0A%20%20%20%20x%20%5Cin%20A(c)%20%5Ctext%7B%20or%20%7D%20x%20%5Cin%20B(c)%0A%5Cend%7Baligned%7D%0A"></p>
<p>where, by a common abuse of notation, we are identifying a monomorphism into <img src="https://latex.codecogs.com/png.latex?X"> with its image in <img src="https://latex.codecogs.com/png.latex?X">. Similarly, true and false are the full sub-<img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set <img src="https://latex.codecogs.com/png.latex?X"> and the empty sub-<img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set, respectively. As a concrete example, the conjunction and disjunction of the two subgraphs <img src="https://latex.codecogs.com/png.latex?A"> and <img src="https://latex.codecogs.com/png.latex?B"> defined above are:</p>
<div id="14" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb4-1">A <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">∧</span> B</span></code></pre></div>
</details>
</div>
<div id="16" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/09/cset-graphs-4/index_files/figure-html/cell-9-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="18" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb5-1">A <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">∨</span> B</span></code></pre></div>
</details>
</div>
<div id="20" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/09/cset-graphs-4/index_files/figure-html/cell-11-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="implication-and-negation" class="level2">
<h2 class="anchored" data-anchor-id="implication-and-negation">Implication and negation</h2>
<p>The logical operations introduced so far have straightforward pointwise formulas reducing them to classical logic, but things become more interesting when we turn to implication and negation.</p>
<p>The left adjoint of conjunction is, by definition, the diagonal, but we can still ask whether conjunction has a right adjoint. To be more precise, fixing a subobject <img src="https://latex.codecogs.com/png.latex?B">, we ask whether conjunction with <img src="https://latex.codecogs.com/png.latex?B">, a map <img src="https://latex.codecogs.com/png.latex?(-)%20%5Cwedge%20B:%20P%20%5Cto%0AP">, has a right adjoint. The answer is yes whenever <img src="https://latex.codecogs.com/png.latex?P"> is the subobjects of a <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set. The adjoint operation is called <strong>implication</strong> and is denoted <img src="https://latex.codecogs.com/png.latex?B%0A%5CRightarrow%20(-):%20P%20%5Cto%20P">. By definition, implication is characterized by the equivalence</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Bmatrix%7D%0A%20%20A%20%5Cwedge%20B%20%5Cleq%20C%20%5C%5C%20%5Chline%0A%20%20A%20%5Cleq%20B%20%5CRightarrow%20C%0A%5Cend%7Bmatrix%7D%0A"></p>
<p>for all <img src="https://latex.codecogs.com/png.latex?A,B,C">. Logically, <img src="https://latex.codecogs.com/png.latex?B%20%5CRightarrow%20C"> is the weakest proposition whose conjunction with <img src="https://latex.codecogs.com/png.latex?B"> implies <img src="https://latex.codecogs.com/png.latex?C">. But recall that <img src="https://latex.codecogs.com/png.latex?B%20%5Cleq%20C">, or the existence of a morphism <img src="https://latex.codecogs.com/png.latex?B%20%5Cto%20C">, already means that “<img src="https://latex.codecogs.com/png.latex?B"> implies <img src="https://latex.codecogs.com/png.latex?C">.” Thus, the proposition <img src="https://latex.codecogs.com/png.latex?B%20%5CRightarrow%20C"> can be seen as “internalizing” implication within the logic itself. Indeed, implication is an example of an <a href="https://ncatlab.org/nlab/show/internal+hom">internal hom</a> in a cartesian monoidal category, although that is slightly beyond the scope of this article.</p>
<p>As in classical logic, negation can defined using implication: the <strong>negation</strong> of <img src="https://latex.codecogs.com/png.latex?A"> is <img src="https://latex.codecogs.com/png.latex?%5Cneg%20A%20:=%20(A%20%5CRightarrow%20%5Cbot)">. Using the adjunction, we have:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Bmatrix%7D%0A%20%20B%20%5Cleq%20%5Cneg%20A%20%5C%5C%20%5Chline%0A%20%20B%20%5Cleq%20A%20%5CRightarrow%20%5Cbot%20%5C%5C%20%5Chline%0A%20%20B%20%5Cwedge%20A%20%5Cleq%20%5Cbot%20%5C%5C%20%5Chline%0A%20%20B%20%5Cwedge%20A%20%5Ccong%20%5Cbot%0A%5Cend%7Bmatrix%7D%0A"></p>
<p>So <img src="https://latex.codecogs.com/png.latex?%5Cneg%20A"> is the largest subobject whose meet with <img src="https://latex.codecogs.com/png.latex?A"> is empty, or in logical terms, the weakest proposition that is inconsistent with <img src="https://latex.codecogs.com/png.latex?A">.</p>
<p>Unlike conjunction or disjunction, implication and negation of sub-<img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets generally cannot be computed by pointwise Boolean operations. Suppose we tried to define the negation of a subgraph <img src="https://latex.codecogs.com/png.latex?A"> by including an element in <img src="https://latex.codecogs.com/png.latex?%5Cneg%20A"> if and only if it is not included in <img src="https://latex.codecogs.com/png.latex?A">. In our running example of a graph <img src="https://latex.codecogs.com/png.latex?X"> and subgraph <img src="https://latex.codecogs.com/png.latex?A">, we would include edge 3 of <img src="https://latex.codecogs.com/png.latex?X"> in <img src="https://latex.codecogs.com/png.latex?%5Cneg%0AA"> but not include its source or target vertices—which does not define a valid subgraph.</p>
<p>Instead, implication and negation of sub-<img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets satisfy the formulas</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Baligned%7D%0A%20%20x%20%5Cin%20(A%20%5CRightarrow%20B)(c)%20&amp;%5Cqquad%5Ctext%7Biff%7D%5Cqquad%0A%20%20%20%20x%20%5Ccdot%20f%20%5Cin%20A(c')%20%5CRightarrow%20x%20%5Ccdot%20f%20%5Cin%20B(c')%0A%20%20%20%20%5Ctext%7B%20for%20all%20$f:%20c%20%5Cto%20c'$%20in%20$%5Cmathsf%7BC%7D$%7D%20%5C%5C%0A%20%20x%20%5Cin%20(%5Cneg%20A)(c)%20&amp;%5Cqquad%5Ctext%7Biff%7D%5Cqquad%0A%20%20%20%20x%20%5Ccdot%20f%20%5Cnotin%20A(c')%0A%20%20%20%20%5Ctext%7B%20for%20all%20$f:%20c%20%5Cto%20c'$%20in%20$%5Cmathsf%7BC%7D$%7D%0A%5Cend%7Baligned%7D%0A"></p>
<p>for every <img src="https://latex.codecogs.com/png.latex?c%20%5Cin%20%5Cmathsf%7BC%7D"> and <img src="https://latex.codecogs.com/png.latex?x%20%5Cin%20X(c)"> <span class="citation" data-cites="reyes2004">(M. L. P. Reyes, Reyes, and Zolfaghari 2004, Proposition 9.1.5)</span>. The reader is encouraged to write out these formulas explicitly in the case of graphs. As concrete examples, here are <img src="https://latex.codecogs.com/png.latex?A%20%5CRightarrow%20B"> and <img src="https://latex.codecogs.com/png.latex?%5Cneg%20A"> for the subgraphs <img src="https://latex.codecogs.com/png.latex?A"> and <img src="https://latex.codecogs.com/png.latex?B"> defined above:</p>
<div id="22" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb6-1">A <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">⟹</span> B</span></code></pre></div>
</details>
</div>
<div id="24" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/09/cset-graphs-4/index_files/figure-html/cell-13-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="26" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb7-1">¬A</span></code></pre></div>
</details>
</div>
<div id="28" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/09/cset-graphs-4/index_files/figure-html/cell-15-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="subtraction-and-complement" class="level2">
<h2 class="anchored" data-anchor-id="subtraction-and-complement">Subtraction and complement</h2>
<p>Negation of sub-<img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets is conservative in the sense that an element <img src="https://latex.codecogs.com/png.latex?x"> is included in <img src="https://latex.codecogs.com/png.latex?%5Cneg%20A"> just when no element <em>reachable</em> from <img src="https://latex.codecogs.com/png.latex?x"> is included in <img src="https://latex.codecogs.com/png.latex?A">. This suggests that there should be a more liberal notion of negation, say <img src="https://latex.codecogs.com/png.latex?%5Cmathord%7B%5Csim%7DA">, such that an element <img src="https://latex.codecogs.com/png.latex?x"> is included in <img src="https://latex.codecogs.com/png.latex?%5Cmathord%7B%5Csim%7DA"> just when <img src="https://latex.codecogs.com/png.latex?x"> is reachable from any element not in <img src="https://latex.codecogs.com/png.latex?A">. We can construct the “other negation” dually to negation: as the two-fold left adjoint to the diagonal map, rather than the two-fold right adjoint.</p>
<p>Fix a subobject <img src="https://latex.codecogs.com/png.latex?B"> and consider disjunction with <img src="https://latex.codecogs.com/png.latex?B">, which is a map <img src="https://latex.codecogs.com/png.latex?B%20%5Cvee%0A(-):%20P%20%5Cto%20P">. When <img src="https://latex.codecogs.com/png.latex?P%20=%20%5Coperatorname%7BSub%7D(X)"> for a <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set <img src="https://latex.codecogs.com/png.latex?X">, this map has a left adjoint, called <strong>subtraction</strong> and denoted <img src="https://latex.codecogs.com/png.latex?(-)%20%5Csetminus%20B:%20P%20%5Cto%20P">. Subtraction is characterized by the equivalence</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Bmatrix%7D%0A%20%20A%20%5Cleq%20B%20%5Cvee%20C%20%5C%5C%20%5Chline%0A%20%20A%20%5Csetminus%20B%20%5Cleq%20C%0A%5Cend%7Bmatrix%7D%0A"></p>
<p>for all <img src="https://latex.codecogs.com/png.latex?A,B,C">. In logical terms, <img src="https://latex.codecogs.com/png.latex?A%20%5Csetminus%20B"> is the strongest proposition whose disjunction with <img src="https://latex.codecogs.com/png.latex?B"> is implied by <img src="https://latex.codecogs.com/png.latex?A">. The <strong>complement</strong> of <img src="https://latex.codecogs.com/png.latex?A"> is then defined by <img src="https://latex.codecogs.com/png.latex?%5Cmathord%7B%5Csim%7DA%20:=%20(%5Ctop%20%5Csetminus%20A)">. By the adjunction, we have:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Bmatrix%7D%0A%20%20%5Cmathord%7B%5Csim%7DA%20%5Cleq%20B%20%5C%5C%20%5Chline%0A%20%20%5Ctop%20%5Csetminus%20A%20%5Cleq%20B%20%5C%5C%20%5Chline%0A%20%20%5Ctop%20%5Cleq%20A%20%5Cvee%20B%20%5C%5C%20%5Chline%0A%20%20%5Ctop%20%5Ccong%20A%20%5Cvee%20B%0A%5Cend%7Bmatrix%7D%0A"></p>
<p>So <img src="https://latex.codecogs.com/png.latex?%5Cmathord%7B%5Csim%7DA"> is the smallest subobject whose join with <img src="https://latex.codecogs.com/png.latex?A"> is all of <img src="https://latex.codecogs.com/png.latex?X">, or in logical terms, the strongest proposition whose disjunction with <img src="https://latex.codecogs.com/png.latex?A"> is a tautology.</p>
<p>Following Lawvere, we read <img src="https://latex.codecogs.com/png.latex?%5Cneg%20A"> as “not-<img src="https://latex.codecogs.com/png.latex?A">” and <img src="https://latex.codecogs.com/png.latex?%5Cmathord%7B%5Csim%7DA"> as “non-<img src="https://latex.codecogs.com/png.latex?A">”. For any subobject <img src="https://latex.codecogs.com/png.latex?A">, we have <img src="https://latex.codecogs.com/png.latex?%5Cneg%20A%20%5Cleq%20%5Cmathord%7B%5Csim%7DA">, i.e., the complement of <img src="https://latex.codecogs.com/png.latex?A"> is at least as large as the negation of <img src="https://latex.codecogs.com/png.latex?A">.</p>
<p>As hinted above, subtraction and complement of sub-<img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets obey the formulas</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Baligned%7D%0A%20%20x%20%5Cin%20(A%20%5Csetminus%20B)(c)%20&amp;%5Cqquad%5Ctext%7Biff%7D%5Cqquad%0A%20%20%20%20x'%20%5Cin%20A(c')%20%5Csetminus%20B(c')%0A%20%20%20%20%5Ctext%7B%20for%20some%20$f:%20c'%20%5Cto%20c$%20in%20$%5Cmathsf%7BC%7D$%20and%20$x'%20%5Cin%20f%5E%7B-1%7D%20%5Ccdot%20x$%7D%20%5C%5C%0A%20%20x%20%5Cin%20(%5Cmathord%7B%5Csim%7DA)(c)%20&amp;%5Cqquad%5Ctext%7Biff%7D%5Cqquad%0A%20%20%20%20x'%20%5Cnotin%20A(c')%0A%20%20%20%20%5Ctext%7B%20for%20some%20$f:%20c'%20%5Cto%20c$%20in%20$%5Cmathsf%7BC%7D$%20and%20$x'%20%5Cin%20f%5E%7B-1%7D%20%5Ccdot%20x$%7D%0A%5Cend%7Baligned%7D%0A"></p>
<p>for all <img src="https://latex.codecogs.com/png.latex?c%20%5Cin%20%5Cmathsf%7BC%7D"> and <img src="https://latex.codecogs.com/png.latex?x%20%5Cin%20X(c)">. In our running example, the subgraphs <img src="https://latex.codecogs.com/png.latex?A%20%5Csetminus%20B"> and <img src="https://latex.codecogs.com/png.latex?%5Cmathord%7B%5Csim%7DA"> are:</p>
<div id="30" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb8-1">A <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\</span> B</span></code></pre></div>
</details>
</div>
<div id="32" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/09/cset-graphs-4/index_files/figure-html/cell-17-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="34" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb9-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>A</span></code></pre></div>
</details>
</div>
<div id="36" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/09/cset-graphs-4/index_files/figure-html/cell-19-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="the-principle-of-excluded-middle" class="level2">
<h2 class="anchored" data-anchor-id="the-principle-of-excluded-middle">The principle of excluded middle</h2>
<p>The principle of excluded middle says that every proposition is either true or false: that is, <img src="https://latex.codecogs.com/png.latex?P%20%5Cvee%20%5Cneg%20P"> for any proposition <img src="https://latex.codecogs.com/png.latex?P">. What else could it be? But as we saw at the beginning of this post, if there is connectivity between the parts of our domain of discourse—if I can loiter in the doorway of your office, not quite in but not quite out—then the law of excluded middle fails. We can now be more precise about how this happens. A graph satisfies the principle of excluded middle if and only if it is <strong>discrete</strong>, meaning that it has no edges whatsoever. A single subgraph <img src="https://latex.codecogs.com/png.latex?A"> satisfies <img src="https://latex.codecogs.com/png.latex?A%20%5Cvee%20%5Cneg%20A%20=%20%5Ctop"> precisely when it is disconnected from the rest of the graph, meaning that there are no edges connecting <img src="https://latex.codecogs.com/png.latex?A"> with <img src="https://latex.codecogs.com/png.latex?%5Cneg%20A">. Since your office is connected to the rest of the building through the doorway, the proposition “I am in your office” will not satisfy the law of excluded middle.</p>
<p>The two negations of the logic of subgraphs lets us answer the question of what exactly the law of excluded middle is excluding. First, we can dualize the law of excluded middle to use the complement: instead of asking whether <img src="https://latex.codecogs.com/png.latex?A%20%5Cvee%20%5Cneg%0AA%20=%20%5Ctop">, we could ask whether <img src="https://latex.codecogs.com/png.latex?A%20%5Cwedge%20%7B%5Csim%7DA%20=%20%5Cbot">. It turns out that one of these conditions holds for all <img src="https://latex.codecogs.com/png.latex?A"> if and only the other does. The latter condition, <img src="https://latex.codecogs.com/png.latex?A%20%5Cwedge%20%7B%5Csim%7DA%20=%20%5Cbot">, is a nice formulation of the law of excluded middle because it excludes a proposition (asks it to be false). The “middle” being excluded here is the intersection of <img src="https://latex.codecogs.com/png.latex?A"> and its complement <img src="https://latex.codecogs.com/png.latex?%7B%5Csim%7DA">. Lawvere calls this the <strong>intrinsic boundary</strong> of <img src="https://latex.codecogs.com/png.latex?A">:</p>
<p><img src="https://latex.codecogs.com/png.latex?%20%5Cpartial%20A%20:=%20A%20%5Cwedge%20%7B%5Csim%7DA.%20"></p>
<p>The law of excluded middle can then be reformulated as: every subobject has an empty boundary.</p>
<p>For graphs, the boundary of a subgraph <img src="https://latex.codecogs.com/png.latex?A"> consists of all vertices in <img src="https://latex.codecogs.com/png.latex?A"> which are connected to the outside of <img src="https://latex.codecogs.com/png.latex?A">.</p>
<div id="38" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb10-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">∂</span>(A) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> A <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">∧</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>A</span>
<span id="cb10-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">∂</span>(A)</span></code></pre></div>
</details>
</div>
<div id="40" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/09/cset-graphs-4/index_files/figure-html/cell-21-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="using-the-logic-of-subgraphs" class="level2">
<h2 class="anchored" data-anchor-id="using-the-logic-of-subgraphs">Using the logic of subgraphs</h2>
<p>The logic of subgraphs offers a powerful language for constructing new subgraphs from old. The boundary operator is an example. Let us see some other examples.</p>
<p>If <img src="https://latex.codecogs.com/png.latex?A"> is a subgraph, then <img src="https://latex.codecogs.com/png.latex?%5Cneg%20%5Cneg%20A"> is the subgraph <strong>induced</strong> by <img src="https://latex.codecogs.com/png.latex?A">: the subgraph having the same vertices as <img src="https://latex.codecogs.com/png.latex?A"> but containing all the edges between those vertices.</p>
<div id="42" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb11-1">C <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Subobject</span>(X, V<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)</span>
<span id="cb11-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">¬</span>(¬C)</span></code></pre></div>
</details>
</div>
<div id="44" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/09/cset-graphs-4/index_files/figure-html/cell-23-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>The expansion and contraction operators are also useful <span class="citation" data-cites="reyes1996">(G. E. Reyes and Zolfaghari 1996)</span>. The subgraph <img src="https://latex.codecogs.com/png.latex?%7B%5Csim%7D%20%5Cneg%20A"> is <img src="https://latex.codecogs.com/png.latex?A"> but expanded by one degree outward. It includes all the edges that are incident to a vertex in <img src="https://latex.codecogs.com/png.latex?A">.</p>
<div id="46" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb12-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">~</span>(¬A)</span></code></pre></div>
</details>
</div>
<div id="48" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/09/cset-graphs-4/index_files/figure-html/cell-25-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>Dually, <img src="https://latex.codecogs.com/png.latex?%5Cneg%20%7B%5Csim%7D%20A"> is <img src="https://latex.codecogs.com/png.latex?A"> but contracted by one degree, containing exactly the edges between vertices in <img src="https://latex.codecogs.com/png.latex?A"> that are not connected to the outside of <img src="https://latex.codecogs.com/png.latex?A">.</p>
<div id="50" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb13-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">¬</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>A)</span></code></pre></div>
</details>
</div>
<div id="52" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/09/cset-graphs-4/index_files/figure-html/cell-27-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>Iterating these two operations will expand or contract <img src="https://latex.codecogs.com/png.latex?A"> until it satisfies <img src="https://latex.codecogs.com/png.latex?A%0A%5Cvee%20%5Cneg%20A%20=%20%5Ctop">, so that there is nothing left to add or remove because <img src="https://latex.codecogs.com/png.latex?A"> is disconnected from the rest of the graph.</p>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>This post has introduced the propositional logic of a <a href="https://ncatlab.org/nlab/show/bi-Heyting+topos">bi-Heyting topos</a>, whose primary example is the topos of graphs or any other topos of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets. We have seen that, while it may initially appear exotic, this generalized logic provides a natural language to reason about domains of discourse that exhibit connectivity. The topos of sets, a <a href="https://ncatlab.org/nlab/show/Boolean+topos">Boolean topos</a>, exemplifies the very special case of a totally disconnected domain, where the two negations coincide and the principle of excluded middle holds.</p>
<p>The logic explored here is relative to a fixed domain of discourse. What if we wish to change the domain of discourse, say from one graph to another? Pursuing this line of thought ultimately leads to extending the propositional logic of a bi-Heyting topos to a full predicate logic, having existential and universal quantifiers. That will be the topic of a future post.</p>



</section>


<div id="quarto-appendix" class="default"><section class="quarto-appendix-contents" id="quarto-bibliography"><h2 class="anchored quarto-appendix-heading">References</h2><div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="0">
<div id="ref-1803.05316" class="csl-entry">
Fong, Brendan, and David I Spivak. 2018. <span>“Seven Sketches in Compositionality: An Invitation to Applied Category Theory.”</span>
</div>
<div id="ref-johnstone2002" class="csl-entry">
Johnstone, Peter T. 2002. <em>Sketches of an Elephant: A Topos Theory Compendium, Volume 1</em>. Oxford, England: Clarendon Press.
</div>
<div id="ref-reyes1996" class="csl-entry">
Reyes, Gonzalo E., and Houman Zolfaghari. 1996. <span>“Bi-Heyting Algebras, Toposes and Modalities.”</span> <em>Journal of Philosophical Logic</em> 25 (1): 25–43. <a href="https://doi.org/10.1007/bf00357841">https://doi.org/10.1007/bf00357841</a>.
</div>
<div id="ref-reyes2004" class="csl-entry">
Reyes, Marie La Palme, Gonzalo E. Reyes, and Houman Zolfaghari. 2004. <span>“Generic Figures and Their Glueings: A Constructive Approach to Functor Categories.”</span> In. <a href="https://marieetgonzalo.files.wordpress.com/2004/06/generic-figures.pdf">https://marieetgonzalo.files.wordpress.com/2004/06/generic-figures.pdf</a>.
</div>
</div></section><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>

<ol>
<li id="fn1"><p>To make a stronger analogy between subsets and subobjects, many authors define a subobject of an object <img src="https://latex.codecogs.com/png.latex?X"> to be an <em>isomorphism class</em> of monomorphisms into <img src="https://latex.codecogs.com/png.latex?X">. In practice, one tends to move freely between the two definitions as is convenient <span class="citation" data-cites="johnstone2002">(Johnstone 2002, sec. A1.3)</span>.↩︎</p></li>
<li id="fn2"><p>If one passes to isomorphism classes of subobjects, the preorder <img src="https://latex.codecogs.com/png.latex?%5Coperatorname%7BSub%7D(X)"> becomes a poset.↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>c-sets</category>
  <category>graphs</category>
  <category>logic</category>
  <guid>https://blog.algebraicjulia.org/post/2021/09/cset-graphs-4/</guid>
  <pubDate>Thu, 23 Sep 2021 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Graphs and C-sets III: Reflexive graphs and C-set homomorphisms</title>
  <dc:creator>Evan Patterson</dc:creator>
  <link>https://blog.algebraicjulia.org/post/2021/04/cset-graphs-3/</link>
  <description><![CDATA[ 





<div class="hidden">
<p>$$ <!-- Number systems --> </p>
<!-- Categories -->
<!-- Graphs -->
<!-- Double categories -->
<!-- Acsets -->
<!-- Wiring diagrams -->
<!-- Dynamical systems -->
<p>$$</p>
</div>
<p>Continuing our tour of the many flavors of graphs and their manifestation as <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets, we discuss reflexive graphs, a seemingly minor variant of graphs that nonetheless has some interesting and distinctive features. A <a href="https://ncatlab.org/nlab/show/reflexive+graph">reflexive graph</a> is a graph where every vertex has a distinguished self-loop, like this:</p>
<div id="2" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/04/cset-graphs-3/index_files/figure-html/cell-2-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>At first glance, the self-loops may seem an inconsequential addition. It is even customary to omit them from drawings, making reflexive graphs more or less interchangeable with graphs as <em>objects</em>. However, the <em>morphisms</em> of reflexive graphs differ significantly from those of graphs and as a result the category of reflexive graphs behaves differently than the category of graphs. We will see that reflexive graphs are more “geometric” than graphs in various ways. For example, if graphs <img src="https://latex.codecogs.com/png.latex?G"> and <img src="https://latex.codecogs.com/png.latex?H"> discretize continuous spaces <img src="https://latex.codecogs.com/png.latex?X"> and <img src="https://latex.codecogs.com/png.latex?Y">, then product <img src="https://latex.codecogs.com/png.latex?G%20%5Ctimes%20H"> will discretize the product space <img src="https://latex.codecogs.com/png.latex?X%20%5Ctimes%20Y"> only if the graphs are reflexive.</p>
<p>The story of reflexive graphs will give us opportunity to discuss morphisms of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets generally, which we have not yet done in this series. To understand this post, it will be helpful to have read <a href="../../../../post/2020/09/cset-graphs-1/">Part I</a>. It is not necessary to read <a href="../../../../post/2020/09/cset-graphs-2/">Part II</a>, which goes in a different direction.</p>
<section id="reflexive-graphs" class="level2">
<h2 class="anchored" data-anchor-id="reflexive-graphs">Reflexive graphs</h2>
<p>A <strong>reflexive graph</strong> is a graph <img src="https://latex.codecogs.com/png.latex?G"> together with a function <img src="https://latex.codecogs.com/png.latex?G(%5Coperatorname%7Brefl%7D):%20G(V)%0A%5Cto%20G(E)"> that assigns to each vertex <img src="https://latex.codecogs.com/png.latex?v"> a self-loop at <img src="https://latex.codecogs.com/png.latex?v">. In other words, a reflexive graph is a <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSch%7D(%5Cmathsf%7BRGraph%7D)">-set, where <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSch%7D(%5Cmathsf%7BRGraph%7D)">, the <strong>schema for reflexive graphs</strong>, is the category generated by</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2021/04/cset-graphs-3/_svgs/1892567cd5aa97a44511a91523b31a0164ad0675.svg" class="img-fluid">
</div>
<p>subject to the equations of the commutative diagram:</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2021/04/cset-graphs-3/_svgs/7a33d653c7241a081904b14fd0a322a957023357.svg" class="img-fluid">
</div>
<p>In Catlab, the schema for reflexive graphs is:</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb1-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@present</span> SchReflexiveGraph <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> SchGraph </span><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb1-2">  refl<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(V,E)</span>
<span id="cb1-3"></span>
<span id="cb1-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compose</span>(refl, src) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">id</span>(V)</span>
<span id="cb1-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compose</span>(refl, tgt) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">id</span>(V)</span>
<span id="cb1-6"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>Similarly, a <strong>symmetric reflexive graph</strong> is a symmetric graph <img src="https://latex.codecogs.com/png.latex?G"> together with a function <img src="https://latex.codecogs.com/png.latex?G(%5Coperatorname%7Brefl%7D):%20G(V)%20%5Cto%20G(E)"> that assigns to each vertex <img src="https://latex.codecogs.com/png.latex?v"> a self-loop at <img src="https://latex.codecogs.com/png.latex?v">, which is fixed under the edge involution. Both reflexive graphs and symmetric reflexive graphs are included in the Catlab module for graphs (<code>Catlab.Graphs</code>).</p>
</section>
<section id="morphisms-of-mathsfc-sets" class="level2">
<h2 class="anchored" data-anchor-id="morphisms-of-mathsfc-sets">Morphisms of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets</h2>
<p>The key difference between graphs and reflexive graphs is between their morphisms, so let us review the notion of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set homomorphism.</p>
<p>Given a small category <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">, a <strong>homomorphism</strong>, or simply a <strong>morphism</strong>, of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets <img src="https://latex.codecogs.com/png.latex?X"> and <img src="https://latex.codecogs.com/png.latex?Y"> is a natural transformation <img src="https://latex.codecogs.com/png.latex?%5Calpha:%20X%20%5CRightarrow%20Y"> between the functors <img src="https://latex.codecogs.com/png.latex?X,%20Y:%20%5Cmathsf%7BC%7D%20%5Cto%20%5Cmathsf%7BSet%7D">. Thus, a homomorphism <img src="https://latex.codecogs.com/png.latex?%5Calpha:%20X%20%5Cto%20Y"> consists of a function <img src="https://latex.codecogs.com/png.latex?%5Calpha_c:%20X(c)%20%5Cto%20Y(c)"> for each object <img src="https://latex.codecogs.com/png.latex?c%20%5Cin%20%5Cmathsf%7BC%7D">, such that for every morphism <img src="https://latex.codecogs.com/png.latex?f:%20c%20%5Cto%20d"> in <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">, the naturality square</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2021/04/cset-graphs-3/_svgs/0c2274c30d2f2c0551bfcd84bced3e1513d1587a.svg" class="img-fluid">
</div>
<p>commutes. The functions <img src="https://latex.codecogs.com/png.latex?(%5Calpha_c)_%7Bc%20%5Cin%20%5Cmathsf%7BC%7D%7D"> are called the <strong>components</strong> of the transformation.</p>
<p>The <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets and <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set homomorphisms then form a category, suggestively denoted <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-<img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSet%7D">, where homomorphisms are composed componentwise and the identity homomorphism has each component the identity function. A homomorphism <img src="https://latex.codecogs.com/png.latex?%5Calpha"> of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets is an <strong>isomorphism</strong> if it has an inverse in <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-<img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSet%7D">, which turns out to be equivalent to each component <img src="https://latex.codecogs.com/png.latex?%5Calpha_c"> being an invertible function <span class="citation" data-cites="awodey2010">(Awodey 2010, Lemma 7.11)</span>.</p>
</section>
<section id="morphisms-of-graphs-and-reflexive-graphs" class="level2">
<h2 class="anchored" data-anchor-id="morphisms-of-graphs-and-reflexive-graphs">Morphisms of graphs and reflexive graphs</h2>
<p>The schema for graphs has only two objects, <img src="https://latex.codecogs.com/png.latex?V"> and <img src="https://latex.codecogs.com/png.latex?E">, and two morphisms, <img src="https://latex.codecogs.com/png.latex?%5Coperatorname%7Bsrc%7D"> and <img src="https://latex.codecogs.com/png.latex?%5Coperatorname%7Btgt%7D">, so a graph homomorphism <img src="https://latex.codecogs.com/png.latex?%5Calpha:%20G%20%5Cto%20H"> consists of a vertex map <img src="https://latex.codecogs.com/png.latex?%5Calpha_V:%20G(V)%20%5Cto%20H(V)"> and an edge map <img src="https://latex.codecogs.com/png.latex?%5Calpha_E:%20G(E)%20%5Cto%20H(E)"> that preserves the source and target vertices:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Calpha_E%20%5Coperatorname%7B%E2%A8%9F%7DH(%5Coperatorname%7Bsrc%7D)%20=%20G(%5Coperatorname%7Bsrc%7D)%20%5Coperatorname%7B%E2%A8%9F%7D%5Calpha_V%0A%5Cqquad%5Ctext%7Band%7D%5Cqquad%0A%5Calpha_E%20%5Coperatorname%7B%E2%A8%9F%7DH(%5Coperatorname%7Btgt%7D)%20=%20G(%5Coperatorname%7Btgt%7D)%20%5Coperatorname%7B%E2%A8%9F%7D%5Calpha_V.%0A"></p>
<p>When <img src="https://latex.codecogs.com/png.latex?H"> is a simple directed graph (has at most one directed edge between any two vertices), the edge map is completely determined by the vertex map and we recover the usual notion of <a href="https://en.wikipedia.org/wiki/Graph_homomorphism">simple graph homomorphism</a>. In general, though, the edge map is a nonredundant part of the data of a graph homomorphism.</p>
<p>A reflexive graph homomorphism is a graph homomorphism that preserves the morphism <img src="https://latex.codecogs.com/png.latex?%5Coperatorname%7Brefl%7D:%20V%20%5Cto%20E">, hence sends reflexive loops to reflexive loops. But there is no requirement that <em>only</em> reflexive loops be sent to reflexive loops. This has the effect of allowing reflexive graph homomorphisms to “collapse” edges onto vertices, which is not allowed in graph homomorphisms unless the target graph happens to have self-loops “by accident.” On the other hand, there is no appreciable difference between isomorphisms of graphs and isomorphisms of reflexive graphs since the latter can only send reflexive loops to reflexive loops.</p>
<p>The following computational example illustrates this contrast. For any finitely presented category <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">, the functions <code>homomorphism</code> and <code>homomorphisms</code> in Catlab find one or all homomorphsims between two <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets.<sup>1</sup> For example, the graphs</p>
<div id="4" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb2-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab.Graphs</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab.CategoricalAlgebra</span></span>
<span id="cb2-2"></span>
<span id="cb2-3">g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">path_graph</span>(Graph, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span></code></pre></div>
</details>
</div>
<div id="6" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/04/cset-graphs-3/index_files/figure-html/cell-4-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>and</p>
<div id="8" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb3-1">h <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Graph</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb3-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_edges!</span>(h, [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>], [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>])</span>
<span id="cb3-3">h</span></code></pre></div>
</details>
</div>
<div id="10" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/04/cset-graphs-3/index_files/figure-html/cell-6-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>are not homomorphic:</p>
<div id="12" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb4-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isempty</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">homomorphisms</span>(g, h))</span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre><code>true</code></pre>
</div>
</div>
<p>There are seven different homomorphisms between the corresponding reflexive graphs, whose vertex maps are shown in the table below. The rows are homomorphisms <img src="https://latex.codecogs.com/png.latex?%5Calpha">, the columns are vertices <img src="https://latex.codecogs.com/png.latex?v"> of <img src="https://latex.codecogs.com/png.latex?G">, and the cells are the assigned vertices <img src="https://latex.codecogs.com/png.latex?%5Calpha_V(v)"> of <img src="https://latex.codecogs.com/png.latex?H">.</p>
<div id="14" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb6-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">DataFrames</span></span>
<span id="cb6-2"></span>
<span id="cb6-3">g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">path_graph</span>(ReflexiveGraph, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb6-4">h <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ReflexiveGraph</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb6-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_edges!</span>(h, [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>], [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>])</span>
<span id="cb6-6"></span>
<span id="cb6-7">αs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">homomorphisms</span>(g, h)</span>
<span id="cb6-8">df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rename!</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DataFrame</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Tuple</span>(α[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>V]) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> α <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> αs), [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"v</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>i<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> for i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nv</span>(g)])</span></code></pre></div>
</details>
</div>
<div id="16" class="cell" data-execution_count="1">
<div class="cell-output cell-output-stdout">
<pre><code>7×3 DataFrame
 α │ v1  v2  v3
───┼────────────
 1 │  1   1   1
 2 │  1   1   3
 3 │  1   3   3
 4 │  2   2   2
 5 │  2   2   3
 6 │  2   3   3
 7 │  3   3   3</code></pre>
</div>
</div>
<p>A reflexive graph homomorphism <img src="https://latex.codecogs.com/png.latex?G%20%5Cto%20H"> can always collapse the entirety of <img src="https://latex.codecogs.com/png.latex?G"> onto a single vertex of <img src="https://latex.codecogs.com/png.latex?H">, which accounts for three of the homomorphisms. Of the remaining four, two homomorphisms collapse vertices 1 and 2 of <img src="https://latex.codecogs.com/png.latex?G"> and the other two collapse vertices 2 and 3. Although reflexive graph homomorphism is clearly weaker than graph homomorphism, it should also be clear that reflexive graph homomorphism imposes significant constraints, as there are <img src="https://latex.codecogs.com/png.latex?3%5E3%20=%2027"> different functions <img src="https://latex.codecogs.com/png.latex?G(V)%20%5Cto%20H(V)"> but only 7 extend to homomorphisms.</p>
<p>When graphs are viewed as presentations of metric spaces, reflexive graph homomorphisms fit better with the metric geometry than graph homomorphisms. Any graph or reflexive graph <img src="https://latex.codecogs.com/png.latex?G"> generates a Lawvere metric space<sup>2</sup> <img src="https://latex.codecogs.com/png.latex?X=G(V)"> where the distance between two points <img src="https://latex.codecogs.com/png.latex?x"> and <img src="https://latex.codecogs.com/png.latex?x'"> is the length of the shortest path from <img src="https://latex.codecogs.com/png.latex?x"> to <img src="https://latex.codecogs.com/png.latex?x'"> in <img src="https://latex.codecogs.com/png.latex?G">. Perhaps the most natural notion of morphism between metric spaces are the nonexpansive maps: a map <img src="https://latex.codecogs.com/png.latex?f:X%20%5Cto%20Y"> between Lawvere metric spaces <img src="https://latex.codecogs.com/png.latex?X"> and <img src="https://latex.codecogs.com/png.latex?Y"> is <strong>nonexpansive</strong> if <img src="https://latex.codecogs.com/png.latex?d_Y(f(x),f(x'))%20%5Cleq%0Ad_X(x,x')"> for all <img src="https://latex.codecogs.com/png.latex?x,%20x'%20%5Cin%20X">. Every graph or reflexive graph homomorphism restricts to a nonexpansive map on the induced metric spaces. However, a nonexpansive map generally only extends to a homomorphism in the case of reflexive graphs <span class="citation" data-cites="hell2004">(Hell and Nesetril 2004, 64)</span>. In other words, the functor <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BRGraph%7D%0A%5Cto%20%5Cmathsf%7BMet%7D"> is full but the functor <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BGraph%7D%5Cto%20%5Cmathsf%7BMet%7D"> is not.</p>
</section>
<section id="cartesian-products-of-graphs-and-reflexive-graphs" class="level2">
<h2 class="anchored" data-anchor-id="cartesian-products-of-graphs-and-reflexive-graphs">Cartesian products of graphs and reflexive graphs</h2>
<p>In a category of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets, the <a href="https://ncatlab.org/nlab/show/cartesian+product">cartesian product</a> or <a href="https://en.wikipedia.org/wiki/Product_(category_theory)">categorical product</a> is computed by taking the cartesian product of sets “pointwise” with respect to the objects of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">. Specifically, the binary product <img src="https://latex.codecogs.com/png.latex?X%20%5Ctimes%20Y"> of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets <img src="https://latex.codecogs.com/png.latex?X"> and <img src="https://latex.codecogs.com/png.latex?Y"> has elements <img src="https://latex.codecogs.com/png.latex?(X%20%5Ctimes%20Y)(c)%20=%20X(c)%20%5Ctimes%20Y(c)"> for every <img src="https://latex.codecogs.com/png.latex?c%20%5Cin%0A%5Cmathsf%7BC%7D">. It is defined on morphisms <img src="https://latex.codecogs.com/png.latex?f:%20c%20%5Cto%20d"> of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D"> by</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A(X%20%5Ctimes%20Y)(f)%20=%20X(f)%20%5Ctimes%20Y(f):%20X(c)%20%5Ctimes%20Y(c)%20%5Cto%20X(d)%20%5Ctimes%20Y(d).%0A"></p>
<p>In particular, the product of graphs <img src="https://latex.codecogs.com/png.latex?G"> and <img src="https://latex.codecogs.com/png.latex?H">, possibly reflexive or symmetric, has vertex set <img src="https://latex.codecogs.com/png.latex?G(V)%20%5Ctimes%20H(V)"> and edge set <img src="https://latex.codecogs.com/png.latex?G(E)%20%5Ctimes%20H(E)">.</p>
<p>Let’s look at the product of the path graph with itself in four different categories. In the category of graphs, this product is:</p>
<div id="18" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb8-1">n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span></span>
<span id="cb8-2">path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">path_graph</span>(Graph, n)</span>
<span id="cb8-3">path2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ob</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">product</span>(path, path))</span></code></pre></div>
</details>
</div>
<div id="20" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/04/cset-graphs-3/index_files/figure-html/cell-11-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>In the category of reflexive graphs, it is:</p>
<div id="22" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb9-1">path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">path_graph</span>(ReflexiveGraph, n)</span>
<span id="cb9-2">path2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ob</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">product</span>(path, path))</span></code></pre></div>
</details>
</div>
<div id="24" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/04/cset-graphs-3/index_files/figure-html/cell-13-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>Note that the reflexive loops are omitted from the drawing. Although it is somewhat obscured by the drawings, the disconnected paths in the graph product correspond to the vertical paths in the reflexive graph product. The remaining edges in the latter product come from pairs <img src="https://latex.codecogs.com/png.latex?(e,e')"> where at least one of <img src="https://latex.codecogs.com/png.latex?e"> and <img src="https://latex.codecogs.com/png.latex?e'"> are reflexive loops.</p>
<p>In the category of symmetric graphs, the product of a path graph with itself looks like:</p>
<div id="26" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb10-1">path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">path_graph</span>(SymmetricGraph, n)</span>
<span id="cb10-2">path2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ob</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">product</span>(path, path))</span></code></pre></div>
</details>
</div>
<div id="28" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/04/cset-graphs-3/index_files/figure-html/cell-15-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>Restricted to simple undirected graphs, graph theorists call this the <strong>direct product</strong> or <strong>tensor product</strong>. The reader should consider why this example has two connected components. (It is related to the fact that the path graph is bipartite.<sup>3</sup>) Finally, in the category of symmetric reflexive graphs, the product is:</p>
<div id="30" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb11-1">path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">path_graph</span>(SymmetricReflexiveGraph, n)</span>
<span id="cb11-2">path2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ob</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">product</span>(path, path))</span></code></pre></div>
</details>
</div>
<div id="32" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/04/cset-graphs-3/index_files/figure-html/cell-17-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>Graph theorists call this the <strong>strong product</strong>. The two components in the previous drawing should be imagined superimposed on this one, comprising the horizontal and vertical paths.</p>
<p>Graphs and reflexive graphs also differ with respect to their generalized elements. In a category with a terminal object <img src="https://latex.codecogs.com/png.latex?1">, a <strong>generalized element</strong> of an object <img src="https://latex.codecogs.com/png.latex?X"> is a morphism <img src="https://latex.codecogs.com/png.latex?1%20%5Cto%20X">. Note that terminal objects are the nullary case of cartesian products. In a category of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets, the terminal object <img src="https://latex.codecogs.com/png.latex?1"> has <img src="https://latex.codecogs.com/png.latex?1(c)%20=%20%5C%7B*%5C%7D"> equal to a singleton set for every <img src="https://latex.codecogs.com/png.latex?c%20%5Cin%0A%5Cmathsf%7BC%7D">. In particular, the terminal graph is a self-loop. This means that a graph with no self-loops has no generalized elements:</p>
<div id="34" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb12-1">I <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ob</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">terminal</span>(Graph))</span>
<span id="cb12-2">g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">path_graph</span>(Graph, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span>
<span id="cb12-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">isempty</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">homomorphisms</span>(I, g))</span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre><code>true</code></pre>
</div>
</div>
<p>On the other hand, the generalized elements of a reflexive graph correspond exactly to its vertices, as one might expect.</p>
<div id="36" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb14-1">I <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ob</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">terminal</span>(ReflexiveGraph))</span>
<span id="cb14-2">g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">path_graph</span>(ReflexiveGraph, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span>
<span id="cb14-3"></span>
<span id="cb14-4">αs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">homomorphisms</span>(I, g)</span>
<span id="cb14-5">df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DataFrame</span>((v1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>α[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>V](<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> α <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> αs)</span></code></pre></div>
</details>
</div>
<div id="38" class="cell" data-execution_count="1">
<div class="cell-output cell-output-stdout">
<pre><code>5×1 DataFrame
 α │ v1
───┼────
 1 │  1
 2 │  2
 3 │  3
 4 │  4
 5 │  5</code></pre>
</div>
</div>
<p>Thus, reflexive graphs have a more geometric notion of “point” than graphs.</p>
</section>
<section id="the-box-product-of-reflexive-graphs" class="level2">
<h2 class="anchored" data-anchor-id="the-box-product-of-reflexive-graphs">The box product of reflexive graphs</h2>
<p>None of the four products considered above correspond to what graph theorists have traditionally considered the standard product of graphs. That would be the <em>box product</em>.<sup>4</sup> From the categorical viewpoint, the box product is a bit curious and and its generalization to categories is affectionately called by category theorists the <a href="https://ncatlab.org/nlab/show/funny+tensor+product">funny tensor product</a>.</p>
<p>Given a reflexive graph <img src="https://latex.codecogs.com/png.latex?G">, let <img src="https://latex.codecogs.com/png.latex?G_0"> be the discrete graph on the vertices of <img src="https://latex.codecogs.com/png.latex?G">, whose only edges are the reflexive loops. The <strong>box product</strong> of reflexive graphs <img src="https://latex.codecogs.com/png.latex?G"> and <img src="https://latex.codecogs.com/png.latex?H">, denoted <img src="https://latex.codecogs.com/png.latex?G%5C,%5Csquare%5C,H">, is defined as the pushout in <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BRGraph%7D">:</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2021/04/cset-graphs-3/_svgs/40742e55ab7d4d867776a148d928078046618611.svg" class="img-fluid">
</div>
<p><a href="https://ncatlab.org/nlab/show/pushout">Pushouts</a> in a category generalize unions of sets. It is beyond the scope of this post to precisely describe pushouts of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets, but Catlab can compute them, so we can at least implement the box product and verify that it gives the desired result on path graphs.</p>
<div id="40" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb16-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab.Theories</span></span>
<span id="cb16-2"></span>
<span id="cb16-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">box_product</span>(g<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">T</span>, h<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">T</span>) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> T <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> ACSet</span></span>
<span id="cb16-4">  g₀, h₀ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">T</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nv</span>(g)), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">T</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nv</span>(h))</span>
<span id="cb16-5">  incl_g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">CSetTransformation</span>((V<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vertices</span>(g), E<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">refl</span>(g)), g₀, g)</span>
<span id="cb16-6">  incl_h <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">CSetTransformation</span>((V<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">vertices</span>(h), E<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">refl</span>(h)), h₀, h)</span>
<span id="cb16-7">  proj_g₀, proj_h₀ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">product</span>(g₀, h₀)</span>
<span id="cb16-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ob</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pushout</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pair</span>(proj_g₀ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">⋅</span> incl_g, proj_h₀),</span>
<span id="cb16-9">             <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pair</span>(proj_g₀, proj_h₀ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">⋅</span> incl_h)))</span>
<span id="cb16-10"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb16-11"></span>
<span id="cb16-12">path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">path_graph</span>(ReflexiveGraph, n)</span>
<span id="cb16-13">path2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">box_product</span>(path, path)</span></code></pre></div>
</details>
</div>
<div id="42" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/04/cset-graphs-3/index_files/figure-html/cell-22-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>In the category of symmetric reflexive graphs, the box product of path graphs looks like:</p>
<div id="44" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb17-1">path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">path_graph</span>(SymmetricReflexiveGraph, n)</span>
<span id="cb17-2">path2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">box_product</span>(path, path)</span></code></pre></div>
</details>
</div>
<div id="46" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/04/cset-graphs-3/index_files/figure-html/cell-24-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>Restricting the box product of symmetric reflexive graphs to a monoidal product of simple undirected graphs, we recover the box product as understood by graph theorists.</p>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>A fundamental principle of modern mathematics, and especially of category theory, is that mathematical objects should be studied through their morphisms. This principle has been exemplified by the contrast between graphs and reflexive graphs, which appear similar as objects but form importantly different categories. As we have seen, reflexive graphs are closer to metric spaces and conform better with geometric intuition than graphs. For further reading, a topos-theoretic perspective is offered by Lawvere, who argues that the topos of reflexive graphs satisfies some axioms making it a “topos of spaces” but the topos of graphs does not <span class="citation" data-cites="lawvere1986">(Lawvere 1986)</span>. Of course, in settings far removed from geometry, ordinary graphs may be preferred for their simplicity.</p>



</section>


<div id="quarto-appendix" class="default"><section class="quarto-appendix-contents" id="quarto-bibliography"><h2 class="anchored quarto-appendix-heading">References</h2><div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="0">
<div id="ref-awodey2010" class="csl-entry">
Awodey, Steve. 2010. <em>Category Theory</em>. 2nd ed. Oxford Logic Guides. London, England: Oxford University Press.
</div>
<div id="ref-hammack2011" class="csl-entry">
Hammack, Richard, Wilfried Imrich, and Sandi Klavžar. 2011. <em>Handbook of Product Graphs</em>. <span>CRC</span> Press. <a href="https://doi.org/10.1201/b10959">https://doi.org/10.1201/b10959</a>.
</div>
<div id="ref-hell2004" class="csl-entry">
Hell, Pavol, and Jaroslav Nesetril. 2004. <em>Graphs and Homomorphisms</em>. Oxford University Press. <a href="https://doi.org/10.1093/acprof:oso/9780198528173.001.0001">https://doi.org/10.1093/acprof:oso/9780198528173.001.0001</a>.
</div>
<div id="ref-lawvere1973" class="csl-entry">
Lawvere, F. William. 1973. <span>“Metric Spaces, Generalized Logic, and Closed Categories.”</span> <em>Rendiconti Del Seminario Matematico e Fisico Di Milano</em> 43 (1): 135–66. <a href="https://doi.org/10.1007/bf02924844">https://doi.org/10.1007/bf02924844</a>.
</div>
<div id="ref-lawvere1986" class="csl-entry">
———. 1986. <span>“Categories of Spaces May Not Be Generalized Spaces as Exemplified by Directed Graphs.”</span> In. <a href="http://tac.mta.ca/tac/reprints/articles/9/tr9abs.html">http://tac.mta.ca/tac/reprints/articles/9/tr9abs.html</a>.
</div>
</div></section><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>

<ol>
<li id="fn1"><p>The homomorphism finding procedure in Catlab uses backtracking search, which, despite being fairly simple, is still much faster than brute-force search. A future post will discuss the general correspondence between finding <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set homomorphisms and solving constraint satisfaction problems.↩︎</p></li>
<li id="fn2"><p>A <strong>Lawvere metric space</strong> is like a metric space except that the metric need not be finite, symmetric, or separate points <span class="citation" data-cites="lawvere1973">(Lawvere 1973)</span>. The Lawvere metric generated by a graph will not be symmetric unless the graph is symmetric and will not be finite unless the graph is strongly connected.↩︎</p></li>
<li id="fn3"><p>In fact, the tensor product of two connected, bipartite, undirected graphs always has exactly two connected components <span class="citation" data-cites="hammack2011">(Hammack, Imrich, and Klavžar 2011, Theorem 5.9)</span>.↩︎</p></li>
<li id="fn4"><p>Some graph theorists call the box product the “cartesian product,” but this terminology should be avoided because it is not the categorical product in the category of simple undirected graphs or, as far as I know, in any category of graph-like objects.↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>c-sets</category>
  <category>graphs</category>
  <guid>https://blog.algebraicjulia.org/post/2021/04/cset-graphs-3/</guid>
  <pubDate>Mon, 19 Apr 2021 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Composing open dynamical systems II: Undirected composition</title>
  <dc:creator>Sophie Libkind and James Fairbanks</dc:creator>
  <link>https://blog.algebraicjulia.org/post/2021/01/resource_sharers/</link>
  <description><![CDATA[ 





<div class="hidden">
<p>$$ <!-- Number systems --> </p>
<!-- Categories -->
<!-- Graphs -->
<!-- Double categories -->
<!-- Acsets -->
<!-- Wiring diagrams -->
<!-- Dynamical systems -->
<p>$$</p>
</div>
<p>In this series of posts on open dynamical systems, we explore various theories of composition for open dynamical systems (shown in the diagram below) and use these theories to build complex systems out of primitive ones. In the <a href="../../../../post/2021/01/machines">previous post</a>, we explored directed theories of composition (shown in purple). In this post, we will focus on undirected theories of composition (shown in blue) and give examples of composing dynamical systems using the <a href="https://algebraicjulia.github.io/AlgebraicDynamics.jl/dev/">AlgebraicDynamics.jl</a> package.</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2021/01/resource_sharers/_svgs/d3c1b96877e14afe232cc06681ae7af114b24c57.svg" class="img-fluid">
</div>
<section id="composing-resource-sharers" class="level2">
<h2 class="anchored" data-anchor-id="composing-resource-sharers">Composing Resource Sharers</h2>
<p>To compose dynamical systems, we will need to give them some extra structure in addition to their dynamics. For a dynamical system which composes via directed communication, a <em>machine</em> is the data structure that captures this additional structure. We say that machines are dynamical systems that compose via directed communication. Now we define <em>resources sharers</em> which are dynamical systems that compose via undirected composition. Informally, a resource sharer consists of four components - states - exposed ports - dynamics for evolution - a map assigning a state to each port</p>
<p>Throughout this post, we will assume that the evolution rule is an ODE, although discrete-time dynamics is also supported by AlgebraicDynamics.jl.</p>
<section id="a-pool-of-water" class="level3">
<h3 class="anchored" data-anchor-id="a-pool-of-water">A pool of water</h3>
<p>Imagine two resource sharers that model the evolution of a pool of water over time. One system models the emptying of the pool via evaporation, and the other system models the filling of the pool via rainfall. Each resource sharer has a state variable representing the volume of water in the pool. We can compose these systems by hooking them up to the same pool of water, and they communicate through this shared resource. Since each system may both affect and be affected by the shared pool of water, we consider this style of communication between systems to be undirected. The slogan for composing resource sharers is “add along shared coordinates” since the effect on the pool of water by the composite system is the sum of the effects on the pool of water by the primitive systems.</p>
<p>Recall the general approach for composing dynamical systems: 1. Choose a theory of composition 2. Choose a composition pattern in that theory 3. Define primitive systems 4. Compose!</p>
<p>Let’s sketch the general approach for our pool of water example.</p>
<p><strong>1. Choose a theory of composition.</strong> In this case (and throughout this post), we choose the theory of undirected wiring diagrams, <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSch%7D(%5Cmathsf%7BUWD%7D)">, which is defined by the schema below.<sup>1</sup></p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2021/01/resource_sharers/_svgs/8f580dc64257e835eae074b26d248eb586654f17.svg" class="img-fluid">
</div>
<p>An <em>undirected wiring diagram</em> is a <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-Set over <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSch%7D(%5Cmathsf%7BUWD%7D)">, i.e.&nbsp;a functor <img src="https://latex.codecogs.com/png.latex?d:%20%5Cmathsf%7BSch%7D(%5Cmathsf%7BUWD%7D)%20%5Cto%20%5Cmathsf%7BSet%7D">. It consists of the following data: 1. a set of boxes <img src="https://latex.codecogs.com/png.latex?d(%5Ctextrm%7BBox%7D)"> and a set of junctions <img src="https://latex.codecogs.com/png.latex?d(J)"> 2. every box <img src="https://latex.codecogs.com/png.latex?b"> has a set of ports <img src="https://latex.codecogs.com/png.latex?d(%5Cbox)%5E%7B-1%7D(b)%20%5Csubseteq%20P"> 3. a junction <img src="https://latex.codecogs.com/png.latex?j"> identifies the ports <img src="https://latex.codecogs.com/png.latex?d(%5Cjunc)%5E%7B-1%7D(j)%20%5Csubseteq%20P"> and is exposed by the outer ports <img src="https://latex.codecogs.com/png.latex?d(%5Cjunc')%5E%7B-1%7D(j)%20%5Csubseteq%20P'"></p>
<p>The theory of undirected wiring diagrams is defined in <code>Catlab.WiringDiagrams</code>, and we can implement an undirected wiring diagram by using the <code>@relation</code> macro.</p>
<p>How will we interpret an undirected wiring diagram as a syntax for composing resource sharers? An undirected wiring diagram specifies how the ports of resource sharers connect to junctions. If multiple ports are connected to the same junction then the variables exposed by the ports are identified in the composite system. Therefore, a junction represents a collection of identified variables, i.e.&nbsp;a shared resource. Outer ports map to junctions and represent the ports of the composite system. <sup>2</sup></p>
<p><strong>2. Choose a composition pattern.</strong> Since our composition theory is <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSch%7D(%5Cmathsf%7BUWD%7D)">, our composition pattern will be an undirected wiring diagram. We will use the <code>@relation</code> macro in order to implement the composition pattern for the pool of water example. The <code>@relation</code> macro provides a convenient syntax for specifying undirected wiring diagrams via a dialect of Julia code designed for graphical regular logic. The variables are captured as junctions, and function calls represent a system acting on those variables. Ports and connections in the undirected wiring diagram are inferred from the relationships between variables and functions.</p>
<div id="2" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab.WiringDiagrams</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab.Programs</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab.Graphics</span></span>
<span id="cb1-2"></span>
<span id="cb1-3">pool_pattern <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@relation</span> (water,) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb1-4">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">evaporation</span>(water)</span>
<span id="cb1-5">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rainfall</span>(water)</span>
<span id="cb1-6"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
</details>
</div>
<div id="4" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/01/resource_sharers/index_files/figure-html/cell-3-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>The two boxes designate the two systems to be composed, and the single junction represents the shared resouce — the pool of water.</p>
<p><strong>3. Choose primitive systems to compose.</strong> The system modeling the evaporation of water has one variable corresponding to the water in the pool. Let’s assume we live in a climate with constant evaporation so the dynamics are given by the ODE <img src="https://latex.codecogs.com/png.latex?%5Cdot%20w_e(t)%20=%20-%5Calpha%20w_e(t)."></p>
<p>The system modeling the rainfall also has one variable corresponding to the water in the pool. Let’s assume we live in a climate with distinct rainy and dry seasons. These oscillating dynamics are given by the ODE <img src="https://latex.codecogs.com/png.latex?%5Cdot%20w_r(t)%20=%20%5Cbeta%20(1%20+%20%5Csin(t))."></p>
<p>We will implement these primitive systems as resource sharers, and both resource sharers will have a single port which exposes the water variable. We use a labeled array for our parameter vector <code>p</code> to easily keep track of the systems’ parameters.</p>
<div id="6" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb2-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">AlgebraicDynamics</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">AlgebraicDynamics.UWDDynam</span></span>
<span id="cb2-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">LabelledArrays</span></span>
<span id="cb2-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dotwₑ</span>(u,p,t) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>p.α<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>u[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb2-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dotwᵣ</span>(u,p,t) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [p.β <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sin</span>(t))]</span>
<span id="cb2-5">evaporation <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ContinuousResourceSharer</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{Float64}</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, dotwₑ, [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]);</span>
<span id="cb2-6">rainfall    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ContinuousResourceSharer</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{Float64}</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, dotwᵣ, [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]);</span></code></pre></div>
</details>
</div>
<p><strong>4. Compose!</strong> Following the slogan “add along shared coordinates,” we add the effects of the evaporation and rainfall systems on the pool of water. We get the composite ODE <img src="https://latex.codecogs.com/png.latex?%5Cdot%20w(t)%20=%20-%5Calpha%20w(t)%20+%20%5Cbeta%20(1%20+%20%5Csin%20t)."></p>
<div id="8" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb3-1">pool_system <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">oapply</span>(pool_pattern, [evaporation, rainfall]);</span></code></pre></div>
</details>
</div>
<p>Let’s turn this composite system into an <code>ODEProblem</code>, solve, and plot!</p>
<div id="10" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb4-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">OrdinaryDiffEq</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Plots</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Plots.Measures</span></span>
<span id="cb4-2"></span>
<span id="cb4-3">u0 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>] <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># initial condition = empty pool of water</span></span>
<span id="cb4-4">params <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">LVector</span>(α <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, β <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>)</span>
<span id="cb4-5">nyears <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span></span>
<span id="cb4-6">tspan <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>, nyears <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">pi</span>)</span>
<span id="cb4-7">prob <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ODEProblem</span>(pool_system, u0, tspan, params)</span>
<span id="cb4-8">sol <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">solve</span>(prob, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Tsit5</span>())</span></code></pre></div>
</details>
</div>
<div id="12" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<!--?xml version="1.0" encoding="utf-8"?-->
<svg xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" width="672" height="480" viewbox="0 0 2688 1920">
<defs>
  <clippath id="clip900">
    <rect x="0" y="0" width="2688" height="1920"></rect>
  </clippath>
</defs>
<path clip-path="url(#clip900)" d="M0 1920 L2688 1920 L2688 0 L0 0  Z" fill="#ffffff" fill-rule="evenodd" fill-opacity="1"></path>
<defs>
  <clippath id="clip901">
    <rect x="537" y="0" width="1883" height="1883"></rect>
  </clippath>
</defs>
<path clip-path="url(#clip900)" d="M300.724 1592.38 L2640.76 1592.38 L2640.76 127.792 L300.724 127.792  Z" fill="#ffffff" fill-rule="evenodd" fill-opacity="1"></path>
<defs>
  <clippath id="clip902">
    <rect x="300" y="127" width="2341" height="1466"></rect>
  </clippath>
</defs>
<polyline clip-path="url(#clip902)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="300.724,1592.38 300.724,127.792 "></polyline>
<polyline clip-path="url(#clip902)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="766.259,1592.38 766.259,127.792 "></polyline>
<polyline clip-path="url(#clip902)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="1231.79,1592.38 1231.79,127.792 "></polyline>
<polyline clip-path="url(#clip902)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="1697.33,1592.38 1697.33,127.792 "></polyline>
<polyline clip-path="url(#clip902)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="2162.86,1592.38 2162.86,127.792 "></polyline>
<polyline clip-path="url(#clip902)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="2628.4,1592.38 2628.4,127.792 "></polyline>
<polyline clip-path="url(#clip902)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="300.724,1550.93 2640.76,1550.93 "></polyline>
<polyline clip-path="url(#clip902)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="300.724,1228.66 2640.76,1228.66 "></polyline>
<polyline clip-path="url(#clip902)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="300.724,906.387 2640.76,906.387 "></polyline>
<polyline clip-path="url(#clip902)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="300.724,584.114 2640.76,584.114 "></polyline>
<polyline clip-path="url(#clip902)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="300.724,261.84 2640.76,261.84 "></polyline>
<polyline clip-path="url(#clip900)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="300.724,1592.38 2640.76,1592.38 "></polyline>
<polyline clip-path="url(#clip900)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="300.724,1592.38 300.724,1573.49 "></polyline>
<polyline clip-path="url(#clip900)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="766.259,1592.38 766.259,1573.49 "></polyline>
<polyline clip-path="url(#clip900)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="1231.79,1592.38 1231.79,1573.49 "></polyline>
<polyline clip-path="url(#clip900)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="1697.33,1592.38 1697.33,1573.49 "></polyline>
<polyline clip-path="url(#clip900)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="2162.86,1592.38 2162.86,1573.49 "></polyline>
<polyline clip-path="url(#clip900)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="2628.4,1592.38 2628.4,1573.49 "></polyline>
<path clip-path="url(#clip900)" d="M300.724 1625.61 Q297.113 1625.61 295.285 1629.17 Q293.479 1632.71 293.479 1639.84 Q293.479 1646.95 295.285 1650.51 Q297.113 1654.06 300.724 1654.06 Q304.359 1654.06 306.164 1650.51 Q307.993 1646.95 307.993 1639.84 Q307.993 1632.71 306.164 1629.17 Q304.359 1625.61 300.724 1625.61 M300.724 1621.9 Q306.535 1621.9 309.59 1626.51 Q312.669 1631.09 312.669 1639.84 Q312.669 1648.57 309.59 1653.18 Q306.535 1657.76 300.724 1657.76 Q294.914 1657.76 291.836 1653.18 Q288.78 1648.57 288.78 1639.84 Q288.78 1631.09 291.836 1626.51 Q294.914 1621.9 300.724 1621.9 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M756.537 1622.53 L774.893 1622.53 L774.893 1626.46 L760.819 1626.46 L760.819 1634.94 Q761.838 1634.59 762.856 1634.43 Q763.875 1634.24 764.893 1634.24 Q770.68 1634.24 774.06 1637.41 Q777.439 1640.58 777.439 1646 Q777.439 1651.58 773.967 1654.68 Q770.495 1657.76 764.176 1657.76 Q762 1657.76 759.731 1657.39 Q757.486 1657.02 755.078 1656.28 L755.078 1651.58 Q757.162 1652.71 759.384 1653.27 Q761.606 1653.82 764.083 1653.82 Q768.088 1653.82 770.426 1651.72 Q772.763 1649.61 772.763 1646 Q772.763 1642.39 770.426 1640.28 Q768.088 1638.18 764.083 1638.18 Q762.208 1638.18 760.333 1638.59 Q758.481 1639.01 756.537 1639.89 L756.537 1622.53 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M1206.48 1653.15 L1214.12 1653.15 L1214.12 1626.79 L1205.81 1628.45 L1205.81 1624.2 L1214.07 1622.53 L1218.75 1622.53 L1218.75 1653.15 L1226.39 1653.15 L1226.39 1657.09 L1206.48 1657.09 L1206.48 1653.15 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M1245.83 1625.61 Q1242.22 1625.61 1240.39 1629.17 Q1238.59 1632.71 1238.59 1639.84 Q1238.59 1646.95 1240.39 1650.51 Q1242.22 1654.06 1245.83 1654.06 Q1249.47 1654.06 1251.27 1650.51 Q1253.1 1646.95 1253.1 1639.84 Q1253.1 1632.71 1251.27 1629.17 Q1249.47 1625.61 1245.83 1625.61 M1245.83 1621.9 Q1251.64 1621.9 1254.7 1626.51 Q1257.78 1631.09 1257.78 1639.84 Q1257.78 1648.57 1254.7 1653.18 Q1251.64 1657.76 1245.83 1657.76 Q1240.02 1657.76 1236.94 1653.18 Q1233.89 1648.57 1233.89 1639.84 Q1233.89 1631.09 1236.94 1626.51 Q1240.02 1621.9 1245.83 1621.9 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M1672.51 1653.15 L1680.15 1653.15 L1680.15 1626.79 L1671.84 1628.45 L1671.84 1624.2 L1680.11 1622.53 L1684.78 1622.53 L1684.78 1653.15 L1692.42 1653.15 L1692.42 1657.09 L1672.51 1657.09 L1672.51 1653.15 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M1701.91 1622.53 L1720.27 1622.53 L1720.27 1626.46 L1706.19 1626.46 L1706.19 1634.94 Q1707.21 1634.59 1708.23 1634.43 Q1709.25 1634.24 1710.27 1634.24 Q1716.05 1634.24 1719.43 1637.41 Q1722.81 1640.58 1722.81 1646 Q1722.81 1651.58 1719.34 1654.68 Q1715.87 1657.76 1709.55 1657.76 Q1707.37 1657.76 1705.11 1657.39 Q1702.86 1657.02 1700.45 1656.28 L1700.45 1651.58 Q1702.54 1652.71 1704.76 1653.27 Q1706.98 1653.82 1709.46 1653.82 Q1713.46 1653.82 1715.8 1651.72 Q1718.14 1649.61 1718.14 1646 Q1718.14 1642.39 1715.8 1640.28 Q1713.46 1638.18 1709.46 1638.18 Q1707.58 1638.18 1705.71 1638.59 Q1703.86 1639.01 1701.91 1639.89 L1701.91 1622.53 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M2141.64 1653.15 L2157.95 1653.15 L2157.95 1657.09 L2136.01 1657.09 L2136.01 1653.15 Q2138.67 1650.4 2143.26 1645.77 Q2147.86 1641.12 2149.04 1639.77 Q2151.29 1637.25 2152.17 1635.51 Q2153.07 1633.76 2153.07 1632.07 Q2153.07 1629.31 2151.13 1627.57 Q2149.2 1625.84 2146.1 1625.84 Q2143.9 1625.84 2141.45 1626.6 Q2139.02 1627.37 2136.24 1628.92 L2136.24 1624.2 Q2139.07 1623.06 2141.52 1622.48 Q2143.97 1621.9 2146.01 1621.9 Q2151.38 1621.9 2154.58 1624.59 Q2157.77 1627.27 2157.77 1631.76 Q2157.77 1633.89 2156.96 1635.82 Q2156.17 1637.71 2154.07 1640.31 Q2153.49 1640.98 2150.39 1644.2 Q2147.28 1647.39 2141.64 1653.15 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M2177.77 1625.61 Q2174.16 1625.61 2172.33 1629.17 Q2170.52 1632.71 2170.52 1639.84 Q2170.52 1646.95 2172.33 1650.51 Q2174.16 1654.06 2177.77 1654.06 Q2181.4 1654.06 2183.21 1650.51 Q2185.04 1646.95 2185.04 1639.84 Q2185.04 1632.71 2183.21 1629.17 Q2181.4 1625.61 2177.77 1625.61 M2177.77 1621.9 Q2183.58 1621.9 2186.64 1626.51 Q2189.71 1631.09 2189.71 1639.84 Q2189.71 1648.57 2186.64 1653.18 Q2183.58 1657.76 2177.77 1657.76 Q2171.96 1657.76 2168.88 1653.18 Q2165.83 1648.57 2165.83 1639.84 Q2165.83 1631.09 2168.88 1626.51 Q2171.96 1621.9 2177.77 1621.9 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M2607.67 1653.15 L2623.99 1653.15 L2623.99 1657.09 L2602.04 1657.09 L2602.04 1653.15 Q2604.7 1650.4 2609.29 1645.77 Q2613.89 1641.12 2615.08 1639.77 Q2617.32 1637.25 2618.2 1635.51 Q2619.1 1633.76 2619.1 1632.07 Q2619.1 1629.31 2617.16 1627.57 Q2615.24 1625.84 2612.14 1625.84 Q2609.94 1625.84 2607.48 1626.6 Q2605.05 1627.37 2602.27 1628.92 L2602.27 1624.2 Q2605.1 1623.06 2607.55 1622.48 Q2610.01 1621.9 2612.04 1621.9 Q2617.41 1621.9 2620.61 1624.59 Q2623.8 1627.27 2623.8 1631.76 Q2623.8 1633.89 2622.99 1635.82 Q2622.2 1637.71 2620.1 1640.31 Q2619.52 1640.98 2616.42 1644.2 Q2613.32 1647.39 2607.67 1653.15 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M2633.85 1622.53 L2652.2 1622.53 L2652.2 1626.46 L2638.13 1626.46 L2638.13 1634.94 Q2639.15 1634.59 2640.17 1634.43 Q2641.19 1634.24 2642.2 1634.24 Q2647.99 1634.24 2651.37 1637.41 Q2654.75 1640.58 2654.75 1646 Q2654.75 1651.58 2651.28 1654.68 Q2647.81 1657.76 2641.49 1657.76 Q2639.31 1657.76 2637.04 1657.39 Q2634.8 1657.02 2632.39 1656.28 L2632.39 1651.58 Q2634.47 1652.71 2636.7 1653.27 Q2638.92 1653.82 2641.39 1653.82 Q2645.4 1653.82 2647.74 1651.72 Q2650.07 1649.61 2650.07 1646 Q2650.07 1642.39 2647.74 1640.28 Q2645.4 1638.18 2641.39 1638.18 Q2639.52 1638.18 2637.64 1638.59 Q2635.79 1639.01 2633.85 1639.89 L2633.85 1622.53 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M1469.8 1695.8 L1469.8 1705.92 L1481.86 1705.92 L1481.86 1710.47 L1469.8 1710.47 L1469.8 1729.82 Q1469.8 1734.18 1470.98 1735.43 Q1472.19 1736.67 1475.85 1736.67 L1481.86 1736.67 L1481.86 1741.57 L1475.85 1741.57 Q1469.07 1741.57 1466.49 1739.05 Q1463.91 1736.51 1463.91 1729.82 L1463.91 1710.47 L1459.62 1710.47 L1459.62 1705.92 L1463.91 1705.92 L1463.91 1695.8 L1469.8 1695.8 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><polyline clip-path="url(#clip900)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="300.724,1592.38 300.724,127.792 "></polyline>
<polyline clip-path="url(#clip900)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="300.724,1550.93 319.622,1550.93 "></polyline>
<polyline clip-path="url(#clip900)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="300.724,1228.66 319.622,1228.66 "></polyline>
<polyline clip-path="url(#clip900)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="300.724,906.387 319.622,906.387 "></polyline>
<polyline clip-path="url(#clip900)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="300.724,584.114 319.622,584.114 "></polyline>
<polyline clip-path="url(#clip900)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="300.724,261.84 319.622,261.84 "></polyline>
<path clip-path="url(#clip900)" d="M203.229 1536.73 Q199.618 1536.73 197.789 1540.3 Q195.983 1543.84 195.983 1550.97 Q195.983 1558.08 197.789 1561.64 Q199.618 1565.18 203.229 1565.18 Q206.863 1565.18 208.669 1561.64 Q210.497 1558.08 210.497 1550.97 Q210.497 1543.84 208.669 1540.3 Q206.863 1536.73 203.229 1536.73 M203.229 1533.03 Q209.039 1533.03 212.094 1537.64 Q215.173 1542.22 215.173 1550.97 Q215.173 1559.7 212.094 1564.3 Q209.039 1568.89 203.229 1568.89 Q197.419 1568.89 194.34 1564.3 Q191.284 1559.7 191.284 1550.97 Q191.284 1542.22 194.34 1537.64 Q197.419 1533.03 203.229 1533.03 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M223.391 1562.33 L228.275 1562.33 L228.275 1568.21 L223.391 1568.21 L223.391 1562.33 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M248.46 1536.73 Q244.849 1536.73 243.02 1540.3 Q241.215 1543.84 241.215 1550.97 Q241.215 1558.08 243.02 1561.64 Q244.849 1565.18 248.46 1565.18 Q252.094 1565.18 253.9 1561.64 Q255.729 1558.08 255.729 1550.97 Q255.729 1543.84 253.9 1540.3 Q252.094 1536.73 248.46 1536.73 M248.46 1533.03 Q254.27 1533.03 257.326 1537.64 Q260.404 1542.22 260.404 1550.97 Q260.404 1559.7 257.326 1564.3 Q254.27 1568.89 248.46 1568.89 Q242.65 1568.89 239.571 1564.3 Q236.516 1559.7 236.516 1550.97 Q236.516 1542.22 239.571 1537.64 Q242.65 1533.03 248.46 1533.03 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M204.224 1214.46 Q200.613 1214.46 198.784 1218.02 Q196.979 1221.57 196.979 1228.7 Q196.979 1235.8 198.784 1239.37 Q200.613 1242.91 204.224 1242.91 Q207.858 1242.91 209.664 1239.37 Q211.493 1235.8 211.493 1228.7 Q211.493 1221.57 209.664 1218.02 Q207.858 1214.46 204.224 1214.46 M204.224 1210.76 Q210.034 1210.76 213.09 1215.36 Q216.169 1219.95 216.169 1228.7 Q216.169 1237.42 213.09 1242.03 Q210.034 1246.61 204.224 1246.61 Q198.414 1246.61 195.335 1242.03 Q192.28 1237.42 192.28 1228.7 Q192.28 1219.95 195.335 1215.36 Q198.414 1210.76 204.224 1210.76 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M224.386 1240.06 L229.27 1240.06 L229.27 1245.94 L224.386 1245.94 L224.386 1240.06 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M239.502 1211.38 L257.858 1211.38 L257.858 1215.32 L243.784 1215.32 L243.784 1223.79 Q244.803 1223.44 245.821 1223.28 Q246.84 1223.09 247.858 1223.09 Q253.645 1223.09 257.025 1226.26 Q260.404 1229.44 260.404 1234.85 Q260.404 1240.43 256.932 1243.53 Q253.46 1246.61 247.141 1246.61 Q244.965 1246.61 242.696 1246.24 Q240.451 1245.87 238.043 1245.13 L238.043 1240.43 Q240.127 1241.57 242.349 1242.12 Q244.571 1242.68 247.048 1242.68 Q251.053 1242.68 253.391 1240.57 Q255.729 1238.46 255.729 1234.85 Q255.729 1231.24 253.391 1229.14 Q251.053 1227.03 247.048 1227.03 Q245.173 1227.03 243.298 1227.45 Q241.446 1227.86 239.502 1228.74 L239.502 1211.38 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M194.039 919.732 L201.678 919.732 L201.678 893.366 L193.368 895.033 L193.368 890.774 L201.632 889.107 L206.307 889.107 L206.307 919.732 L213.946 919.732 L213.946 923.667 L194.039 923.667 L194.039 919.732 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M223.391 917.788 L228.275 917.788 L228.275 923.667 L223.391 923.667 L223.391 917.788 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M248.46 892.186 Q244.849 892.186 243.02 895.751 Q241.215 899.292 241.215 906.422 Q241.215 913.528 243.02 917.093 Q244.849 920.635 248.46 920.635 Q252.094 920.635 253.9 917.093 Q255.729 913.528 255.729 906.422 Q255.729 899.292 253.9 895.751 Q252.094 892.186 248.46 892.186 M248.46 888.482 Q254.27 888.482 257.326 893.089 Q260.404 897.672 260.404 906.422 Q260.404 915.149 257.326 919.755 Q254.27 924.338 248.46 924.338 Q242.65 924.338 239.571 919.755 Q236.516 915.149 236.516 906.422 Q236.516 897.672 239.571 893.089 Q242.65 888.482 248.46 888.482 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M195.034 597.459 L202.673 597.459 L202.673 571.093 L194.363 572.76 L194.363 568.5 L202.627 566.834 L207.303 566.834 L207.303 597.459 L214.942 597.459 L214.942 601.394 L195.034 601.394 L195.034 597.459 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M224.386 595.514 L229.27 595.514 L229.27 601.394 L224.386 601.394 L224.386 595.514 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M239.502 566.834 L257.858 566.834 L257.858 570.769 L243.784 570.769 L243.784 579.241 Q244.803 578.894 245.821 578.732 Q246.84 578.547 247.858 578.547 Q253.645 578.547 257.025 581.718 Q260.404 584.889 260.404 590.306 Q260.404 595.884 256.932 598.986 Q253.46 602.065 247.141 602.065 Q244.965 602.065 242.696 601.695 Q240.451 601.324 238.043 600.583 L238.043 595.884 Q240.127 597.019 242.349 597.574 Q244.571 598.13 247.048 598.13 Q251.053 598.13 253.391 596.023 Q255.729 593.917 255.729 590.306 Q255.729 586.695 253.391 584.588 Q251.053 582.482 247.048 582.482 Q245.173 582.482 243.298 582.898 Q241.446 583.315 239.502 584.195 L239.502 566.834 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M197.257 275.185 L213.576 275.185 L213.576 279.12 L191.632 279.12 L191.632 275.185 Q194.294 272.43 198.877 267.801 Q203.483 263.148 204.664 261.806 Q206.909 259.282 207.789 257.546 Q208.692 255.787 208.692 254.097 Q208.692 251.343 206.747 249.607 Q204.826 247.87 201.724 247.87 Q199.525 247.87 197.071 248.634 Q194.641 249.398 191.863 250.949 L191.863 246.227 Q194.687 245.093 197.141 244.514 Q199.595 243.935 201.632 243.935 Q207.002 243.935 210.196 246.62 Q213.391 249.306 213.391 253.796 Q213.391 255.926 212.581 257.847 Q211.794 259.745 209.687 262.338 Q209.108 263.009 206.007 266.227 Q202.905 269.421 197.257 275.185 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M223.391 273.241 L228.275 273.241 L228.275 279.12 L223.391 279.12 L223.391 273.241 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M248.46 247.639 Q244.849 247.639 243.02 251.204 Q241.215 254.745 241.215 261.875 Q241.215 268.981 243.02 272.546 Q244.849 276.088 248.46 276.088 Q252.094 276.088 253.9 272.546 Q255.729 268.981 255.729 261.875 Q255.729 254.745 253.9 251.204 Q252.094 247.639 248.46 247.639 M248.46 243.935 Q254.27 243.935 257.326 248.542 Q260.404 253.125 260.404 261.875 Q260.404 270.602 257.326 275.208 Q254.27 279.792 248.46 279.792 Q242.65 279.792 239.571 275.208 Q236.516 270.602 236.516 261.875 Q236.516 253.125 239.571 248.542 Q242.65 243.935 248.46 243.935 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M1184.06 20.1573 L1172.96 50.2555 L1195.2 50.2555 L1184.06 20.1573 M1179.44 12.096 L1188.72 12.096 L1211.77 72.576 L1203.26 72.576 L1197.75 57.061 L1170.49 57.061 L1164.98 72.576 L1156.35 72.576 L1179.44 12.096 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M1253.85 65.7705 L1253.85 89.8329 L1246.36 89.8329 L1246.36 27.2059 L1253.85 27.2059 L1253.85 34.0924 Q1256.2 30.0415 1259.77 28.0971 Q1263.37 26.1121 1268.36 26.1121 Q1276.62 26.1121 1281.77 32.6746 Q1286.95 39.2371 1286.95 49.9314 Q1286.95 60.6258 1281.77 67.1883 Q1276.62 73.7508 1268.36 73.7508 Q1263.37 73.7508 1259.77 71.8063 Q1256.2 69.8214 1253.85 65.7705 M1279.21 49.9314 Q1279.21 41.7081 1275.81 37.0496 Q1272.45 32.3505 1266.53 32.3505 Q1260.62 32.3505 1257.22 37.0496 Q1253.85 41.7081 1253.85 49.9314 Q1253.85 58.1548 1257.22 62.8538 Q1260.62 67.5124 1266.53 67.5124 Q1272.45 67.5124 1275.81 62.8538 Q1279.21 58.1548 1279.21 49.9314 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M1316.89 32.4315 Q1310.89 32.4315 1307.41 37.1306 Q1303.92 41.7891 1303.92 49.9314 Q1303.92 58.0738 1307.37 62.7728 Q1310.85 67.4314 1316.89 67.4314 Q1322.84 67.4314 1326.33 62.7323 Q1329.81 58.0333 1329.81 49.9314 Q1329.81 41.8701 1326.33 37.1711 Q1322.84 32.4315 1316.89 32.4315 M1316.89 26.1121 Q1326.61 26.1121 1332.16 32.4315 Q1337.71 38.7509 1337.71 49.9314 Q1337.71 61.0714 1332.16 67.4314 Q1326.61 73.7508 1316.89 73.7508 Q1307.12 73.7508 1301.57 67.4314 Q1296.07 61.0714 1296.07 49.9314 Q1296.07 38.7509 1301.57 32.4315 Q1307.12 26.1121 1316.89 26.1121 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M1367.64 32.4315 Q1361.65 32.4315 1358.17 37.1306 Q1354.68 41.7891 1354.68 49.9314 Q1354.68 58.0738 1358.13 62.7728 Q1361.61 67.4314 1367.64 67.4314 Q1373.6 67.4314 1377.08 62.7323 Q1380.57 58.0333 1380.57 49.9314 Q1380.57 41.8701 1377.08 37.1711 Q1373.6 32.4315 1367.64 32.4315 M1367.64 26.1121 Q1377.37 26.1121 1382.92 32.4315 Q1388.47 38.7509 1388.47 49.9314 Q1388.47 61.0714 1382.92 67.4314 Q1377.37 73.7508 1367.64 73.7508 Q1357.88 73.7508 1352.33 67.4314 Q1346.82 61.0714 1346.82 49.9314 Q1346.82 38.7509 1352.33 32.4315 Q1357.88 26.1121 1367.64 26.1121 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M1400.82 9.54393 L1408.28 9.54393 L1408.28 72.576 L1400.82 72.576 L1400.82 9.54393 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M1467.82 32.4315 Q1461.83 32.4315 1458.34 37.1306 Q1454.86 41.7891 1454.86 49.9314 Q1454.86 58.0738 1458.3 62.7728 Q1461.79 67.4314 1467.82 67.4314 Q1473.78 67.4314 1477.26 62.7323 Q1480.75 58.0333 1480.75 49.9314 Q1480.75 41.8701 1477.26 37.1711 Q1473.78 32.4315 1467.82 32.4315 M1467.82 26.1121 Q1477.55 26.1121 1483.1 32.4315 Q1488.65 38.7509 1488.65 49.9314 Q1488.65 61.0714 1483.1 67.4314 Q1477.55 73.7508 1467.82 73.7508 Q1458.06 73.7508 1452.51 67.4314 Q1447 61.0714 1447 49.9314 Q1447 38.7509 1452.51 32.4315 Q1458.06 26.1121 1467.82 26.1121 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M1523.97 9.54393 L1523.97 15.7418 L1516.84 15.7418 Q1512.83 15.7418 1511.25 17.3622 Q1509.71 18.9825 1509.71 23.1955 L1509.71 27.2059 L1521.98 27.2059 L1521.98 32.9987 L1509.71 32.9987 L1509.71 72.576 L1502.22 72.576 L1502.22 32.9987 L1495.09 32.9987 L1495.09 27.2059 L1502.22 27.2059 L1502.22 24.0462 Q1502.22 16.471 1505.74 13.0277 Q1509.26 9.54393 1516.92 9.54393 L1523.97 9.54393 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M1552.24 27.2059 L1559.7 27.2059 L1569.02 62.6108 L1578.29 27.2059 L1587.08 27.2059 L1596.4 62.6108 L1605.68 27.2059 L1613.13 27.2059 L1601.26 72.576 L1592.47 72.576 L1582.71 35.3887 L1572.9 72.576 L1564.11 72.576 L1552.24 27.2059 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M1645.05 49.7694 Q1636.02 49.7694 1632.53 51.8354 Q1629.05 53.9013 1629.05 58.8839 Q1629.05 62.8538 1631.64 65.2034 Q1634.28 67.5124 1638.77 67.5124 Q1644.97 67.5124 1648.7 63.1374 Q1652.46 58.7219 1652.46 51.4303 L1652.46 49.7694 L1645.05 49.7694 M1659.92 46.6907 L1659.92 72.576 L1652.46 72.576 L1652.46 65.6895 Q1649.91 69.8214 1646.1 71.8063 Q1642.3 73.7508 1636.79 73.7508 Q1629.82 73.7508 1625.69 69.8619 Q1621.6 65.9325 1621.6 59.3701 Q1621.6 51.7138 1626.7 47.825 Q1631.84 43.9361 1642.01 43.9361 L1652.46 43.9361 L1652.46 43.2069 Q1652.46 38.0623 1649.06 35.2672 Q1645.7 32.4315 1639.58 32.4315 Q1635.69 32.4315 1632.01 33.3632 Q1628.32 34.295 1624.92 36.1584 L1624.92 29.2718 Q1629.01 27.692 1632.86 26.9223 Q1636.71 26.1121 1640.35 26.1121 Q1650.2 26.1121 1655.06 31.2163 Q1659.92 36.3204 1659.92 46.6907 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M1682.64 14.324 L1682.64 27.2059 L1698 27.2059 L1698 32.9987 L1682.64 32.9987 L1682.64 57.6282 Q1682.64 63.1779 1684.14 64.7578 Q1685.68 66.3376 1690.34 66.3376 L1698 66.3376 L1698 72.576 L1690.34 72.576 Q1681.71 72.576 1678.43 69.3758 Q1675.15 66.1351 1675.15 57.6282 L1675.15 32.9987 L1669.68 32.9987 L1669.68 27.2059 L1675.15 27.2059 L1675.15 14.324 L1682.64 14.324 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M1746.61 48.0275 L1746.61 51.6733 L1712.34 51.6733 Q1712.82 59.3701 1716.95 63.421 Q1721.13 67.4314 1728.54 67.4314 Q1732.83 67.4314 1736.84 66.3781 Q1740.89 65.3249 1744.86 63.2184 L1744.86 70.267 Q1740.85 71.9684 1736.64 72.8596 Q1732.43 73.7508 1728.09 73.7508 Q1717.24 73.7508 1710.88 67.4314 Q1704.56 61.1119 1704.56 50.3365 Q1704.56 39.1965 1710.55 32.6746 Q1716.59 26.1121 1726.8 26.1121 Q1735.95 26.1121 1741.26 32.0264 Q1746.61 37.9003 1746.61 48.0275 M1739.15 45.84 Q1739.07 39.7232 1735.71 36.0774 Q1732.39 32.4315 1726.88 32.4315 Q1720.64 32.4315 1716.87 35.9558 Q1713.15 39.4801 1712.58 45.8805 L1739.15 45.84 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M1785.13 34.1734 Q1783.88 33.4443 1782.38 33.1202 Q1780.92 32.7556 1779.14 32.7556 Q1772.82 32.7556 1769.41 36.8875 Q1766.05 40.9789 1766.05 48.6757 L1766.05 72.576 L1758.56 72.576 L1758.56 27.2059 L1766.05 27.2059 L1766.05 34.2544 Q1768.4 30.1225 1772.17 28.1376 Q1775.94 26.1121 1781.32 26.1121 Q1782.09 26.1121 1783.02 26.2337 Q1783.96 26.3147 1785.09 26.5172 L1785.13 34.1734 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><polyline clip-path="url(#clip902)" style="stroke:#009af9; stroke-linecap:round; stroke-linejoin:round; stroke-width:8; stroke-opacity:1; fill:none" points="300.724,1550.93 303.067,1542.76 305.409,1534.43 307.752,1525.97 310.094,1517.37 312.436,1508.64 314.779,1499.76 317.121,1490.76 319.463,1481.62 321.806,1472.35 324.148,1462.95 326.491,1453.42 328.833,1443.77 331.175,1434 333.518,1424.11 335.86,1414.11 338.202,1403.99 340.545,1393.76 342.887,1383.42 345.23,1372.98 347.572,1362.44 349.914,1351.79 352.257,1341.05 354.599,1330.22 356.941,1319.3 359.284,1308.3 361.626,1297.21 363.969,1286.05 366.311,1274.81 368.653,1263.5 370.996,1252.13 373.338,1240.69 375.68,1229.19 378.023,1217.64 380.365,1206.04 382.707,1194.39 385.05,1182.7 387.392,1170.98 389.735,1159.22 392.077,1147.43 394.419,1135.62 396.762,1123.78 399.104,1111.94 401.446,1100.08 403.789,1088.21 406.131,1076.35 408.474,1064.48 410.816,1052.63 413.158,1040.78 415.501,1028.96 417.843,1017.15 420.185,1005.37 422.528,993.626 424.87,981.914 427.213,970.242 429.555,958.615 431.897,947.038 434.24,935.515 436.582,924.05 438.924,912.649 441.267,901.315 443.609,890.055 445.952,878.871 448.294,867.769 450.636,856.754 452.979,845.83 455.321,835.001 457.663,824.272 460.006,813.646 462.348,803.128 464.691,792.723 467.033,782.434 469.375,772.267 471.718,762.224 474.06,752.311 476.402,742.531 478.745,732.888 481.087,723.385 483.43,714.027 485.772,704.817 488.114,695.759 490.457,686.856 492.799,678.111 495.141,669.528 497.484,661.109 499.826,652.859 502.169,644.78 504.511,636.875 506.853,629.146 509.196,621.598 511.538,614.232 513.88,607.051 516.223,600.058 518.565,593.254 520.908,586.644 523.25,580.228 525.592,574.009 527.935,567.988 530.277,562.169 532.619,556.551 534.962,551.137 537.304,545.929 539.647,540.928 541.989,536.134 544.331,531.55 546.674,527.176 549.016,523.013 551.358,519.063 553.701,515.325 556.043,511.8 558.386,508.489 560.728,505.392 563.07,502.509 565.413,499.841 567.755,497.387 570.097,495.147 572.44,493.121 574.782,491.308 577.125,489.708 579.467,488.321 581.809,487.145 584.152,486.179 586.494,485.423 588.836,484.875 591.179,484.535 593.521,484.4 595.864,484.47 598.206,484.742 600.548,485.215 602.891,485.887 605.233,486.756 607.575,487.82 609.918,489.077 612.26,490.524 614.603,492.159 616.945,493.982 619.287,495.988 621.63,498.175 623.972,500.54 626.314,503.079 628.657,505.79 630.999,508.668 633.341,511.711 635.684,514.916 638.026,518.277 640.369,521.793 642.711,525.459 645.053,529.272 647.396,533.228 649.738,537.324 652.08,541.554 654.423,545.916 656.765,550.406 659.108,555.019 661.45,559.752 663.792,564.599 666.135,569.558 668.477,574.624 670.819,579.792 673.162,585.058 675.504,590.418 677.847,595.867 680.189,601.401 682.531,607.014 684.874,612.703 687.216,618.462 689.558,624.288 691.901,630.174 694.243,636.116 696.586,642.109 698.928,648.149 701.27,654.229 703.613,660.345 705.955,666.492 708.297,672.664 710.64,678.856 712.982,685.063 715.325,691.279 717.667,697.498 720.009,703.719 722.352,709.936 724.694,716.146 727.036,722.342 729.379,728.52 731.721,734.673 734.064,740.796 736.406,746.885 738.748,752.935 741.091,758.939 743.433,764.894 745.775,770.795 748.118,776.636 750.46,782.414 752.803,788.123 755.145,793.759 757.487,799.318 759.83,804.795 762.172,810.185 764.514,815.485 766.857,820.691 769.199,825.798 771.542,830.802 773.884,835.7 776.226,840.488 778.569,845.161 780.911,849.716 783.253,854.15 785.596,858.459 787.938,862.64 790.281,866.689 792.623,870.603 794.965,874.378 797.308,878.012 799.65,881.501 801.992,884.843 804.335,888.034 806.677,891.072 809.02,893.954 811.362,896.677 813.704,899.238 816.047,901.636 818.389,903.867 820.731,905.93 823.074,907.821 825.416,909.539 827.759,911.082 830.101,912.447 832.443,913.633 834.786,914.637 837.128,915.459 839.47,916.099 841.813,916.554 844.155,916.826 846.498,916.911 848.84,916.811 851.182,916.524 853.525,916.05 855.867,915.389 858.209,914.54 860.552,913.503 862.894,912.278 865.237,910.866 867.579,909.266 869.921,907.48 872.264,905.507 874.606,903.348 876.948,901.003 879.291,898.474 881.633,895.762 883.976,892.867 886.318,889.791 888.66,886.535 891.003,883.101 893.345,879.489 895.687,875.701 898.03,871.741 900.372,867.608 902.714,863.305 905.057,858.834 907.399,854.198 909.742,849.399 912.084,844.439 914.426,839.32 916.769,834.046 919.111,828.619 921.453,823.042 923.796,817.318 926.138,811.451 928.481,805.443 930.823,799.298 933.165,793.019 935.508,786.61 937.85,780.075 940.192,773.417 942.535,766.64 944.877,759.749 947.22,752.743 949.562,745.625 951.904,738.4 954.247,731.073 956.589,723.649 958.931,716.133 961.274,708.529 963.616,700.843 965.959,693.079 968.301,685.242 970.643,677.337 972.986,669.369 975.328,661.343 977.67,653.263 980.013,645.134 982.355,636.961 984.698,628.749 987.04,620.502 989.382,612.225 991.725,603.923 994.067,595.601 996.409,587.262 998.752,578.913 1001.09,570.557 1003.44,562.2 1005.78,553.845 1008.12,545.498 1010.46,537.163 1012.81,528.845 1015.15,520.548 1017.49,512.277 1019.83,504.036 1022.18,495.83 1024.52,487.664 1026.86,479.542 1029.2,471.468 1031.55,463.448 1033.89,455.485 1036.23,447.584 1038.57,439.75 1040.91,431.986 1043.26,424.298 1045.6,416.69 1047.94,409.166 1050.28,401.731 1052.63,394.389 1054.97,387.144 1057.31,380.001 1059.65,372.965 1062,366.038 1064.34,359.227 1066.68,352.535 1069.02,345.966 1071.37,339.525 1073.71,333.216 1076.05,327.044 1078.39,321.012 1080.73,315.124 1083.08,309.386 1085.42,303.801 1087.76,298.373 1090.1,293.101 1092.45,287.986 1094.79,283.033 1097.13,278.243 1099.47,273.62 1101.82,269.166 1104.16,264.885 1106.5,260.777 1108.84,256.847 1111.19,253.096 1113.53,249.525 1115.87,246.138 1118.21,242.936 1120.56,239.92 1122.9,237.093 1125.24,234.455 1127.58,232.008 1129.92,229.754 1132.27,227.694 1134.61,225.828 1136.95,224.157 1139.29,222.682 1141.64,221.405 1143.98,220.325 1146.32,219.442 1148.66,218.757 1151.01,218.271 1153.35,217.983 1155.69,217.893 1158.03,218.001 1160.38,218.307 1162.72,218.81 1165.06,219.51 1167.4,220.405 1169.75,221.496 1172.09,222.781 1174.43,224.259 1176.77,225.929 1179.11,227.79 1181.46,229.841 1183.8,232.079 1186.14,234.503 1188.48,237.112 1190.83,239.903 1193.17,242.875 1195.51,246.025 1197.85,249.351 1200.2,252.851 1202.54,256.522 1204.88,260.361 1207.22,264.367 1209.57,268.536 1211.91,272.864 1214.25,277.35 1216.59,281.992 1218.93,286.79 1221.28,291.74 1223.62,296.837 1225.96,302.079 1228.3,307.459 1230.65,312.975 1232.99,318.621 1235.33,324.394 1237.67,330.288 1240.02,336.3 1242.36,342.425 1244.7,348.659 1247.04,354.997 1249.39,361.436 1251.73,367.97 1254.07,374.595 1256.41,381.307 1258.76,388.102 1261.1,394.974 1263.44,401.92 1265.78,408.934 1268.12,416.014 1270.47,423.153 1272.81,430.347 1275.15,437.593 1277.49,444.885 1279.84,452.219 1282.18,459.59 1284.52,466.994 1286.86,474.426 1289.21,481.882 1291.55,489.356 1293.89,496.846 1296.23,504.345 1298.58,511.849 1300.92,519.354 1303.26,526.855 1305.6,534.347 1307.95,541.825 1310.29,549.286 1312.63,556.724 1314.97,564.134 1317.31,571.512 1319.66,578.853 1322,586.153 1324.34,593.406 1326.68,600.608 1329.03,607.754 1331.37,614.84 1333.71,621.86 1336.05,628.81 1338.4,635.685 1340.74,642.48 1343.08,649.19 1345.42,655.811 1347.77,662.337 1350.11,668.765 1352.45,675.088 1354.79,681.302 1357.14,687.402 1359.48,693.384 1361.82,699.242 1364.16,704.971 1366.5,710.568 1368.85,716.034 1371.19,721.367 1373.53,726.563 1375.87,731.619 1378.22,736.53 1380.56,741.293 1382.9,745.906 1385.24,750.365 1387.59,754.667 1389.93,758.809 1392.27,762.788 1394.61,766.601 1396.96,770.247 1399.3,773.722 1401.64,777.024 1403.98,780.151 1406.32,783.102 1408.67,785.873 1411.01,788.463 1413.35,790.871 1415.69,793.094 1418.04,795.132 1420.38,796.982 1422.72,798.645 1425.06,800.118 1427.41,801.4 1429.75,802.491 1432.09,803.39 1434.43,804.096 1436.78,804.609 1439.12,804.928 1441.46,805.053 1443.8,804.984 1446.15,804.721 1448.49,804.264 1450.83,803.613 1453.17,802.768 1455.51,801.73 1457.86,800.499 1460.2,799.076 1462.54,797.463 1464.88,795.659 1467.23,793.665 1469.57,791.484 1471.91,789.115 1474.25,786.562 1476.6,783.824 1478.94,780.904 1481.28,777.804 1483.62,774.525 1485.97,771.069 1488.31,767.438 1490.65,763.635 1492.99,759.663 1495.34,755.522 1497.68,751.217 1500.02,746.749 1502.36,742.122 1504.7,737.339 1507.05,732.402 1509.39,727.315 1511.73,722.076 1514.07,716.689 1516.42,711.158 1518.76,705.486 1521.1,699.679 1523.44,693.74 1525.79,687.673 1528.13,681.484 1530.47,675.175 1532.81,668.753 1535.16,662.221 1537.5,655.583 1539.84,648.843 1542.18,642.007 1544.52,635.079 1546.87,628.062 1549.21,620.962 1551.55,613.783 1553.89,606.529 1556.24,599.205 1558.58,591.814 1560.92,584.363 1563.26,576.855 1565.61,569.294 1567.95,561.685 1570.29,554.034 1572.63,546.343 1574.98,538.618 1577.32,530.864 1579.66,523.084 1582,515.284 1584.35,507.468 1586.69,499.64 1589.03,491.806 1591.37,483.97 1593.71,476.136 1596.06,468.31 1598.4,460.495 1600.74,452.697 1603.08,444.92 1605.43,437.169 1607.77,429.448 1610.11,421.763 1612.45,414.118 1614.8,406.517 1617.14,398.966 1619.48,391.47 1621.82,384.032 1624.17,376.658 1626.51,369.353 1628.85,362.121 1631.19,354.968 1633.54,347.897 1635.88,340.915 1638.22,334.025 1640.56,327.233 1642.9,320.543 1645.25,313.961 1647.59,307.491 1649.93,301.138 1652.27,294.908 1654.62,288.804 1656.96,282.83 1659.3,276.985 1661.64,271.271 1663.99,265.693 1666.33,260.255 1668.67,254.96 1671.01,249.812 1673.36,244.813 1675.7,239.968 1678.04,235.279 1680.38,230.75 1682.72,226.382 1685.07,222.18 1687.41,218.146 1689.75,214.281 1692.09,210.589 1694.44,207.072 1696.78,203.733 1699.12,200.572 1701.46,197.592 1703.81,194.795 1706.15,192.183 1708.49,189.757 1710.83,187.518 1713.18,185.469 1715.52,183.609 1717.86,181.941 1720.2,180.465 1722.55,179.182 1724.89,178.093 1727.23,177.198 1729.57,176.499 1731.91,175.994 1734.26,175.685 1736.6,175.572 1738.94,175.655 1741.28,175.933 1743.63,176.407 1745.97,177.076 1748.31,177.94 1750.65,178.997 1753,180.249 1755.34,181.692 1757.68,183.328 1760.02,185.154 1762.37,187.169 1764.71,189.373 1767.05,191.763 1769.39,194.339 1771.74,197.098 1774.08,200.039 1776.42,203.16 1778.76,206.459 1781.1,209.934 1783.45,213.582 1785.79,217.402 1788.13,221.39 1790.47,225.545 1792.82,229.863 1795.16,234.341 1797.5,238.977 1799.84,243.768 1802.19,248.71 1804.53,253.8 1806.87,259.035 1809.21,264.411 1811.56,269.925 1813.9,275.578 1816.24,281.369 1818.58,287.291 1820.93,293.341 1823.27,299.512 1825.61,305.802 1827.95,312.204 1830.29,318.715 1832.64,325.328 1834.98,332.04 1837.32,338.846 1839.66,345.741 1842.01,352.721 1844.35,359.78 1846.69,366.914 1849.03,374.118 1851.38,381.388 1853.72,388.718 1856.06,396.105 1858.4,403.543 1860.75,411.028 1863.09,418.555 1865.43,426.119 1867.77,433.717 1870.11,441.342 1872.46,448.991 1874.8,456.66 1877.14,464.342 1879.48,472.034 1881.83,479.732 1884.17,487.43 1886.51,495.124 1888.85,502.809 1891.2,510.481 1893.54,518.136 1895.88,525.768 1898.22,533.373 1900.57,540.947 1902.91,548.486 1905.25,555.983 1907.59,563.436 1909.94,570.84 1912.28,578.189 1914.62,585.48 1916.96,592.709 1919.3,599.869 1921.65,606.959 1923.99,613.971 1926.33,620.903 1928.67,627.75 1931.02,634.508 1933.36,641.171 1935.7,647.736 1938.04,654.198 1940.39,660.552 1942.73,666.795 1945.07,672.922 1947.41,678.929 1949.76,684.81 1952.1,690.563 1954.44,696.182 1956.78,701.663 1959.13,707.001 1961.47,712.193 1963.81,717.235 1966.15,722.121 1968.49,726.847 1970.84,731.415 1973.18,735.823 1975.52,740.071 1977.86,744.154 1980.21,748.07 1982.55,751.817 1984.89,755.392 1987.23,758.794 1989.58,762.019 1991.92,765.066 1994.26,767.932 1996.6,770.617 1998.95,773.118 2001.29,775.434 2003.63,777.564 2005.97,779.505 2008.31,781.257 2010.66,782.819 2013,784.19 2015.34,785.368 2017.68,786.354 2020.03,787.146 2022.37,787.744 2024.71,788.147 2027.05,788.356 2029.4,788.37 2031.74,788.189 2034.08,787.814 2036.42,787.243 2038.77,786.478 2041.11,785.52 2043.45,784.368 2045.79,783.023 2048.14,781.487 2050.48,779.759 2052.82,777.842 2055.16,775.735 2057.5,773.441 2059.85,770.961 2062.19,768.296 2064.53,765.447 2066.87,762.418 2069.22,759.208 2071.56,755.822 2073.9,752.259 2076.24,748.523 2078.59,744.616 2080.93,740.541 2083.27,736.299 2085.61,731.894 2087.96,727.328 2090.3,722.604 2092.64,717.726 2094.98,712.696 2097.33,707.517 2099.67,702.194 2102.01,696.729 2104.35,691.126 2106.69,685.389 2109.04,679.522 2111.38,673.528 2113.72,667.411 2116.06,661.177 2118.41,654.829 2120.75,648.371 2123.09,641.808 2125.43,635.144 2127.78,628.374 2130.12,621.504 2132.46,614.54 2134.8,607.486 2137.15,600.348 2139.49,593.132 2141.83,585.843 2144.17,578.486 2146.52,571.066 2148.86,563.59 2151.2,556.061 2153.54,548.486 2155.88,540.869 2158.23,533.216 2160.57,525.531 2162.91,517.819 2165.25,510.087 2167.6,502.338 2169.94,494.577 2172.28,486.81 2174.62,479.04 2176.97,471.274 2179.31,463.516 2181.65,455.77 2183.99,448.042 2186.34,440.335 2188.68,432.655 2191.02,425.006 2193.36,417.392 2195.7,409.819 2198.05,402.29 2200.39,394.811 2202.73,387.385 2205.07,380.017 2207.42,372.711 2209.76,365.471 2212.1,358.302 2214.44,351.208 2216.79,344.193 2219.13,337.262 2221.47,330.417 2223.81,323.664 2226.16,317.007 2228.5,310.449 2230.84,303.994 2233.18,297.647 2235.53,291.411 2237.87,285.29 2240.21,279.287 2242.55,273.408 2244.89,267.654 2247.24,262.031 2249.58,256.541 2251.92,251.189 2254.26,245.977 2256.61,240.91 2258.95,235.99 2261.29,231.223 2263.63,226.61 2265.98,222.155 2268.32,217.861 2270.66,213.733 2273,209.773 2275.35,205.984 2277.69,202.37 2280.03,198.933 2282.37,195.678 2284.72,192.606 2287.06,189.722 2289.4,187.026 2291.74,184.516 2294.08,182.193 2296.43,180.059 2298.77,178.114 2301.11,176.359 2303.45,174.796 2305.8,173.424 2308.14,172.245 2310.48,171.26 2312.82,170.468 2315.17,169.87 2317.51,169.467 2319.85,169.257 2322.19,169.243 2324.54,169.423 2326.88,169.797 2329.22,170.364 2331.56,171.126 2333.9,172.08 2336.25,173.227 2338.59,174.565 2340.93,176.094 2343.27,177.814 2345.62,179.722 2347.96,181.817 2350.3,184.1 2352.64,186.567 2354.99,189.218 2357.33,192.051 2359.67,195.065 2362.01,198.257 2364.36,201.626 2366.7,205.17 2369.04,208.886 2371.38,212.773 2373.73,216.828 2376.07,221.049 2378.41,225.432 2380.75,229.977 2383.09,234.679 2385.44,239.536 2387.78,244.545 2390.12,249.703 2392.46,255.007 2394.81,260.453 2397.15,266.038 2399.49,271.759 2401.83,277.612 2404.18,283.594 2406.52,289.699 2408.86,295.926 2411.2,302.269 2413.55,308.724 2415.89,315.288 2418.23,321.956 2420.57,328.723 2422.92,335.585 2425.26,342.537 2427.6,349.575 2429.94,356.693 2432.28,363.887 2434.63,371.151 2436.97,378.481 2439.31,385.87 2441.65,393.315 2444,400.808 2446.34,408.354 2448.68,415.953 2451.02,423.599 2453.37,431.286 2455.71,439.008 2458.05,446.757 2460.39,454.529 2462.74,462.317 2465.08,470.116 2467.42,477.919 2469.76,485.722 2472.1,493.518 2474.45,501.301 2476.79,509.067 2479.13,516.81 2481.47,524.525 2483.82,532.206 2486.16,539.849 2488.5,547.448 2490.84,554.999 2493.19,562.495 2495.53,569.934 2497.87,577.31 2500.21,584.618 2502.56,591.853 2504.9,599.012 2507.24,606.09 2509.58,613.083 2511.93,619.986 2514.27,626.795 2516.61,633.506 2518.95,640.116 2521.29,646.62 2523.64,653.014 2525.98,659.295 2528.32,665.46 2530.66,671.503 2533.01,677.423 2535.35,683.216 2537.69,688.877 2540.03,694.405 2542.38,699.796 2544.72,705.046 2547.06,710.154 2549.4,715.115 2551.75,719.928 2554.09,724.588 2556.43,729.095 2558.77,733.444 2561.12,737.634 2563.46,741.662 2565.8,745.526 2568.14,749.223 2570.48,752.752 2572.83,756.11 2575.17,759.296 2577.51,762.306 2579.85,765.14 2582.2,767.796 2584.54,770.272 2586.88,772.566 2589.22,774.677 2591.57,776.604 2593.91,778.345 2596.25,779.898 2598.59,781.263 2600.94,782.439 2603.28,783.424 2605.62,784.217 2607.96,784.819 2610.31,785.227 2612.65,785.441 2614.99,785.461 2617.33,785.286 2619.67,784.915 2622.02,784.349 2624.36,783.586 2626.7,782.628 2629.04,781.472 2631.39,780.12 2633.73,778.572 2636.07,776.827 2638.41,774.887 2640.76,772.75 "></polyline>
<path clip-path="url(#clip900)" d="M2195.67 1543.56 L2562.75 1543.56 L2562.75 1439.88 L2195.67 1439.88  Z" fill="#ffffff" fill-rule="evenodd" fill-opacity="1"></path>
<polyline clip-path="url(#clip900)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="2195.67,1543.56 2562.75,1543.56 2562.75,1439.88 2195.67,1439.88 2195.67,1543.56 "></polyline>
<polyline clip-path="url(#clip900)" style="stroke:#009af9; stroke-linecap:round; stroke-linejoin:round; stroke-width:8; stroke-opacity:1; fill:none" points="2221.67,1491.72 2377.68,1491.72 "></polyline>
<path clip-path="url(#clip900)" d="M2403.68 1483.08 L2407.94 1483.08 L2413.26 1503.31 L2418.56 1483.08 L2423.58 1483.08 L2428.91 1503.31 L2434.21 1483.08 L2438.47 1483.08 L2431.69 1509 L2426.66 1509 L2421.08 1487.76 L2415.48 1509 L2410.46 1509 L2403.68 1483.08 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M2456.71 1495.97 Q2451.55 1495.97 2449.56 1497.15 Q2447.57 1498.33 2447.57 1501.18 Q2447.57 1503.45 2449.05 1504.79 Q2450.55 1506.11 2453.12 1506.11 Q2456.66 1506.11 2458.79 1503.61 Q2460.94 1501.09 2460.94 1496.92 L2460.94 1495.97 L2456.71 1495.97 M2465.2 1494.21 L2465.2 1509 L2460.94 1509 L2460.94 1505.07 Q2459.49 1507.43 2457.31 1508.57 Q2455.13 1509.68 2451.99 1509.68 Q2448 1509.68 2445.64 1507.45 Q2443.31 1505.21 2443.31 1501.46 Q2443.31 1497.08 2446.22 1494.86 Q2449.16 1492.64 2454.97 1492.64 L2460.94 1492.64 L2460.94 1492.22 Q2460.94 1489.28 2459 1487.69 Q2457.08 1486.07 2453.58 1486.07 Q2451.36 1486.07 2449.25 1486.6 Q2447.15 1487.13 2445.2 1488.19 L2445.2 1484.26 Q2447.54 1483.36 2449.74 1482.92 Q2451.94 1482.45 2454.02 1482.45 Q2459.65 1482.45 2462.43 1485.37 Q2465.2 1488.29 2465.2 1494.21 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M2478.19 1475.72 L2478.19 1483.08 L2486.96 1483.08 L2486.96 1486.39 L2478.19 1486.39 L2478.19 1500.46 Q2478.19 1503.63 2479.05 1504.54 Q2479.93 1505.44 2482.59 1505.44 L2486.96 1505.44 L2486.96 1509 L2482.59 1509 Q2477.66 1509 2475.78 1507.18 Q2473.91 1505.32 2473.91 1500.46 L2473.91 1486.39 L2470.78 1486.39 L2470.78 1483.08 L2473.91 1483.08 L2473.91 1475.72 L2478.19 1475.72 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M2514.74 1494.98 L2514.74 1497.06 L2495.16 1497.06 Q2495.44 1501.46 2497.8 1503.77 Q2500.18 1506.07 2504.42 1506.07 Q2506.87 1506.07 2509.16 1505.46 Q2511.48 1504.86 2513.75 1503.66 L2513.75 1507.69 Q2511.45 1508.66 2509.05 1509.17 Q2506.64 1509.68 2504.16 1509.68 Q2497.96 1509.68 2494.32 1506.07 Q2490.71 1502.45 2490.71 1496.3 Q2490.71 1489.93 2494.14 1486.2 Q2497.59 1482.45 2503.42 1482.45 Q2508.65 1482.45 2511.69 1485.83 Q2514.74 1489.19 2514.74 1494.98 M2510.48 1493.73 Q2510.44 1490.23 2508.51 1488.15 Q2506.62 1486.07 2503.47 1486.07 Q2499.9 1486.07 2497.75 1488.08 Q2495.62 1490.09 2495.3 1493.75 L2510.48 1493.73 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip900)" d="M2536.75 1487.06 Q2536.04 1486.64 2535.18 1486.46 Q2534.35 1486.25 2533.33 1486.25 Q2529.72 1486.25 2527.77 1488.61 Q2525.85 1490.95 2525.85 1495.35 L2525.85 1509 L2521.57 1509 L2521.57 1483.08 L2525.85 1483.08 L2525.85 1487.11 Q2527.19 1484.75 2529.35 1483.61 Q2531.5 1482.45 2534.58 1482.45 Q2535.02 1482.45 2535.55 1482.52 Q2536.08 1482.57 2536.73 1482.69 L2536.75 1487.06 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path></svg>
</div>
</div>
<p>For the inspired reader, here are some suggested exercises: - Adjust the parameters <img src="https://latex.codecogs.com/png.latex?%5Calpha"> and <img src="https://latex.codecogs.com/png.latex?%5Cbeta">. - Change the primitive evaporation system so that it is also sinusoidal. Explore what happens when the periods align like in humid subtropics (rainy summer, dry winter) or anti-align like in Mediterranean climates (rainy winter, dry summer). - Suppose there is a person with a hose and a drain who is attempting to keep precisely 2 liters of water in the pool. Add a third resource sharer to the composite, which models this hose/drain system. Suggested dynamics are <img src="https://latex.codecogs.com/png.latex?%5Cdot%20w_h%20=%20%5Cgamma(2%20-%20w_h)."></p>
</section>
</section>
<section id="complex-compositions" class="level2">
<h2 class="anchored" data-anchor-id="complex-compositions">Complex compositions</h2>
<p>Careful bookkeeping is endemic to implementing a complicated composition pattern. Previously we applied <a href="../../../../post/2021/01/machines/#composition_patterns_from_graphs">pullback functorial data migration</a> in order to construct complex composition patterns more easily and with less room for error. In this post, we give two more strategies, which both rely on the rich structure of the composition syntax: 1. <strong>Hierarchical composition</strong>, in which a primitive system can itself be a composition of systems. Hierarchical composition is extremely useful when we want to divide and conquer or when we want to build upon a composite system without starting from scratch. This strategy is only available in open composition syntaxes such as <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSch%7D(%5Cmathsf%7BUWD%7D)">, <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSch%7D(%5Cmathsf%7BDWD%7D)">, <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSch%7D(%5Cmathsf%7BOpenCPG%7D)">. 2. <strong>Taking (co)limits of composition patterns.</strong> This strategy is available in all of the composition syntaxes discussed so far.</p>
<p>We will demonstrate these two strategies as we construct a complex ecosystem with six species: rabbits, foxes, hawks, little fish, big fish, and sharks.</p>
<section id="divide-and-conquer" class="level3">
<h3 class="anchored" data-anchor-id="divide-and-conquer">Divide and conquer</h3>
<p>First we will apply hierarchical composition so that we don’t have to simultaneously study all of the interactions between the six species. We will separately model the three sub-ecosystems — land, air, and water — which may themselves be compositions of even more primitive system. Once we have constructed these sub-systems, we will compose them according to the following pattern:</p>
<div id="14" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb5-1">eco_pattern <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@relation</span> (rabbits, foxes, hawks, littlefish, bigfish, sharks) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb5-2">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">land_eco</span>(rabbits, foxes, hawks)</span>
<span id="cb5-3">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">air_eco</span>(hawks, littlefish)</span>
<span id="cb5-4">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ocean_eco</span>(littlefish, bigfish, sharks)</span>
<span id="cb5-5"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
</details>
</div>
<div id="16" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/01/resource_sharers/index_files/figure-html/cell-9-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>In other words, there aren’t two independent hawk populations for the land and air sub-ecosystems. So in the final model we identify the hawk population from the land ecosystem and the hawk population from the air ecosystem. Likewise, for little fish.</p>
</section>
<section id="land" class="level3">
<h3 class="anchored" data-anchor-id="land">Land</h3>
<p>Let’s zoom-in on the land ecosystem. We have five primitive systems which share variables: 1. rabbit growth: <img src="https://latex.codecogs.com/png.latex?%5Cdot%20r(t)%20=%20%5Calpha_1%20r(t)"> 2. rabbit/fox predation: <img src="https://latex.codecogs.com/png.latex?%5Cdot%20r(t)%20=%20-%5Cbeta_1%20r(t)%20f(t),%5C;%20%5Cdot%20f(t)%20=%20%5Cgamma_1%20r(t)f(t)"> 3. fox decline: <img src="https://latex.codecogs.com/png.latex?%5Cdot%20f(t)%20=%20-%5Cdelta_1%20f(t)"> 4. rabbit/hawk predation: <img src="https://latex.codecogs.com/png.latex?%5Cdot%20r(t)%20=%20-%5Cbeta_2%20r(t)h(t),%5C;%20%5Cdot%20h(t)%20=%20%5Cgamma_2%20r(t)h(t)"> 5. hawk decline: <img src="https://latex.codecogs.com/png.latex?%5Cdot%20h(t)%20=%20-%5Cdelta_2%20h(t)"></p>
<p>Therefore, the desired composition pattern has five boxes and many ports and wires to keep track of. Instead of implementing this composition pattern by hand, we construct it as a pushout of two simpler composition patterns — one which represents the rabbit/fox interactions and one which represents the rabbit/hawk interactions.</p>
<p>For the rabbit/fox composition pattern note that there are not two independent rabbit populations — one that grows and one that gets eaten by foxes. Likewise, there are not two independent fox populations — one that declines and one that feasts on rabbits. To capture these interactions, we identify the two rabbit populations and identify the two fox populations via the following composition pattern.</p>
<div id="18" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb6-1">rabbitfox_pattern <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@relation</span> (rabbits, foxes) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb6-2">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rabbit_growth</span>(rabbits)</span>
<span id="cb6-3">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rabbit_fox_predation</span>(rabbits,foxes)</span>
<span id="cb6-4">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fox_decline</span>(foxes)</span>
<span id="cb6-5"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
</details>
</div>
<div id="20" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/01/resource_sharers/index_files/figure-html/cell-11-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>The rabbit/hawk composition pattern is identical.</p>
<div id="22" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb7-1">rabbithawk_pattern <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@relation</span> (rabbits, hawks) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span></span>
<span id="cb7-2">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rabbit_growth</span>(rabbits)</span>
<span id="cb7-3">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rabbit_hawk_predation</span>(rabbits,hawks)</span>
<span id="cb7-4">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">hawk_decline</span>(hawks)</span>
<span id="cb7-5"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
</details>
</div>
<p>Now we construct the complete composition pattern for the land ecosystem by gluing these two composition patterns along the box corresponding to rabbit growth.</p>
<div id="24" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb8-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab.CategoricalAlgebra</span></span>
<span id="cb8-2"></span>
<span id="cb8-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define the composition pattern for rabbit growth</span></span>
<span id="cb8-4">rabbit_pattern <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@relation</span> (rabbits,) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rabbit_growth</span>(rabbits)</span>
<span id="cb8-5"></span>
<span id="cb8-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define transformations between the composition patterns</span></span>
<span id="cb8-7">rabbitfox_transform  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ACSetTransformation</span>((Box<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], Junction<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], Port<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], OuterPort<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]), rabbit_pattern, rabbitfox_pattern)</span>
<span id="cb8-8">rabbithawk_transform <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ACSetTransformation</span>((Box<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], Junction<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], Port<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], OuterPort<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]), rabbit_pattern, rabbithawk_pattern)</span>
<span id="cb8-9"></span>
<span id="cb8-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Take the pushout</span></span>
<span id="cb8-11">land_pattern <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ob</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pushout</span>(rabbitfox_transform, rabbithawk_transform))</span></code></pre></div>
</details>
</div>
<div id="26" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/01/resource_sharers/index_files/figure-html/cell-14-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>Phew! After seeing the complexity of this composition pattern, we are grateful that we used a pushout instead of constructing it by hand. Lastly, we define the primitive systems and compose.</p>
<div id="28" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb9-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dotr</span>(u,p,t)  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> p.α₁<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>u</span>
<span id="cb9-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dotrf</span>(u,p,t) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>p.β₁<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>u[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>u[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>], p.γ₁<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>u[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>u[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]]</span>
<span id="cb9-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dotf</span>(u,p,t)  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>p.δ₁<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>u</span>
<span id="cb9-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dotrh</span>(u, p, t) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>p.β₂<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>u[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>u[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>], p.γ₂<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>u[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>u[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]]</span>
<span id="cb9-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">doth</span>(u, p, t)  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>p.δ₂<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>u</span>
<span id="cb9-6"></span>
<span id="cb9-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define the primitive systems</span></span>
<span id="cb9-8">rabbit_growth       <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ContinuousResourceSharer</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{Float64}</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, dotr,  [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])</span>
<span id="cb9-9">rabbitfox_predation <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ContinuousResourceSharer</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{Float64}</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, dotrf, [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>])</span>
<span id="cb9-10">fox_decline         <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ContinuousResourceSharer</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{Float64}</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, dotf,  [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])</span>
<span id="cb9-11">rabbithawk_predation<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ContinuousResourceSharer</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{Float64}</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, dotrh, [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>])</span>
<span id="cb9-12">hawk_decline        <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ContinuousResourceSharer</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{Float64}</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, doth,  [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])</span>
<span id="cb9-13"></span>
<span id="cb9-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Compose</span></span>
<span id="cb9-15">land_sys<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">oapply</span>(land_pattern, [rabbit_growth, rabbitfox_predation, fox_decline, rabbithawk_predation, hawk_decline]);</span></code></pre></div>
</details>
</div>
<p>The resource sharer <code>land_sys</code> models the land ecosystem. Although it will play the role of a primitive system in our total ecosystem, we see that it is a composite itself. This structure — primitive systems themselves being composites — is the essence of hierarchical composition.</p>
</section>
<section id="air" class="level3">
<h3 class="anchored" data-anchor-id="air">Air</h3>
<p>The air ecosystem is straightforwardly defined by the following resource sharer which models hawk/little fish predation. Here we don’t model the decay of hawks or the growth of little fish because these processes are already accounted for in the land and water ecosystems. The air ecosystem is a pure coupling term between the two systems.</p>
<div id="30" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb10-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dothf</span>(u,p,t) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [p.γ₃<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>u[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>u[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>], <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>p.β₃<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>u[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>u[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]]</span>
<span id="cb10-2">air_sys <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ContinuousResourceSharer</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{Float64}</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, dothf, [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]);</span></code></pre></div>
</details>
</div>
</section>
<section id="water" class="level3">
<h3 class="anchored" data-anchor-id="water">Water</h3>
<p>In the <a href="../../../../post/2021/01/machines/#example_three_species_ecosystem">previous post</a>, we defined a ocean ecosystem as the directed composition of machines. In this aquatic foodchain, sharks eat big fish and big fish eat little fish. We can turn the machine representing this ocean ecosystem into a resource sharer as follows.</p>
<div id="34" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb11-1">water_sys <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ContinuousResourceSharer</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{Float64}</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, (u,p,t)<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">-&gt;eval_dynamics</span>(ocean_sys, u, [], p, t));</span></code></pre></div>
</details>
</div>
</section>
<section id="putting-it-all-together" class="level3">
<h3 class="anchored" data-anchor-id="putting-it-all-together">Putting it all together</h3>
<p>Now that we have constructed resource sharers for the three sub-ecosystems, we are ready to plug them into the established composition pattern, <code>eco_pattern</code>.</p>
<div id="36" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb12-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Compose</span></span>
<span id="cb12-2">eco_system <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">oapply</span>(eco_pattern, [land_sys, air_sys, water_sys])</span>
<span id="cb12-3"></span>
<span id="cb12-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Plot and solve</span></span>
<span id="cb12-5">u0 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">100.0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">50.0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">20.0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.0</span>]</span>
<span id="cb12-6">params <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">LVector</span>(</span>
<span id="cb12-7">    α₁ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, β₁ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.015</span>, γ₁ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.015</span>, δ₁ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>, β₂ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">.01</span>, γ₂ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">.01</span>, δ₂ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">.5</span>,  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># land params</span></span>
<span id="cb12-8">    γ₃ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.001</span>, β₃ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.003</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># air params</span></span>
<span id="cb12-9">    α₄ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.35</span>, β₄ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.015</span>, γ₄ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.015</span>, δ₄ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>, β₅ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.017</span>, γ₅ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.017</span>, δ₅ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.35</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># water params</span></span>
<span id="cb12-10">)</span>
<span id="cb12-11">tspan <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">75.0</span>)</span>
<span id="cb12-12">prob <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ODEProblem</span>(eco_system, u0, tspan, params)</span>
<span id="cb12-13">sol <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">solve</span>(prob, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Tsit5</span>())</span>
<span id="cb12-14"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(sol, lw<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, label <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rabbits"</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"foxes"</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"hawks"</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"little fish"</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"big fish"</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sharks"</span>])</span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="1">
<!--?xml version="1.0" encoding="utf-8"?-->
<svg xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" width="672" height="480" viewbox="0 0 2688 1920">
<defs>
  <clippath id="clip960">
    <rect x="0" y="0" width="2688" height="1920"></rect>
  </clippath>
</defs>
<path clip-path="url(#clip960)" d="M0 1920 L2688 1920 L2688 0 L0 0  Z" fill="#ffffff" fill-rule="evenodd" fill-opacity="1"></path>
<defs>
  <clippath id="clip961">
    <rect x="537" y="0" width="1883" height="1883"></rect>
  </clippath>
</defs>
<path clip-path="url(#clip960)" d="M172.001 1734.12 L2640.76 1734.12 L2640.76 47.2441 L172.001 47.2441  Z" fill="#ffffff" fill-rule="evenodd" fill-opacity="1"></path>
<defs>
  <clippath id="clip962">
    <rect x="172" y="47" width="2470" height="1688"></rect>
  </clippath>
</defs>
<polyline clip-path="url(#clip962)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="172.001,1734.12 172.001,47.2441 "></polyline>
<polyline clip-path="url(#clip962)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="994.92,1734.12 994.92,47.2441 "></polyline>
<polyline clip-path="url(#clip962)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="1817.84,1734.12 1817.84,47.2441 "></polyline>
<polyline clip-path="url(#clip962)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="2640.76,1734.12 2640.76,47.2441 "></polyline>
<polyline clip-path="url(#clip962)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="172.001,1690.22 2640.76,1690.22 "></polyline>
<polyline clip-path="url(#clip962)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="172.001,1398.27 2640.76,1398.27 "></polyline>
<polyline clip-path="url(#clip962)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="172.001,1106.32 2640.76,1106.32 "></polyline>
<polyline clip-path="url(#clip962)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="172.001,814.375 2640.76,814.375 "></polyline>
<polyline clip-path="url(#clip962)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="172.001,522.428 2640.76,522.428 "></polyline>
<polyline clip-path="url(#clip962)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="172.001,230.481 2640.76,230.481 "></polyline>
<polyline clip-path="url(#clip960)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="172.001,1734.12 2640.76,1734.12 "></polyline>
<polyline clip-path="url(#clip960)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="172.001,1734.12 172.001,1715.22 "></polyline>
<polyline clip-path="url(#clip960)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="994.92,1734.12 994.92,1715.22 "></polyline>
<polyline clip-path="url(#clip960)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="1817.84,1734.12 1817.84,1715.22 "></polyline>
<polyline clip-path="url(#clip960)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="2640.76,1734.12 2640.76,1715.22 "></polyline>
<path clip-path="url(#clip960)" d="M172.001 1767.34 Q168.39 1767.34 166.562 1770.9 Q164.756 1774.45 164.756 1781.58 Q164.756 1788.68 166.562 1792.25 Q168.39 1795.79 172.001 1795.79 Q175.636 1795.79 177.441 1792.25 Q179.27 1788.68 179.27 1781.58 Q179.27 1774.45 177.441 1770.9 Q175.636 1767.34 172.001 1767.34 M172.001 1763.64 Q177.811 1763.64 180.867 1768.24 Q183.946 1772.83 183.946 1781.58 Q183.946 1790.3 180.867 1794.91 Q177.811 1799.49 172.001 1799.49 Q166.191 1799.49 163.112 1794.91 Q160.057 1790.3 160.057 1781.58 Q160.057 1772.83 163.112 1768.24 Q166.191 1763.64 172.001 1763.64 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M974.19 1794.89 L990.51 1794.89 L990.51 1798.82 L968.565 1798.82 L968.565 1794.89 Q971.228 1792.13 975.811 1787.5 Q980.417 1782.85 981.598 1781.51 Q983.843 1778.98 984.723 1777.25 Q985.626 1775.49 985.626 1773.8 Q985.626 1771.04 983.681 1769.31 Q981.76 1767.57 978.658 1767.57 Q976.459 1767.57 974.005 1768.34 Q971.575 1769.1 968.797 1770.65 L968.797 1765.93 Q971.621 1764.79 974.075 1764.21 Q976.528 1763.64 978.565 1763.64 Q983.936 1763.64 987.13 1766.32 Q990.325 1769.01 990.325 1773.5 Q990.325 1775.63 989.514 1777.55 Q988.727 1779.45 986.621 1782.04 Q986.042 1782.71 982.94 1785.93 Q979.839 1789.12 974.19 1794.89 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M1000.37 1764.26 L1018.73 1764.26 L1018.73 1768.2 L1004.65 1768.2 L1004.65 1776.67 Q1005.67 1776.32 1006.69 1776.16 Q1007.71 1775.97 1008.73 1775.97 Q1014.51 1775.97 1017.89 1779.15 Q1021.27 1782.32 1021.27 1787.73 Q1021.27 1793.31 1017.8 1796.41 Q1014.33 1799.49 1008.01 1799.49 Q1005.83 1799.49 1003.57 1799.12 Q1001.32 1798.75 998.913 1798.01 L998.913 1793.31 Q1001 1794.45 1003.22 1795 Q1005.44 1795.56 1007.92 1795.56 Q1011.92 1795.56 1014.26 1793.45 Q1016.6 1791.34 1016.6 1787.73 Q1016.6 1784.12 1014.26 1782.02 Q1011.92 1779.91 1007.92 1779.91 Q1006.04 1779.91 1004.17 1780.33 Q1002.32 1780.74 1000.37 1781.62 L1000.37 1764.26 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M1792.54 1764.26 L1810.89 1764.26 L1810.89 1768.2 L1796.82 1768.2 L1796.82 1776.67 Q1797.84 1776.32 1798.86 1776.16 Q1799.87 1775.97 1800.89 1775.97 Q1806.68 1775.97 1810.06 1779.15 Q1813.44 1782.32 1813.44 1787.73 Q1813.44 1793.31 1809.97 1796.41 Q1806.5 1799.49 1800.18 1799.49 Q1798 1799.49 1795.73 1799.12 Q1793.49 1798.75 1791.08 1798.01 L1791.08 1793.31 Q1793.16 1794.45 1795.38 1795 Q1797.61 1795.56 1800.08 1795.56 Q1804.09 1795.56 1806.43 1793.45 Q1808.76 1791.34 1808.76 1787.73 Q1808.76 1784.12 1806.43 1782.02 Q1804.09 1779.91 1800.08 1779.91 Q1798.21 1779.91 1796.33 1780.33 Q1794.48 1780.74 1792.54 1781.62 L1792.54 1764.26 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M1832.65 1767.34 Q1829.04 1767.34 1827.21 1770.9 Q1825.41 1774.45 1825.41 1781.58 Q1825.41 1788.68 1827.21 1792.25 Q1829.04 1795.79 1832.65 1795.79 Q1836.29 1795.79 1838.09 1792.25 Q1839.92 1788.68 1839.92 1781.58 Q1839.92 1774.45 1838.09 1770.9 Q1836.29 1767.34 1832.65 1767.34 M1832.65 1763.64 Q1838.46 1763.64 1841.52 1768.24 Q1844.6 1772.83 1844.6 1781.58 Q1844.6 1790.3 1841.52 1794.91 Q1838.46 1799.49 1832.65 1799.49 Q1826.84 1799.49 1823.76 1794.91 Q1820.71 1790.3 1820.71 1781.58 Q1820.71 1772.83 1823.76 1768.24 Q1826.84 1763.64 1832.65 1763.64 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M2614.61 1764.26 L2636.83 1764.26 L2636.83 1766.25 L2624.29 1798.82 L2619.4 1798.82 L2631.21 1768.2 L2614.61 1768.2 L2614.61 1764.26 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M2646 1764.26 L2664.36 1764.26 L2664.36 1768.2 L2650.28 1768.2 L2650.28 1776.67 Q2651.3 1776.32 2652.32 1776.16 Q2653.34 1775.97 2654.36 1775.97 Q2660.14 1775.97 2663.52 1779.15 Q2666.9 1782.32 2666.9 1787.73 Q2666.9 1793.31 2663.43 1796.41 Q2659.96 1799.49 2653.64 1799.49 Q2651.46 1799.49 2649.19 1799.12 Q2646.95 1798.75 2644.54 1798.01 L2644.54 1793.31 Q2646.62 1794.45 2648.85 1795 Q2651.07 1795.56 2653.55 1795.56 Q2657.55 1795.56 2659.89 1793.45 Q2662.23 1791.34 2662.23 1787.73 Q2662.23 1784.12 2659.89 1782.02 Q2657.55 1779.91 2653.55 1779.91 Q2651.67 1779.91 2649.8 1780.33 Q2647.94 1780.74 2646 1781.62 L2646 1764.26 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M1405.44 1837.53 L1405.44 1847.65 L1417.5 1847.65 L1417.5 1852.2 L1405.44 1852.2 L1405.44 1871.56 Q1405.44 1875.92 1406.62 1877.16 Q1407.83 1878.4 1411.49 1878.4 L1417.5 1878.4 L1417.5 1883.3 L1411.49 1883.3 Q1404.71 1883.3 1402.13 1880.79 Q1399.55 1878.24 1399.55 1871.56 L1399.55 1852.2 L1395.25 1852.2 L1395.25 1847.65 L1399.55 1847.65 L1399.55 1837.53 L1405.44 1837.53 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><polyline clip-path="url(#clip960)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="172.001,1734.12 172.001,47.2441 "></polyline>
<polyline clip-path="url(#clip960)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="172.001,1690.22 190.899,1690.22 "></polyline>
<polyline clip-path="url(#clip960)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="172.001,1398.27 190.899,1398.27 "></polyline>
<polyline clip-path="url(#clip960)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="172.001,1106.32 190.899,1106.32 "></polyline>
<polyline clip-path="url(#clip960)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="172.001,814.375 190.899,814.375 "></polyline>
<polyline clip-path="url(#clip960)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="172.001,522.428 190.899,522.428 "></polyline>
<polyline clip-path="url(#clip960)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="172.001,230.481 190.899,230.481 "></polyline>
<path clip-path="url(#clip960)" d="M119.737 1676.01 Q116.126 1676.01 114.297 1679.58 Q112.492 1683.12 112.492 1690.25 Q112.492 1697.36 114.297 1700.92 Q116.126 1704.46 119.737 1704.46 Q123.371 1704.46 125.177 1700.92 Q127.005 1697.36 127.005 1690.25 Q127.005 1683.12 125.177 1679.58 Q123.371 1676.01 119.737 1676.01 M119.737 1672.31 Q125.547 1672.31 128.603 1676.92 Q131.681 1681.5 131.681 1690.25 Q131.681 1698.98 128.603 1703.58 Q125.547 1708.17 119.737 1708.17 Q113.927 1708.17 110.848 1703.58 Q107.793 1698.98 107.793 1690.25 Q107.793 1681.5 110.848 1676.92 Q113.927 1672.31 119.737 1672.31 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M84.5982 1411.61 L100.918 1411.61 L100.918 1415.55 L78.9733 1415.55 L78.9733 1411.61 Q81.6353 1408.86 86.2186 1404.23 Q90.8251 1399.58 92.0056 1398.23 Q94.251 1395.71 95.1306 1393.98 Q96.0334 1392.22 96.0334 1390.53 Q96.0334 1387.77 94.0889 1386.04 Q92.1676 1384.3 89.0658 1384.3 Q86.8667 1384.3 84.4131 1385.06 Q81.9825 1385.83 79.2047 1387.38 L79.2047 1382.66 Q82.0288 1381.52 84.4825 1380.94 Q86.9362 1380.36 88.9732 1380.36 Q94.3436 1380.36 97.538 1383.05 Q100.732 1385.73 100.732 1390.23 Q100.732 1392.35 99.9222 1394.28 Q99.1352 1396.17 97.0287 1398.77 Q96.45 1399.44 93.3482 1402.66 Q90.2464 1405.85 84.5982 1411.61 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M110.779 1380.99 L129.135 1380.99 L129.135 1384.92 L115.061 1384.92 L115.061 1393.4 Q116.08 1393.05 117.098 1392.89 Q118.117 1392.7 119.135 1392.7 Q124.922 1392.7 128.302 1395.87 Q131.681 1399.04 131.681 1404.46 Q131.681 1410.04 128.209 1413.14 Q124.737 1416.22 118.417 1416.22 Q116.242 1416.22 113.973 1415.85 Q111.728 1415.48 109.32 1414.74 L109.32 1410.04 Q111.404 1411.17 113.626 1411.73 Q115.848 1412.29 118.325 1412.29 Q122.33 1412.29 124.667 1410.18 Q127.005 1408.07 127.005 1404.46 Q127.005 1400.85 124.667 1398.74 Q122.33 1396.64 118.325 1396.64 Q116.45 1396.64 114.575 1397.05 Q112.723 1397.47 110.779 1398.35 L110.779 1380.99 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M79.6214 1089.04 L97.9778 1089.04 L97.9778 1092.98 L83.9038 1092.98 L83.9038 1101.45 Q84.9223 1101.1 85.9408 1100.94 Q86.9593 1100.76 87.9778 1100.76 Q93.7649 1100.76 97.1445 1103.93 Q100.524 1107.1 100.524 1112.51 Q100.524 1118.09 97.0519 1121.19 Q93.5797 1124.27 87.2603 1124.27 Q85.0843 1124.27 82.8158 1123.9 Q80.5705 1123.53 78.1631 1122.79 L78.1631 1118.09 Q80.2464 1119.23 82.4686 1119.78 Q84.6908 1120.34 87.1677 1120.34 Q91.1723 1120.34 93.5102 1118.23 Q95.8482 1116.13 95.8482 1112.51 Q95.8482 1108.9 93.5102 1106.8 Q91.1723 1104.69 87.1677 1104.69 Q85.2927 1104.69 83.4177 1105.11 Q81.5658 1105.52 79.6214 1106.4 L79.6214 1089.04 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M119.737 1092.12 Q116.126 1092.12 114.297 1095.69 Q112.492 1099.23 112.492 1106.36 Q112.492 1113.46 114.297 1117.03 Q116.126 1120.57 119.737 1120.57 Q123.371 1120.57 125.177 1117.03 Q127.005 1113.46 127.005 1106.36 Q127.005 1099.23 125.177 1095.69 Q123.371 1092.12 119.737 1092.12 M119.737 1088.42 Q125.547 1088.42 128.603 1093.02 Q131.681 1097.61 131.681 1106.36 Q131.681 1115.08 128.603 1119.69 Q125.547 1124.27 119.737 1124.27 Q113.927 1124.27 110.848 1119.69 Q107.793 1115.08 107.793 1106.36 Q107.793 1097.61 110.848 1093.02 Q113.927 1088.42 119.737 1088.42 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M79.3899 797.095 L101.612 797.095 L101.612 799.086 L89.0658 831.655 L84.1816 831.655 L95.9871 801.03 L79.3899 801.03 L79.3899 797.095 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M110.779 797.095 L129.135 797.095 L129.135 801.03 L115.061 801.03 L115.061 809.502 Q116.08 809.155 117.098 808.993 Q118.117 808.808 119.135 808.808 Q124.922 808.808 128.302 811.979 Q131.681 815.151 131.681 820.567 Q131.681 826.146 128.209 829.248 Q124.737 832.326 118.417 832.326 Q116.242 832.326 113.973 831.956 Q111.728 831.586 109.32 830.845 L109.32 826.146 Q111.404 827.28 113.626 827.836 Q115.848 828.391 118.325 828.391 Q122.33 828.391 124.667 826.285 Q127.005 824.178 127.005 820.567 Q127.005 816.956 124.667 814.85 Q122.33 812.743 118.325 812.743 Q116.45 812.743 114.575 813.16 Q112.723 813.577 110.779 814.456 L110.779 797.095 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M50.2234 535.773 L57.8623 535.773 L57.8623 509.407 L49.5521 511.074 L49.5521 506.815 L57.816 505.148 L62.4919 505.148 L62.4919 535.773 L70.1307 535.773 L70.1307 539.708 L50.2234 539.708 L50.2234 535.773 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M89.5751 508.227 Q85.964 508.227 84.1353 511.792 Q82.3297 515.333 82.3297 522.463 Q82.3297 529.569 84.1353 533.134 Q85.964 536.676 89.5751 536.676 Q93.2093 536.676 95.0148 533.134 Q96.8435 529.569 96.8435 522.463 Q96.8435 515.333 95.0148 511.792 Q93.2093 508.227 89.5751 508.227 M89.5751 504.523 Q95.3852 504.523 98.4408 509.13 Q101.519 513.713 101.519 522.463 Q101.519 531.19 98.4408 535.796 Q95.3852 540.379 89.5751 540.379 Q83.7649 540.379 80.6862 535.796 Q77.6307 531.19 77.6307 522.463 Q77.6307 513.713 80.6862 509.13 Q83.7649 504.523 89.5751 504.523 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M119.737 508.227 Q116.126 508.227 114.297 511.792 Q112.492 515.333 112.492 522.463 Q112.492 529.569 114.297 533.134 Q116.126 536.676 119.737 536.676 Q123.371 536.676 125.177 533.134 Q127.005 529.569 127.005 522.463 Q127.005 515.333 125.177 511.792 Q123.371 508.227 119.737 508.227 M119.737 504.523 Q125.547 504.523 128.603 509.13 Q131.681 513.713 131.681 522.463 Q131.681 531.19 128.603 535.796 Q125.547 540.379 119.737 540.379 Q113.927 540.379 110.848 535.796 Q107.793 531.19 107.793 522.463 Q107.793 513.713 110.848 509.13 Q113.927 504.523 119.737 504.523 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M51.2188 243.826 L58.8576 243.826 L58.8576 217.46 L50.5475 219.127 L50.5475 214.868 L58.8113 213.201 L63.4872 213.201 L63.4872 243.826 L71.1261 243.826 L71.1261 247.761 L51.2188 247.761 L51.2188 243.826 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M84.5982 243.826 L100.918 243.826 L100.918 247.761 L78.9733 247.761 L78.9733 243.826 Q81.6353 241.071 86.2186 236.442 Q90.8251 231.789 92.0056 230.446 Q94.251 227.923 95.1306 226.187 Q96.0334 224.428 96.0334 222.738 Q96.0334 219.983 94.0889 218.247 Q92.1676 216.511 89.0658 216.511 Q86.8667 216.511 84.4131 217.275 Q81.9825 218.039 79.2047 219.59 L79.2047 214.868 Q82.0288 213.733 84.4825 213.155 Q86.9362 212.576 88.9732 212.576 Q94.3436 212.576 97.538 215.261 Q100.732 217.946 100.732 222.437 Q100.732 224.567 99.9222 226.488 Q99.1352 228.386 97.0287 230.979 Q96.45 231.65 93.3482 234.868 Q90.2464 238.062 84.5982 243.826 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M110.779 213.201 L129.135 213.201 L129.135 217.136 L115.061 217.136 L115.061 225.608 Q116.08 225.261 117.098 225.099 Q118.117 224.914 119.135 224.914 Q124.922 224.914 128.302 228.085 Q131.681 231.257 131.681 236.673 Q131.681 242.252 128.209 245.354 Q124.737 248.432 118.417 248.432 Q116.242 248.432 113.973 248.062 Q111.728 247.692 109.32 246.951 L109.32 242.252 Q111.404 243.386 113.626 243.942 Q115.848 244.497 118.325 244.497 Q122.33 244.497 124.667 242.391 Q127.005 240.284 127.005 236.673 Q127.005 233.062 124.667 230.956 Q122.33 228.849 118.325 228.849 Q116.45 228.849 114.575 229.266 Q112.723 229.682 110.779 230.562 L110.779 213.201 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><polyline clip-path="url(#clip962)" style="stroke:#009af9; stroke-linecap:round; stroke-linejoin:round; stroke-width:8; stroke-opacity:1; fill:none" points="172.001,522.428 174.473,580.274 176.944,639.354 179.415,698.936 181.886,758.312 184.357,816.823 186.829,873.88 189.3,928.982 191.771,981.726 194.242,1031.8 196.714,1079.01 199.185,1123.22 201.656,1164.4 204.127,1202.55 206.598,1237.76 209.07,1270.13 211.541,1299.8 214.012,1326.94 216.483,1351.72 218.955,1374.3 221.426,1394.85 223.897,1413.54 226.368,1430.52 228.84,1445.96 231.311,1459.99 233.782,1472.74 236.253,1484.33 238.724,1494.87 241.196,1504.45 243.667,1513.16 246.138,1521.1 248.609,1528.32 251.081,1534.9 253.552,1540.89 256.023,1546.35 258.494,1551.33 260.965,1555.87 263.437,1560.01 265.908,1563.78 268.379,1567.21 270.85,1570.33 273.322,1573.16 275.793,1575.74 278.264,1578.07 280.735,1580.18 283.206,1582.09 285.678,1583.8 288.149,1585.34 290.62,1586.71 293.091,1587.92 295.563,1588.99 298.034,1589.93 300.505,1590.73 302.976,1591.41 305.448,1591.98 307.919,1592.44 310.39,1592.8 312.861,1593.06 315.332,1593.23 317.804,1593.31 320.275,1593.3 322.746,1593.21 325.217,1593.04 327.689,1592.79 330.16,1592.47 332.631,1592.08 335.102,1591.61 337.573,1591.08 340.045,1590.48 342.516,1589.81 344.987,1589.09 347.458,1588.29 349.93,1587.44 352.401,1586.52 354.872,1585.55 357.343,1584.51 359.814,1583.41 362.286,1582.25 364.757,1581.04 367.228,1579.76 369.699,1578.43 372.171,1577.03 374.642,1575.58 377.113,1574.07 379.584,1572.5 382.056,1570.87 384.527,1569.18 386.998,1567.43 389.469,1565.62 391.94,1563.75 394.412,1561.82 396.883,1559.82 399.354,1557.76 401.825,1555.64 404.297,1553.46 406.768,1551.2 409.239,1548.89 411.71,1546.5 414.181,1544.05 416.653,1541.53 419.124,1538.94 421.595,1536.27 424.066,1533.54 426.538,1530.73 429.009,1527.85 431.48,1524.9 433.951,1521.86 436.422,1518.75 438.894,1515.56 441.365,1512.29 443.836,1508.93 446.307,1505.49 448.779,1501.97 451.25,1498.36 453.721,1494.66 456.192,1490.87 458.664,1486.99 461.135,1483.02 463.606,1478.95 466.077,1474.78 468.548,1470.51 471.02,1466.15 473.491,1461.68 475.962,1457.1 478.433,1452.42 480.905,1447.63 483.376,1442.73 485.847,1437.71 488.318,1432.58 490.789,1427.33 493.261,1421.96 495.732,1416.46 498.203,1410.85 500.674,1405.1 503.146,1399.22 505.617,1393.21 508.088,1387.06 510.559,1380.78 513.03,1374.35 515.502,1367.78 517.973,1361.07 520.444,1354.2 522.915,1347.18 525.387,1340.01 527.858,1332.67 530.329,1325.18 532.8,1317.51 535.272,1309.68 537.743,1301.68 540.214,1293.5 542.685,1285.15 545.156,1276.61 547.628,1267.88 550.099,1258.97 552.57,1249.86 555.041,1240.56 557.513,1231.06 559.984,1221.35 562.455,1211.43 564.926,1201.31 567.397,1190.96 569.869,1180.4 572.34,1169.62 574.811,1158.6 577.282,1147.36 579.754,1135.88 582.225,1124.16 584.696,1112.19 587.167,1099.98 589.638,1087.51 592.11,1074.79 594.581,1061.81 597.052,1048.57 599.523,1035.06 601.995,1021.27 604.466,1007.22 606.937,992.882 609.408,978.266 611.88,963.364 614.351,948.173 616.822,932.69 619.293,916.914 621.764,900.842 624.236,884.472 626.707,867.799 629.178,850.822 631.649,833.538 634.121,815.946 636.592,798.047 639.063,779.842 641.534,761.332 644.005,742.52 646.477,723.409 648.948,704.004 651.419,684.31 653.89,664.333 656.362,644.079 658.833,623.557 661.304,602.775 663.775,581.748 666.246,560.509 668.718,539.064 671.189,517.422 673.66,495.598 676.131,473.615 678.603,451.502 681.074,429.296 683.545,407.043 686.016,384.794 688.488,362.607 690.959,340.549 693.43,318.693 695.901,297.12 698.372,275.918 700.844,255.182 703.315,235.015 705.786,215.526 708.257,196.833 710.729,179.033 713.2,162.256 715.671,146.757 718.142,132.794 720.613,120.625 723.085,110.507 725.556,102.692 728.027,97.435 730.498,94.9858 732.97,95.5941 735.441,99.5078 737.912,106.973 740.383,118.235 742.854,133.536 745.326,153.118 747.797,177.256 750.268,206.308 752.739,240.068 755.211,278.207 757.682,320.365 760.153,366.151 762.624,415.145 765.096,466.894 767.567,520.918 770.038,576.701 772.509,633.702 774.98,691.345 777.452,749.026 779.923,806.11 782.394,861.93 784.865,915.798 787.337,967.345 789.808,1016.42 792.279,1062.86 794.75,1106.55 797.221,1147.42 799.693,1185.43 802.164,1220.6 804.635,1252.98 807.106,1282.66 809.578,1309.79 812.049,1334.54 814.52,1357.14 816.991,1377.84 819.462,1396.91 821.934,1414.38 824.405,1430.35 826.876,1444.93 829.347,1458.24 831.819,1470.36 834.29,1481.42 836.761,1491.48 839.232,1500.64 841.704,1508.98 844.175,1516.57 846.646,1523.49 849.117,1529.79 851.588,1535.53 854.06,1540.77 856.531,1545.55 859.002,1549.91 861.473,1553.9 863.945,1557.53 866.416,1560.85 868.887,1563.87 871.358,1566.61 873.829,1569.1 876.301,1571.37 878.772,1573.41 881.243,1575.26 883.714,1576.93 886.186,1578.42 888.657,1579.75 891.128,1580.93 893.599,1581.96 896.07,1582.86 898.542,1583.64 901.013,1584.29 903.484,1584.83 905.955,1585.26 908.427,1585.59 910.898,1585.82 913.369,1585.95 915.84,1585.99 918.312,1585.95 920.783,1585.83 923.254,1585.62 925.725,1585.34 928.196,1584.99 930.668,1584.56 933.139,1584.07 935.61,1583.5 938.081,1582.87 940.553,1582.18 943.024,1581.41 945.495,1580.59 947.966,1579.7 950.437,1578.75 952.909,1577.73 955.38,1576.66 957.851,1575.53 960.322,1574.33 962.794,1573.08 965.265,1571.76 967.736,1570.39 970.207,1568.96 972.678,1567.47 975.15,1565.92 977.621,1564.31 980.092,1562.64 982.563,1560.91 985.035,1559.12 987.506,1557.27 989.977,1555.37 992.448,1553.39 994.92,1551.36 997.391,1549.27 999.862,1547.11 1002.33,1544.88 1004.8,1542.6 1007.28,1540.25 1009.75,1537.83 1012.22,1535.34 1014.69,1532.79 1017.16,1530.17 1019.63,1527.47 1022.1,1524.71 1024.57,1521.88 1027.05,1518.97 1029.52,1515.99 1031.99,1512.94 1034.46,1509.81 1036.93,1506.6 1039.4,1503.31 1041.87,1499.94 1044.34,1496.49 1046.82,1492.96 1049.29,1489.35 1051.76,1485.64 1054.23,1481.85 1056.7,1477.97 1059.17,1474 1061.64,1469.94 1064.11,1465.78 1066.59,1461.52 1069.06,1457.17 1071.53,1452.71 1074,1448.16 1076.47,1443.49 1078.94,1438.73 1081.41,1433.85 1083.88,1428.86 1086.35,1423.76 1088.83,1418.54 1091.3,1413.21 1093.77,1407.75 1096.24,1402.17 1098.71,1396.46 1101.18,1390.63 1103.65,1384.66 1106.12,1378.57 1108.6,1372.33 1111.07,1365.96 1113.54,1359.44 1116.01,1352.78 1118.48,1345.98 1120.95,1339.02 1123.42,1331.91 1125.89,1324.64 1128.37,1317.21 1130.84,1309.62 1133.31,1301.86 1135.78,1293.94 1138.25,1285.84 1140.72,1277.57 1143.19,1269.11 1145.66,1260.48 1148.14,1251.66 1150.61,1242.65 1153.08,1233.45 1155.55,1224.05 1158.02,1214.45 1160.49,1204.65 1162.96,1194.64 1165.43,1184.41 1167.91,1173.98 1170.38,1163.32 1172.85,1152.45 1175.32,1141.34 1177.79,1130.01 1180.26,1118.45 1182.73,1106.64 1185.2,1094.6 1187.68,1082.31 1190.15,1069.77 1192.62,1056.99 1195.09,1043.94 1197.56,1030.64 1200.03,1017.07 1202.5,1003.24 1204.97,989.14 1207.44,974.766 1209.92,960.117 1212.39,945.19 1214.86,929.982 1217.33,914.493 1219.8,898.719 1222.27,882.66 1224.74,866.314 1227.21,849.681 1229.69,832.758 1232.16,815.548 1234.63,798.052 1237.1,780.27 1239.57,762.203 1242.04,743.853 1244.51,725.224 1246.98,706.321 1249.46,687.151 1251.93,667.724 1254.4,648.048 1256.87,628.135 1259.34,608 1261.81,587.655 1264.28,567.118 1266.75,546.405 1269.23,525.548 1271.7,504.583 1274.17,483.526 1276.64,462.399 1279.11,441.233 1281.58,420.069 1284.05,398.955 1286.52,377.952 1289,357.127 1291.47,336.556 1293.94,316.325 1296.41,296.529 1298.88,277.272 1301.35,258.668 1303.82,240.838 1306.29,223.913 1308.77,208.034 1311.24,193.35 1313.71,180.02 1316.18,168.2 1318.65,157.981 1321.12,149.668 1323.59,143.6 1326.06,140.084 1328.53,139.397 1331.01,141.784 1333.48,147.464 1335.95,156.621 1338.42,169.412 1340.89,185.963 1343.36,206.37 1345.83,230.697 1348.3,258.979 1350.78,291.223 1353.25,327.402 1355.72,367.469 1358.19,411.121 1360.66,457.803 1363.13,506.965 1365.6,558.067 1368.07,610.583 1370.55,663.998 1373.02,717.808 1375.49,771.521 1377.96,824.658 1380.43,876.75 1382.9,927.341 1385.37,975.985 1387.84,1022.31 1390.32,1066.22 1392.79,1107.65 1395.26,1146.59 1397.73,1183.04 1400.2,1217.02 1402.67,1248.57 1405.14,1277.74 1407.61,1304.62 1410.09,1329.32 1412.56,1351.94 1415.03,1372.64 1417.5,1391.58 1419.97,1408.93 1422.44,1424.9 1424.91,1439.61 1427.38,1453.1 1429.86,1465.46 1432.33,1476.78 1434.8,1487.15 1437.27,1496.65 1439.74,1505.35 1442.21,1513.33 1444.68,1520.65 1447.15,1527.36 1449.63,1533.53 1452.1,1539.18 1454.57,1544.38 1457.04,1549.14 1459.51,1553.5 1461.98,1557.5 1464.45,1561.18 1466.92,1564.56 1469.39,1567.65 1471.87,1570.49 1474.34,1573.09 1476.81,1575.47 1479.28,1577.65 1481.75,1579.63 1484.22,1581.44 1486.69,1583.09 1489.16,1584.58 1491.64,1585.93 1494.11,1587.14 1496.58,1588.22 1499.05,1589.18 1501.52,1590.03 1503.99,1590.77 1506.46,1591.4 1508.93,1591.94 1511.41,1592.38 1513.88,1592.73 1516.35,1592.99 1518.82,1593.18 1521.29,1593.28 1523.76,1593.31 1526.23,1593.27 1528.7,1593.15 1531.18,1592.97 1533.65,1592.72 1536.12,1592.4 1538.59,1592.02 1541.06,1591.57 1543.53,1591.07 1546,1590.5 1548.47,1589.87 1550.95,1589.19 1553.42,1588.45 1555.89,1587.65 1558.36,1586.79 1560.83,1585.88 1563.3,1584.91 1565.77,1583.88 1568.24,1582.81 1570.72,1581.67 1573.19,1580.48 1575.66,1579.24 1578.13,1577.94 1580.6,1576.59 1583.07,1575.18 1585.54,1573.71 1588.01,1572.19 1590.48,1570.61 1592.96,1568.98 1595.43,1567.28 1597.9,1565.53 1600.37,1563.73 1602.84,1561.86 1605.31,1559.93 1607.78,1557.95 1610.25,1555.9 1612.73,1553.8 1615.2,1551.63 1617.67,1549.39 1620.14,1547.1 1622.61,1544.73 1625.08,1542.31 1627.55,1539.81 1630.02,1537.25 1632.5,1534.62 1634.97,1531.92 1637.44,1529.14 1639.91,1526.3 1642.38,1523.38 1644.85,1520.38 1647.32,1517.31 1649.79,1514.17 1652.27,1510.94 1654.74,1507.63 1657.21,1504.24 1659.68,1500.77 1662.15,1497.21 1664.62,1493.57 1667.09,1489.84 1669.56,1486.02 1672.04,1482.1 1674.51,1478.1 1676.98,1474 1679.45,1469.8 1681.92,1465.5 1684.39,1461.1 1686.86,1456.6 1689.33,1452 1691.81,1447.29 1694.28,1442.47 1696.75,1437.54 1699.22,1432.49 1701.69,1427.33 1704.16,1422.06 1706.63,1416.66 1709.1,1411.14 1711.57,1405.49 1714.05,1399.72 1716.52,1393.82 1718.99,1387.79 1721.46,1381.62 1723.93,1375.31 1726.4,1368.86 1728.87,1362.27 1731.34,1355.54 1733.82,1348.65 1736.29,1341.61 1738.76,1334.42 1741.23,1327.07 1743.7,1319.56 1746.17,1311.88 1748.64,1304.04 1751.11,1296.03 1753.59,1287.84 1756.06,1279.48 1758.53,1270.93 1761,1262.2 1763.47,1253.29 1765.94,1244.18 1768.41,1234.88 1770.88,1225.38 1773.36,1215.68 1775.83,1205.77 1778.3,1195.66 1780.77,1185.33 1783.24,1174.79 1785.71,1164.02 1788.18,1153.03 1790.65,1141.81 1793.13,1130.36 1795.6,1118.68 1798.07,1106.75 1800.54,1094.59 1803.01,1082.18 1805.48,1069.52 1807.95,1056.6 1810.42,1043.43 1812.9,1029.99 1815.37,1016.3 1817.84,1002.33 1820.31,988.105 1822.78,973.603 1825.25,958.823 1827.72,943.763 1830.19,928.418 1832.67,912.787 1835.14,896.868 1837.61,880.66 1840.08,864.162 1842.55,847.374 1845.02,830.296 1847.49,812.931 1849.96,795.279 1852.43,777.343 1854.91,759.127 1857.38,740.633 1859.85,721.866 1862.32,702.831 1864.79,683.533 1867.26,663.978 1869.73,644.173 1872.2,624.128 1874.68,603.869 1877.15,583.402 1879.62,562.738 1882.09,541.894 1884.56,520.889 1887.03,499.749 1889.5,478.504 1891.97,457.188 1894.45,435.841 1896.92,414.508 1899.39,393.236 1901.86,372.081 1904.33,351.101 1906.8,330.358 1909.27,309.922 1911.74,289.865 1914.22,270.263 1916.69,251.149 1919.16,232.635 1921.63,214.887 1924.1,198.072 1926.57,182.362 1929.04,167.932 1931.51,154.96 1933.99,143.625 1936.46,134.114 1938.93,126.612 1941.4,121.31 1943.87,118.402 1946.34,118.085 1948.81,120.558 1951.28,126.024 1953.76,134.69 1956.23,146.765 1958.7,162.461 1961.17,182.017 1963.64,205.597 1966.11,233.111 1968.58,264.414 1971.05,299.325 1973.52,337.619 1976,379.038 1978.47,423.279 1980.94,470.003 1983.41,518.832 1985.88,569.347 1988.35,621.091 1990.82,673.569 1993.29,726.243 1995.77,778.54 1998.24,829.905 2000.71,880.065 2003.18,928.701 2005.65,975.522 2008.12,1020.29 2010.59,1062.82 2013.06,1102.97 2015.54,1140.66 2018.01,1175.85 2020.48,1208.56 2022.95,1238.85 2025.42,1266.85 2027.89,1292.72 2030.36,1316.68 2032.83,1338.93 2035.31,1359.44 2037.78,1378.31 2040.25,1395.67 2042.72,1411.63 2045.19,1426.29 2047.66,1439.75 2050.13,1452.12 2052.6,1463.47 2055.08,1473.89 2057.55,1483.45 2060.02,1492.23 2062.49,1500.28 2064.96,1507.67 2067.43,1514.44 2069.9,1520.66 2072.37,1526.38 2074.85,1531.63 2077.32,1536.46 2079.79,1540.89 2082.26,1544.96 2084.73,1548.7 2087.2,1552.13 2089.67,1555.28 2092.14,1558.17 2094.62,1560.81 2097.09,1563.23 2099.56,1565.43 2102.03,1567.44 2104.5,1569.26 2106.97,1570.91 2109.44,1572.39 2111.91,1573.73 2114.38,1574.92 2116.86,1575.97 2119.33,1576.9 2121.8,1577.7 2124.27,1578.39 2126.74,1578.97 2129.21,1579.44 2131.68,1579.82 2134.15,1580.1 2136.63,1580.29 2139.1,1580.4 2141.57,1580.42 2144.04,1580.36 2146.51,1580.23 2148.98,1580.02 2151.45,1579.73 2153.92,1579.38 2156.4,1578.95 2158.87,1578.46 2161.34,1577.9 2163.81,1577.27 2166.28,1576.58 2168.75,1575.83 2171.22,1575.02 2173.69,1574.14 2176.17,1573.2 2178.64,1572.21 2181.11,1571.15 2183.58,1570.03 2186.05,1568.86 2188.52,1567.63 2190.99,1566.34 2193.46,1564.99 2195.94,1563.59 2198.41,1562.12 2200.88,1560.6 2203.35,1559.02 2205.82,1557.38 2208.29,1555.68 2210.76,1553.93 2213.23,1552.11 2215.71,1550.24 2218.18,1548.3 2220.65,1546.3 2223.12,1544.24 2225.59,1542.12 2228.06,1539.94 2230.53,1537.69 2233,1535.38 2235.47,1533.01 2237.95,1530.57 2240.42,1528.06 2242.89,1525.49 2245.36,1522.85 2247.83,1520.14 2250.3,1517.36 2252.77,1514.51 2255.24,1511.58 2257.72,1508.59 2260.19,1505.52 2262.66,1502.38 2265.13,1499.16 2267.6,1495.86 2270.07,1492.48 2272.54,1489.02 2275.01,1485.49 2277.49,1481.87 2279.96,1478.16 2282.43,1474.37 2284.9,1470.5 2287.37,1466.53 2289.84,1462.48 2292.31,1458.34 2294.78,1454.1 2297.26,1449.77 2299.73,1445.34 2302.2,1440.81 2304.67,1436.19 2307.14,1431.46 2309.61,1426.64 2312.08,1421.7 2314.55,1416.66 2317.03,1411.51 2319.5,1406.25 2321.97,1400.87 2324.44,1395.39 2326.91,1389.78 2329.38,1384.05 2331.85,1378.2 2334.32,1372.23 2336.8,1366.12 2339.27,1359.89 2341.74,1353.53 2344.21,1347.03 2346.68,1340.39 2349.15,1333.61 2351.62,1326.69 2354.09,1319.62 2356.56,1312.4 2359.04,1305.03 2361.51,1297.5 2363.98,1289.82 2366.45,1281.97 2368.92,1273.96 2371.39,1265.78 2373.86,1257.43 2376.33,1248.91 2378.81,1240.21 2381.28,1231.33 2383.75,1222.26 2386.22,1213.01 2388.69,1203.57 2391.16,1193.93 2393.63,1184.1 2396.1,1174.07 2398.58,1163.84 2401.05,1153.4 2403.52,1142.75 2405.99,1131.89 2408.46,1120.82 2410.93,1109.52 2413.4,1098.01 2415.87,1086.27 2418.35,1074.3 2420.82,1062.11 2423.29,1049.68 2425.76,1037.02 2428.23,1024.11 2430.7,1010.97 2433.17,997.587 2435.64,983.959 2438.12,970.084 2440.59,955.962 2443.06,941.591 2445.53,926.97 2448,912.098 2450.47,896.976 2452.94,881.604 2455.41,865.981 2457.89,850.108 2460.36,833.986 2462.83,817.616 2465.3,801.002 2467.77,784.148 2470.24,767.059 2472.71,749.741 2475.18,732.2 2477.66,714.443 2480.13,696.481 2482.6,678.321 2485.07,659.975 2487.54,641.457 2490.01,622.783 2492.48,603.97 2494.95,585.032 2497.42,565.992 2499.9,546.874 2502.37,527.705 2504.84,508.518 2507.31,489.349 2509.78,470.238 2512.25,451.228 2514.72,432.365 2517.19,413.703 2519.67,395.294 2522.14,377.197 2524.61,359.466 2527.08,342.184 2529.55,325.447 2532.02,309.354 2534.49,294.012 2536.96,279.533 2539.44,266.037 2541.91,253.647 2544.38,242.496 2546.85,232.72 2549.32,224.463 2551.79,217.874 2554.26,213.109 2556.73,210.33 2559.21,209.705 2561.68,211.408 2564.15,215.61 2566.62,222.448 2569.09,232.094 2571.56,244.684 2574.03,260.313 2576.5,279.038 2578.98,300.871 2581.45,325.784 2583.92,353.708 2586.39,384.533 2588.86,418.106 2591.33,454.236 2593.8,492.686 2596.27,533.181 2598.75,575.407 2601.22,619.07 2603.69,663.754 2606.16,709.019 2608.63,754.461 2611.1,799.712 2613.57,844.437 2616.04,888.339 2618.51,931.157 2620.99,972.662 2623.46,1012.66 2625.93,1051.01 2628.4,1087.58 2630.87,1122.28 2633.34,1155.11 2635.81,1186.04 2638.28,1215.09 2640.76,1242.3 "></polyline>
<polyline clip-path="url(#clip962)" style="stroke:#e26f46; stroke-linecap:round; stroke-linejoin:round; stroke-width:8; stroke-opacity:1; fill:none" points="172.001,1106.32 174.473,1071.9 176.944,1039.13 179.415,1008.54 181.886,980.597 184.357,955.701 186.829,934.16 189.3,916.186 191.771,901.897 194.242,891.318 196.714,884.389 199.185,880.97 201.656,880.873 204.127,883.871 206.598,889.696 209.07,898.065 211.541,908.683 214.012,921.262 216.483,935.529 218.955,951.221 221.426,968.094 223.897,985.913 226.368,1004.47 228.84,1023.58 231.311,1043.08 233.782,1062.82 236.253,1082.67 238.724,1102.51 241.196,1122.26 243.667,1141.83 246.138,1161.15 248.609,1180.16 251.081,1198.82 253.552,1217.08 256.023,1234.92 258.494,1252.3 260.965,1269.21 263.437,1285.63 265.908,1301.57 268.379,1317 270.85,1331.94 273.322,1346.38 275.793,1360.32 278.264,1373.77 280.735,1386.74 283.206,1399.23 285.678,1411.25 288.149,1422.83 290.62,1433.95 293.091,1444.65 295.563,1454.92 298.034,1464.79 300.505,1474.26 302.976,1483.35 305.448,1492.07 307.919,1500.43 310.39,1508.44 312.861,1516.12 315.332,1523.48 317.804,1530.53 320.275,1537.28 322.746,1543.75 325.217,1549.94 327.689,1555.87 330.16,1561.54 332.631,1566.97 335.102,1572.17 337.573,1577.14 340.045,1581.89 342.516,1586.44 344.987,1590.79 347.458,1594.95 349.93,1598.94 352.401,1602.74 354.872,1606.38 357.343,1609.86 359.814,1613.19 362.286,1616.38 364.757,1619.42 367.228,1622.33 369.699,1625.11 372.171,1627.77 374.642,1630.31 377.113,1632.74 379.584,1635.07 382.056,1637.29 384.527,1639.41 386.998,1641.44 389.469,1643.39 391.94,1645.24 394.412,1647.02 396.883,1648.71 399.354,1650.34 401.825,1651.89 404.297,1653.37 406.768,1654.79 409.239,1656.15 411.71,1657.44 414.181,1658.68 416.653,1659.87 419.124,1661 421.595,1662.09 424.066,1663.12 426.538,1664.12 429.009,1665.07 431.48,1665.97 433.951,1666.84 436.422,1667.67 438.894,1668.47 441.365,1669.23 443.836,1669.95 446.307,1670.65 448.779,1671.31 451.25,1671.95 453.721,1672.56 456.192,1673.14 458.664,1673.7 461.135,1674.23 463.606,1674.74 466.077,1675.22 468.548,1675.69 471.02,1676.14 473.491,1676.56 475.962,1676.97 478.433,1677.36 480.905,1677.73 483.376,1678.09 485.847,1678.43 488.318,1678.75 490.789,1679.06 493.261,1679.36 495.732,1679.64 498.203,1679.91 500.674,1680.17 503.146,1680.42 505.617,1680.65 508.088,1680.87 510.559,1681.09 513.03,1681.29 515.502,1681.48 517.973,1681.66 520.444,1681.84 522.915,1682 525.387,1682.16 527.858,1682.3 530.329,1682.44 532.8,1682.57 535.272,1682.7 537.743,1682.81 540.214,1682.92 542.685,1683.02 545.156,1683.11 547.628,1683.2 550.099,1683.28 552.57,1683.35 555.041,1683.42 557.513,1683.48 559.984,1683.53 562.455,1683.58 564.926,1683.62 567.397,1683.65 569.869,1683.67 572.34,1683.69 574.811,1683.7 577.282,1683.71 579.754,1683.7 582.225,1683.7 584.696,1683.68 587.167,1683.65 589.638,1683.62 592.11,1683.58 594.581,1683.53 597.052,1683.47 599.523,1683.41 601.995,1683.33 604.466,1683.24 606.937,1683.14 609.408,1683.03 611.88,1682.91 614.351,1682.78 616.822,1682.63 619.293,1682.47 621.764,1682.29 624.236,1682.09 626.707,1681.87 629.178,1681.64 631.649,1681.38 634.121,1681.11 636.592,1680.81 639.063,1680.48 641.534,1680.12 644.005,1679.74 646.477,1679.31 648.948,1678.85 651.419,1678.34 653.89,1677.79 656.362,1677.19 658.833,1676.53 661.304,1675.81 663.775,1675.02 666.246,1674.14 668.718,1673.17 671.189,1672.11 673.66,1670.96 676.131,1669.69 678.603,1668.3 681.074,1666.77 683.545,1665.09 686.016,1663.23 688.488,1661.17 690.959,1658.87 693.43,1656.32 695.901,1653.47 698.372,1650.29 700.844,1646.74 703.315,1642.78 705.786,1638.35 708.257,1633.42 710.729,1627.95 713.2,1621.88 715.671,1615.11 718.142,1607.5 720.613,1598.96 723.085,1589.39 725.556,1578.67 728.027,1566.72 730.498,1553.45 732.97,1538.77 735.441,1522.6 737.912,1504.87 740.383,1485.5 742.854,1464.43 745.326,1441.6 747.797,1416.91 750.268,1390.17 752.739,1361.68 755.211,1331.84 757.682,1301.04 760.153,1269.68 762.624,1238.13 765.096,1206.77 767.567,1175.98 770.038,1146.14 772.509,1117.59 774.98,1090.72 777.452,1065.86 779.923,1043.37 782.394,1023.6 784.865,1006.89 787.337,993.407 789.808,983.098 792.279,975.883 794.75,971.659 797.221,970.298 799.693,971.653 802.164,975.55 804.635,981.796 807.106,990.172 809.578,1000.44 812.049,1012.34 814.52,1025.57 816.991,1039.85 819.462,1054.85 821.934,1070.47 824.405,1086.59 826.876,1103.12 829.347,1119.96 831.819,1137.02 834.29,1154.21 836.761,1171.45 839.232,1188.67 841.704,1205.78 844.175,1222.73 846.646,1239.44 849.117,1255.85 851.588,1271.91 854.06,1287.57 856.531,1302.78 859.002,1317.53 861.473,1331.86 863.945,1345.77 866.416,1359.25 868.887,1372.3 871.358,1384.92 873.829,1397.12 876.301,1408.89 878.772,1420.24 881.243,1431.19 883.714,1441.73 886.186,1451.87 888.657,1461.64 891.128,1471.03 893.599,1480.06 896.07,1488.74 898.542,1497.08 901.013,1505.08 903.484,1512.77 905.955,1520.14 908.427,1527.22 910.898,1534 913.369,1540.5 915.84,1546.73 918.312,1552.7 920.783,1558.42 923.254,1563.9 925.725,1569.15 928.196,1574.17 930.668,1578.99 933.139,1583.6 935.61,1588.01 938.081,1592.24 940.553,1596.28 943.024,1600.16 945.495,1603.87 947.966,1607.41 950.437,1610.81 952.909,1614.06 955.38,1617.16 957.851,1620.14 960.322,1622.98 962.794,1625.7 965.265,1628.3 967.736,1630.79 970.207,1633.18 972.678,1635.46 975.15,1637.64 977.621,1639.72 980.092,1641.72 982.563,1643.63 985.035,1645.46 987.506,1647.2 989.977,1648.88 992.448,1650.48 994.92,1652.01 997.391,1653.47 999.862,1654.87 1002.33,1656.21 1004.8,1657.49 1007.28,1658.72 1009.75,1659.89 1012.22,1661.01 1014.69,1662.09 1017.16,1663.12 1019.63,1664.1 1022.1,1665.04 1024.57,1665.94 1027.05,1666.81 1029.52,1667.63 1031.99,1668.42 1034.46,1669.18 1036.93,1669.9 1039.4,1670.59 1041.87,1671.26 1044.34,1671.89 1046.82,1672.5 1049.29,1673.08 1051.76,1673.64 1054.23,1674.17 1056.7,1674.68 1059.17,1675.17 1061.64,1675.63 1064.11,1676.08 1066.59,1676.51 1069.06,1676.92 1071.53,1677.31 1074,1677.68 1076.47,1678.04 1078.94,1678.38 1081.41,1678.71 1083.88,1679.02 1086.35,1679.32 1088.83,1679.61 1091.3,1679.88 1093.77,1680.14 1096.24,1680.39 1098.71,1680.63 1101.18,1680.86 1103.65,1681.07 1106.12,1681.28 1108.6,1681.47 1111.07,1681.66 1113.54,1681.84 1116.01,1682.01 1118.48,1682.17 1120.95,1682.32 1123.42,1682.46 1125.89,1682.6 1128.37,1682.73 1130.84,1682.85 1133.31,1682.96 1135.78,1683.07 1138.25,1683.17 1140.72,1683.26 1143.19,1683.34 1145.66,1683.42 1148.14,1683.49 1150.61,1683.56 1153.08,1683.62 1155.55,1683.67 1158.02,1683.72 1160.49,1683.76 1162.96,1683.79 1165.43,1683.82 1167.91,1683.84 1170.38,1683.86 1172.85,1683.86 1175.32,1683.86 1177.79,1683.86 1180.26,1683.85 1182.73,1683.83 1185.2,1683.8 1187.68,1683.76 1190.15,1683.72 1192.62,1683.67 1195.09,1683.61 1197.56,1683.54 1200.03,1683.46 1202.5,1683.37 1204.97,1683.27 1207.44,1683.16 1209.92,1683.04 1212.39,1682.91 1214.86,1682.76 1217.33,1682.6 1219.8,1682.42 1222.27,1682.22 1224.74,1682.01 1227.21,1681.78 1229.69,1681.53 1232.16,1681.26 1234.63,1680.96 1237.1,1680.63 1239.57,1680.28 1242.04,1679.9 1244.51,1679.48 1246.98,1679.03 1249.46,1678.54 1251.93,1678 1254.4,1677.41 1256.87,1676.77 1259.34,1676.07 1261.81,1675.3 1264.28,1674.46 1266.75,1673.54 1269.23,1672.53 1271.7,1671.41 1274.17,1670.18 1276.64,1668.82 1279.11,1667.34 1281.58,1665.71 1284.05,1663.92 1286.52,1661.95 1289,1659.77 1291.47,1657.35 1293.94,1654.67 1296.41,1651.69 1298.88,1648.37 1301.35,1644.67 1303.82,1640.56 1306.29,1635.97 1308.77,1630.86 1311.24,1625.17 1313.71,1618.86 1316.18,1611.85 1318.65,1604.12 1321.12,1595.53 1323.59,1585.97 1326.06,1575.34 1328.53,1563.54 1331.01,1550.51 1333.48,1536.19 1335.95,1520.56 1338.42,1503.6 1340.89,1485.3 1343.36,1465.69 1345.83,1444.81 1348.3,1422.71 1350.78,1399.45 1353.25,1375.14 1355.72,1349.89 1358.19,1324 1360.66,1297.88 1363.13,1271.92 1365.6,1246.49 1368.07,1221.93 1370.55,1198.55 1373.02,1176.65 1375.49,1156.49 1377.96,1138.32 1380.43,1122.35 1382.9,1108.78 1385.37,1097.76 1387.84,1089.43 1390.32,1083.7 1392.79,1080.42 1395.26,1079.46 1397.73,1080.66 1400.2,1083.87 1402.67,1088.93 1405.14,1095.68 1407.61,1103.94 1410.09,1113.57 1412.56,1124.37 1415.03,1136.17 1417.5,1148.8 1419.97,1162.07 1422.44,1175.79 1424.91,1189.81 1427.38,1204.08 1429.86,1218.52 1432.33,1233.04 1434.8,1247.59 1437.27,1262.1 1439.74,1276.51 1442.21,1290.77 1444.68,1304.84 1447.15,1318.68 1449.63,1332.25 1452.1,1345.52 1454.57,1358.47 1457.04,1371.08 1459.51,1383.34 1461.98,1395.24 1464.45,1406.79 1466.92,1417.97 1469.39,1428.8 1471.87,1439.27 1474.34,1449.39 1476.81,1459.15 1479.28,1468.57 1481.75,1477.64 1484.22,1486.38 1486.69,1494.8 1489.16,1502.89 1491.64,1510.67 1494.11,1518.15 1496.58,1525.33 1499.05,1532.24 1501.52,1538.86 1503.99,1545.23 1506.46,1551.33 1508.93,1557.18 1511.41,1562.8 1513.88,1568.18 1516.35,1573.33 1518.82,1578.27 1521.29,1583 1523.76,1587.54 1526.23,1591.88 1528.7,1596.03 1531.18,1600.01 1533.65,1603.83 1536.12,1607.47 1538.59,1610.96 1541.06,1614.3 1543.53,1617.5 1546,1620.56 1548.47,1623.49 1550.95,1626.28 1553.42,1628.96 1555.89,1631.52 1558.36,1633.97 1560.83,1636.31 1563.3,1638.55 1565.77,1640.69 1568.24,1642.74 1570.72,1644.7 1573.19,1646.58 1575.66,1648.37 1578.13,1650.08 1580.6,1651.72 1583.07,1653.28 1585.54,1654.78 1588.01,1656.21 1590.48,1657.58 1592.96,1658.89 1595.43,1660.14 1597.9,1661.34 1600.37,1662.48 1602.84,1663.58 1605.31,1664.62 1607.78,1665.63 1610.25,1666.58 1612.73,1667.5 1615.2,1668.37 1617.67,1669.21 1620.14,1670.01 1622.61,1670.78 1625.08,1671.51 1627.55,1672.21 1630.02,1672.88 1632.5,1673.52 1634.97,1674.13 1637.44,1674.72 1639.91,1675.28 1642.38,1675.82 1644.85,1676.33 1647.32,1676.82 1649.79,1677.29 1652.27,1677.74 1654.74,1678.17 1657.21,1678.59 1659.68,1678.98 1662.15,1679.36 1664.62,1679.72 1667.09,1680.06 1669.56,1680.39 1672.04,1680.71 1674.51,1681.01 1676.98,1681.3 1679.45,1681.57 1681.92,1681.84 1684.39,1682.09 1686.86,1682.33 1689.33,1682.57 1691.81,1682.79 1694.28,1683 1696.75,1683.2 1699.22,1683.39 1701.69,1683.58 1704.16,1683.76 1706.63,1683.92 1709.1,1684.09 1711.57,1684.24 1714.05,1684.39 1716.52,1684.52 1718.99,1684.66 1721.46,1684.78 1723.93,1684.91 1726.4,1685.02 1728.87,1685.13 1731.34,1685.23 1733.82,1685.33 1736.29,1685.42 1738.76,1685.51 1741.23,1685.6 1743.7,1685.68 1746.17,1685.75 1748.64,1685.82 1751.11,1685.88 1753.59,1685.95 1756.06,1686 1758.53,1686.05 1761,1686.1 1763.47,1686.15 1765.94,1686.19 1768.41,1686.22 1770.88,1686.26 1773.36,1686.28 1775.83,1686.31 1778.3,1686.33 1780.77,1686.35 1783.24,1686.36 1785.71,1686.37 1788.18,1686.37 1790.65,1686.38 1793.13,1686.37 1795.6,1686.36 1798.07,1686.35 1800.54,1686.34 1803.01,1686.31 1805.48,1686.29 1807.95,1686.26 1810.42,1686.22 1812.9,1686.18 1815.37,1686.13 1817.84,1686.08 1820.31,1686.01 1822.78,1685.94 1825.25,1685.87 1827.72,1685.79 1830.19,1685.69 1832.67,1685.6 1835.14,1685.49 1837.61,1685.37 1840.08,1685.24 1842.55,1685.1 1845.02,1684.95 1847.49,1684.79 1849.96,1684.61 1852.43,1684.41 1854.91,1684.2 1857.38,1683.96 1859.85,1683.71 1862.32,1683.43 1864.79,1683.13 1867.26,1682.8 1869.73,1682.43 1872.2,1682.04 1874.68,1681.61 1877.15,1681.13 1879.62,1680.61 1882.09,1680.04 1884.56,1679.42 1887.03,1678.75 1889.5,1678 1891.97,1677.18 1894.45,1676.28 1896.92,1675.29 1899.39,1674.18 1901.86,1672.96 1904.33,1671.61 1906.8,1670.1 1909.27,1668.43 1911.74,1666.57 1914.22,1664.51 1916.69,1662.25 1919.16,1659.74 1921.63,1656.96 1924.1,1653.85 1926.57,1650.36 1929.04,1646.45 1931.51,1642.06 1933.99,1637.16 1936.46,1631.68 1938.93,1625.59 1941.4,1618.83 1943.87,1611.35 1946.34,1603.09 1948.81,1594.02 1951.28,1584.08 1953.76,1573.21 1956.23,1561.36 1958.7,1548.48 1961.17,1534.5 1963.64,1519.33 1966.11,1503.12 1968.58,1485.99 1971.05,1468.11 1973.52,1449.63 1976,1430.73 1978.47,1411.6 1980.94,1392.41 1983.41,1373.38 1985.88,1354.7 1988.35,1336.6 1990.82,1319.31 1993.29,1303.05 1995.77,1288.08 1998.24,1274.63 2000.71,1262.8 2003.18,1252.68 2005.65,1244.33 2008.12,1237.79 2010.59,1233.08 2013.06,1230.17 2015.54,1229.03 2018.01,1229.57 2020.48,1231.71 2022.95,1235.3 2025.42,1240.19 2027.89,1246.21 2030.36,1253.13 2032.83,1260.77 2035.31,1269.1 2037.78,1278.03 2040.25,1287.47 2042.72,1297.33 2045.19,1307.52 2047.66,1317.96 2050.13,1328.58 2052.6,1339.31 2055.08,1350.09 2057.55,1360.86 2060.02,1371.58 2062.49,1382.2 2064.96,1392.69 2067.43,1403 2069.9,1413.13 2072.37,1423.05 2074.85,1432.75 2077.32,1442.23 2079.79,1451.46 2082.26,1460.44 2084.73,1469.18 2087.2,1477.65 2089.67,1485.86 2092.14,1493.81 2094.62,1501.51 2097.09,1508.94 2099.56,1516.11 2102.03,1523.04 2104.5,1529.73 2106.97,1536.17 2109.44,1542.38 2111.91,1548.35 2114.38,1554.11 2116.86,1559.64 2119.33,1564.96 2121.8,1570.08 2124.27,1574.99 2126.74,1579.71 2129.21,1584.24 2131.68,1588.59 2134.15,1592.76 2136.63,1596.76 2139.1,1600.6 2141.57,1604.28 2144.04,1607.81 2146.51,1611.2 2148.98,1614.44 2151.45,1617.55 2153.92,1620.53 2156.4,1623.39 2158.87,1626.13 2161.34,1628.75 2163.81,1631.26 2166.28,1633.66 2168.75,1635.97 2171.22,1638.17 2173.69,1640.28 2176.17,1642.3 2178.64,1644.24 2181.11,1646.09 2183.58,1647.86 2186.05,1649.56 2188.52,1651.18 2190.99,1652.74 2193.46,1654.23 2195.94,1655.65 2198.41,1657.02 2200.88,1658.32 2203.35,1659.57 2205.82,1660.77 2208.29,1661.92 2210.76,1663.01 2213.23,1664.06 2215.71,1665.07 2218.18,1666.03 2220.65,1666.95 2223.12,1667.83 2225.59,1668.67 2228.06,1669.48 2230.53,1670.25 2233,1670.99 2235.47,1671.69 2237.95,1672.37 2240.42,1673.02 2242.89,1673.64 2245.36,1674.24 2247.83,1674.81 2250.3,1675.35 2252.77,1675.87 2255.24,1676.37 2257.72,1676.85 2260.19,1677.31 2262.66,1677.75 2265.13,1678.17 2267.6,1678.57 2270.07,1678.96 2272.54,1679.32 2275.01,1679.68 2277.49,1680.02 2279.96,1680.34 2282.43,1680.65 2284.9,1680.95 2287.37,1681.23 2289.84,1681.51 2292.31,1681.77 2294.78,1682.02 2297.26,1682.26 2299.73,1682.48 2302.2,1682.7 2304.67,1682.91 2307.14,1683.11 2309.61,1683.3 2312.08,1683.49 2314.55,1683.66 2317.03,1683.83 2319.5,1683.99 2321.97,1684.14 2324.44,1684.29 2326.91,1684.43 2329.38,1684.56 2331.85,1684.69 2334.32,1684.81 2336.8,1684.93 2339.27,1685.04 2341.74,1685.14 2344.21,1685.24 2346.68,1685.34 2349.15,1685.43 2351.62,1685.51 2354.09,1685.59 2356.56,1685.67 2359.04,1685.74 2361.51,1685.8 2363.98,1685.87 2366.45,1685.92 2368.92,1685.98 2371.39,1686.03 2373.86,1686.08 2376.33,1686.12 2378.81,1686.16 2381.28,1686.19 2383.75,1686.23 2386.22,1686.25 2388.69,1686.28 2391.16,1686.3 2393.63,1686.31 2396.1,1686.33 2398.58,1686.34 2401.05,1686.34 2403.52,1686.34 2405.99,1686.34 2408.46,1686.33 2410.93,1686.32 2413.4,1686.3 2415.87,1686.28 2418.35,1686.26 2420.82,1686.23 2423.29,1686.2 2425.76,1686.16 2428.23,1686.11 2430.7,1686.06 2433.17,1686 2435.64,1685.94 2438.12,1685.87 2440.59,1685.79 2443.06,1685.71 2445.53,1685.62 2448,1685.51 2450.47,1685.4 2452.94,1685.28 2455.41,1685.15 2457.89,1685.01 2460.36,1684.86 2462.83,1684.69 2465.3,1684.51 2467.77,1684.31 2470.24,1684.1 2472.71,1683.86 2475.18,1683.61 2477.66,1683.34 2480.13,1683.04 2482.6,1682.71 2485.07,1682.36 2487.54,1681.98 2490.01,1681.56 2492.48,1681.1 2494.95,1680.6 2497.42,1680.06 2499.9,1679.47 2502.37,1678.82 2504.84,1678.11 2507.31,1677.33 2509.78,1676.48 2512.25,1675.54 2514.72,1674.51 2517.19,1673.38 2519.67,1672.13 2522.14,1670.76 2524.61,1669.25 2527.08,1667.59 2529.55,1665.76 2532.02,1663.73 2534.49,1661.49 2536.96,1659 2539.44,1656.26 2541.91,1653.22 2544.38,1649.86 2546.85,1646.16 2549.32,1642.07 2551.79,1637.58 2554.26,1632.63 2556.73,1627.21 2559.21,1621.26 2561.68,1614.76 2564.15,1607.67 2566.62,1599.93 2569.09,1591.54 2571.56,1582.47 2574.03,1572.73 2576.5,1562.33 2578.98,1551.3 2581.45,1539.69 2583.92,1527.54 2586.39,1514.93 2588.86,1501.94 2591.33,1488.67 2593.8,1475.23 2596.27,1461.74 2598.75,1448.35 2601.22,1435.19 2603.69,1422.43 2606.16,1410.26 2608.63,1398.83 2611.1,1388.28 2613.57,1378.71 2616.04,1370.21 2618.51,1362.86 2620.99,1356.7 2623.46,1351.76 2625.93,1348.05 2628.4,1345.54 2630.87,1344.2 2633.34,1343.99 2635.81,1344.84 2638.28,1346.68 2640.76,1349.44 "></polyline>
<polyline clip-path="url(#clip962)" style="stroke:#3da44d; stroke-linecap:round; stroke-linejoin:round; stroke-width:8; stroke-opacity:1; fill:none" points="172.001,1456.66 174.473,1446.34 176.944,1436.5 179.415,1427.26 181.886,1418.7 184.357,1410.91 186.829,1403.95 189.3,1397.87 191.771,1392.68 194.242,1388.39 196.714,1384.99 199.185,1382.47 201.656,1380.77 204.127,1379.87 206.598,1379.72 209.07,1380.25 211.541,1381.42 214.012,1383.16 216.483,1385.44 218.955,1388.19 221.426,1391.36 223.897,1394.91 226.368,1398.8 228.84,1402.97 231.311,1407.4 233.782,1412.05 236.253,1416.89 238.724,1421.88 241.196,1427.01 243.667,1432.23 246.138,1437.54 248.609,1442.92 251.081,1448.33 253.552,1453.77 256.023,1459.21 258.494,1464.65 260.965,1470.07 263.437,1475.46 265.908,1480.81 268.379,1486.11 270.85,1491.35 273.322,1496.52 275.793,1501.61 278.264,1506.63 280.735,1511.56 283.206,1516.41 285.678,1521.16 288.149,1525.82 290.62,1530.38 293.091,1534.84 295.563,1539.2 298.034,1543.46 300.505,1547.62 302.976,1551.68 305.448,1555.64 307.919,1559.49 310.39,1563.25 312.861,1566.91 315.332,1570.46 317.804,1573.92 320.275,1577.29 322.746,1580.56 325.217,1583.74 327.689,1586.83 330.16,1589.83 332.631,1592.74 335.102,1595.57 337.573,1598.31 340.045,1600.98 342.516,1603.56 344.987,1606.06 347.458,1608.49 349.93,1610.85 352.401,1613.13 354.872,1615.34 357.343,1617.49 359.814,1619.57 362.286,1621.58 364.757,1623.53 367.228,1625.42 369.699,1627.25 372.171,1629.03 374.642,1630.74 377.113,1632.4 379.584,1634.01 382.056,1635.57 384.527,1637.08 386.998,1638.54 389.469,1639.95 391.94,1641.32 394.412,1642.65 396.883,1643.93 399.354,1645.17 401.825,1646.37 404.297,1647.53 406.768,1648.65 409.239,1649.74 411.71,1650.79 414.181,1651.8 416.653,1652.79 419.124,1653.74 421.595,1654.66 424.066,1655.54 426.538,1656.4 429.009,1657.23 431.48,1658.04 433.951,1658.81 436.422,1659.56 438.894,1660.29 441.365,1660.99 443.836,1661.66 446.307,1662.32 448.779,1662.95 451.25,1663.56 453.721,1664.14 456.192,1664.71 458.664,1665.26 461.135,1665.79 463.606,1666.3 466.077,1666.79 468.548,1667.26 471.02,1667.72 473.491,1668.16 475.962,1668.58 478.433,1668.99 480.905,1669.38 483.376,1669.76 485.847,1670.12 488.318,1670.47 490.789,1670.8 493.261,1671.12 495.732,1671.43 498.203,1671.73 500.674,1672.01 503.146,1672.28 505.617,1672.53 508.088,1672.78 510.559,1673.01 513.03,1673.23 515.502,1673.44 517.973,1673.64 520.444,1673.83 522.915,1674.01 525.387,1674.17 527.858,1674.33 530.329,1674.48 532.8,1674.61 535.272,1674.73 537.743,1674.85 540.214,1674.95 542.685,1675.04 545.156,1675.13 547.628,1675.2 550.099,1675.26 552.57,1675.31 555.041,1675.36 557.513,1675.39 559.984,1675.41 562.455,1675.41 564.926,1675.41 567.397,1675.4 569.869,1675.37 572.34,1675.34 574.811,1675.29 577.282,1675.23 579.754,1675.15 582.225,1675.06 584.696,1674.96 587.167,1674.85 589.638,1674.72 592.11,1674.58 594.581,1674.42 597.052,1674.25 599.523,1674.06 601.995,1673.85 604.466,1673.63 606.937,1673.39 609.408,1673.12 611.88,1672.84 614.351,1672.54 616.822,1672.21 619.293,1671.86 621.764,1671.48 624.236,1671.08 626.707,1670.65 629.178,1670.2 631.649,1669.71 634.121,1669.19 636.592,1668.64 639.063,1668.05 641.534,1667.42 644.005,1666.76 646.477,1666.04 648.948,1665.28 651.419,1664.47 653.89,1663.6 656.362,1662.67 658.833,1661.67 661.304,1660.61 663.775,1659.48 666.246,1658.26 668.718,1656.95 671.189,1655.54 673.66,1654.03 676.131,1652.42 678.603,1650.68 681.074,1648.81 683.545,1646.8 686.016,1644.64 688.488,1642.31 690.959,1639.79 693.43,1637.06 695.901,1634.12 698.372,1630.93 700.844,1627.48 703.315,1623.75 705.786,1619.71 708.257,1615.34 710.729,1610.62 713.2,1605.53 715.671,1600.01 718.142,1594.04 720.613,1587.57 723.085,1580.57 725.556,1573.03 728.027,1564.91 730.498,1556.2 732.97,1546.9 735.441,1537 737.912,1526.5 740.383,1515.41 742.854,1503.74 745.326,1491.51 747.797,1478.74 750.268,1465.42 752.739,1451.71 755.211,1437.79 757.682,1423.82 760.153,1409.95 762.624,1396.33 765.096,1383.1 767.567,1370.39 770.038,1358.32 772.509,1347.02 774.98,1336.59 777.452,1327.14 779.923,1318.74 782.394,1311.5 784.865,1305.49 787.337,1300.73 789.808,1297.18 792.279,1294.79 794.75,1293.52 797.221,1293.31 799.693,1294.09 802.164,1295.8 804.635,1298.36 807.106,1301.7 809.578,1305.73 812.049,1310.37 814.52,1315.53 816.991,1321.1 819.462,1326.99 821.934,1333.17 824.405,1339.6 826.876,1346.23 829.347,1353.02 831.819,1359.95 834.29,1366.98 836.761,1374.08 839.232,1381.22 841.704,1388.37 844.175,1395.51 846.646,1402.61 849.117,1409.65 851.588,1416.62 854.06,1423.5 856.531,1430.26 859.002,1436.91 861.473,1443.44 863.945,1449.86 866.416,1456.15 868.887,1462.31 871.358,1468.34 873.829,1474.23 876.301,1480 878.772,1485.62 881.243,1491.11 883.714,1496.46 886.186,1501.68 888.657,1506.76 891.128,1511.71 893.599,1516.53 896.07,1521.22 898.542,1525.78 901.013,1530.21 903.484,1534.52 905.955,1538.71 908.427,1542.78 910.898,1546.73 913.369,1550.57 915.84,1554.29 918.312,1557.91 920.783,1561.42 923.254,1564.82 925.725,1568.12 928.196,1571.32 930.668,1574.42 933.139,1577.43 935.61,1580.35 938.081,1583.18 940.553,1585.92 943.024,1588.58 945.495,1591.15 947.966,1593.64 950.437,1596.06 952.909,1598.4 955.38,1600.66 957.851,1602.86 960.322,1604.98 962.794,1607.04 965.265,1609.03 967.736,1610.96 970.207,1612.82 972.678,1614.63 975.15,1616.37 977.621,1618.06 980.092,1619.7 982.563,1621.28 985.035,1622.81 987.506,1624.29 989.977,1625.72 992.448,1627.1 994.92,1628.44 997.391,1629.73 999.862,1630.98 1002.33,1632.19 1004.8,1633.36 1007.28,1634.49 1009.75,1635.59 1012.22,1636.64 1014.69,1637.67 1017.16,1638.65 1019.63,1639.61 1022.1,1640.53 1024.57,1641.43 1027.05,1642.29 1029.52,1643.13 1031.99,1643.94 1034.46,1644.73 1036.93,1645.49 1039.4,1646.23 1041.87,1646.95 1044.34,1647.64 1046.82,1648.32 1049.29,1648.98 1051.76,1649.63 1054.23,1650.26 1056.7,1650.87 1059.17,1651.47 1061.64,1652.06 1064.11,1652.64 1066.59,1653.21 1069.06,1653.76 1071.53,1654.31 1074,1654.85 1076.47,1655.38 1078.94,1655.9 1081.41,1656.41 1083.88,1656.92 1086.35,1657.41 1088.83,1657.9 1091.3,1658.38 1093.77,1658.85 1096.24,1659.31 1098.71,1659.75 1101.18,1660.19 1103.65,1660.62 1106.12,1661.04 1108.6,1661.44 1111.07,1661.83 1113.54,1662.22 1116.01,1662.58 1118.48,1662.94 1120.95,1663.28 1123.42,1663.61 1125.89,1663.93 1128.37,1664.23 1130.84,1664.52 1133.31,1664.79 1135.78,1665.06 1138.25,1665.3 1140.72,1665.54 1143.19,1665.76 1145.66,1665.96 1148.14,1666.15 1150.61,1666.33 1153.08,1666.49 1155.55,1666.64 1158.02,1666.78 1160.49,1666.9 1162.96,1667 1165.43,1667.09 1167.91,1667.16 1170.38,1667.22 1172.85,1667.26 1175.32,1667.29 1177.79,1667.3 1180.26,1667.29 1182.73,1667.26 1185.2,1667.22 1187.68,1667.16 1190.15,1667.08 1192.62,1666.98 1195.09,1666.86 1197.56,1666.72 1200.03,1666.56 1202.5,1666.38 1204.97,1666.17 1207.44,1665.94 1209.92,1665.68 1212.39,1665.4 1214.86,1665.08 1217.33,1664.74 1219.8,1664.37 1222.27,1663.96 1224.74,1663.52 1227.21,1663.04 1229.69,1662.52 1232.16,1661.96 1234.63,1661.36 1237.1,1660.71 1239.57,1660 1242.04,1659.25 1244.51,1658.44 1246.98,1657.56 1249.46,1656.62 1251.93,1655.61 1254.4,1654.52 1256.87,1653.34 1259.34,1652.08 1261.81,1650.72 1264.28,1649.26 1266.75,1647.68 1269.23,1645.98 1271.7,1644.15 1274.17,1642.17 1276.64,1640.04 1279.11,1637.74 1281.58,1635.25 1284.05,1632.57 1286.52,1629.68 1289,1626.55 1291.47,1623.17 1293.94,1619.5 1296.41,1615.54 1298.88,1611.25 1301.35,1606.61 1303.82,1601.58 1306.29,1596.14 1308.77,1590.25 1311.24,1583.88 1313.71,1576.99 1316.18,1569.56 1318.65,1561.54 1321.12,1552.88 1323.59,1543.55 1326.06,1533.5 1328.53,1522.71 1331.01,1511.17 1333.48,1498.87 1335.95,1485.82 1338.42,1472.05 1340.89,1457.58 1343.36,1442.45 1345.83,1426.73 1348.3,1410.48 1350.78,1393.76 1353.25,1376.68 1355.72,1359.33 1358.19,1341.9 1360.66,1324.59 1363.13,1307.61 1365.6,1291.12 1368.07,1275.31 1370.55,1260.3 1373.02,1246.24 1375.49,1233.26 1377.96,1221.44 1380.43,1210.88 1382.9,1201.66 1385.37,1193.83 1387.84,1187.42 1390.32,1182.4 1392.79,1178.7 1395.26,1176.25 1397.73,1174.98 1400.2,1174.82 1402.67,1175.7 1405.14,1177.53 1407.61,1180.26 1410.09,1183.79 1412.56,1188.05 1415.03,1192.95 1417.5,1198.42 1419.97,1204.36 1422.44,1210.7 1424.91,1217.36 1427.38,1224.32 1429.86,1231.52 1432.33,1238.94 1434.8,1246.52 1437.27,1254.24 1439.74,1262.06 1442.21,1269.95 1444.68,1277.89 1447.15,1285.85 1449.63,1293.81 1452.1,1301.76 1454.57,1309.66 1457.04,1317.53 1459.51,1325.33 1461.98,1333.07 1464.45,1340.73 1466.92,1348.31 1469.39,1355.8 1471.87,1363.2 1474.34,1370.51 1476.81,1377.73 1479.28,1384.84 1481.75,1391.85 1484.22,1398.75 1486.69,1405.56 1489.16,1412.26 1491.64,1418.85 1494.11,1425.34 1496.58,1431.73 1499.05,1438.01 1501.52,1444.19 1503.99,1450.27 1506.46,1456.24 1508.93,1462.1 1511.41,1467.86 1513.88,1473.52 1516.35,1479.07 1518.82,1484.52 1521.29,1489.86 1523.76,1495.09 1526.23,1500.22 1528.7,1505.24 1531.18,1510.15 1533.65,1514.96 1536.12,1519.66 1538.59,1524.26 1541.06,1528.75 1543.53,1533.13 1546,1537.41 1548.47,1541.58 1550.95,1545.65 1553.42,1549.62 1555.89,1553.49 1558.36,1557.25 1560.83,1560.92 1563.3,1564.48 1565.77,1567.96 1568.24,1571.33 1570.72,1574.61 1573.19,1577.8 1575.66,1580.9 1578.13,1583.91 1580.6,1586.84 1583.07,1589.68 1585.54,1592.44 1588.01,1595.11 1590.48,1597.71 1592.96,1600.23 1595.43,1602.67 1597.9,1605.04 1600.37,1607.34 1602.84,1609.57 1605.31,1611.73 1607.78,1613.82 1610.25,1615.85 1612.73,1617.82 1615.2,1619.72 1617.67,1621.57 1620.14,1623.35 1622.61,1625.09 1625.08,1626.76 1627.55,1628.39 1630.02,1629.96 1632.5,1631.48 1634.97,1632.95 1637.44,1634.38 1639.91,1635.76 1642.38,1637.09 1644.85,1638.39 1647.32,1639.64 1649.79,1640.84 1652.27,1642.01 1654.74,1643.14 1657.21,1644.24 1659.68,1645.29 1662.15,1646.32 1664.62,1647.3 1667.09,1648.26 1669.56,1649.18 1672.04,1650.07 1674.51,1650.93 1676.98,1651.76 1679.45,1652.56 1681.92,1653.33 1684.39,1654.08 1686.86,1654.8 1689.33,1655.49 1691.81,1656.16 1694.28,1656.8 1696.75,1657.42 1699.22,1658.02 1701.69,1658.6 1704.16,1659.15 1706.63,1659.68 1709.1,1660.19 1711.57,1660.68 1714.05,1661.14 1716.52,1661.59 1718.99,1662.02 1721.46,1662.43 1723.93,1662.82 1726.4,1663.2 1728.87,1663.55 1731.34,1663.89 1733.82,1664.21 1736.29,1664.52 1738.76,1664.81 1741.23,1665.08 1743.7,1665.33 1746.17,1665.57 1748.64,1665.79 1751.11,1665.99 1753.59,1666.18 1756.06,1666.36 1758.53,1666.51 1761,1666.66 1763.47,1666.78 1765.94,1666.89 1768.41,1666.98 1770.88,1667.06 1773.36,1667.12 1775.83,1667.16 1778.3,1667.19 1780.77,1667.2 1783.24,1667.19 1785.71,1667.17 1788.18,1667.12 1790.65,1667.06 1793.13,1666.98 1795.6,1666.88 1798.07,1666.76 1800.54,1666.61 1803.01,1666.45 1805.48,1666.26 1807.95,1666.05 1810.42,1665.81 1812.9,1665.55 1815.37,1665.26 1817.84,1664.94 1820.31,1664.6 1822.78,1664.22 1825.25,1663.8 1827.72,1663.36 1830.19,1662.88 1832.67,1662.36 1835.14,1661.8 1837.61,1661.2 1840.08,1660.56 1842.55,1659.86 1845.02,1659.12 1847.49,1658.32 1849.96,1657.47 1852.43,1656.55 1854.91,1655.56 1857.38,1654.5 1859.85,1653.36 1862.32,1652.14 1864.79,1650.83 1867.26,1649.43 1869.73,1647.93 1872.2,1646.32 1874.68,1644.58 1877.15,1642.73 1879.62,1640.73 1882.09,1638.59 1884.56,1636.29 1887.03,1633.83 1889.5,1631.18 1891.97,1628.33 1894.45,1625.26 1896.92,1621.96 1899.39,1618.4 1901.86,1614.56 1904.33,1610.42 1906.8,1605.96 1909.27,1601.13 1911.74,1595.93 1914.22,1590.32 1916.69,1584.28 1919.16,1577.79 1921.63,1570.77 1924.1,1563.17 1926.57,1554.93 1929.04,1546.01 1931.51,1536.36 1933.99,1525.94 1936.46,1514.71 1938.93,1502.64 1941.4,1489.69 1943.87,1475.85 1946.34,1461.09 1948.81,1445.39 1951.28,1428.75 1953.76,1411.14 1956.23,1392.58 1958.7,1373.06 1961.17,1352.56 1963.64,1331.12 1966.11,1308.95 1968.58,1286.24 1971.05,1263.2 1973.52,1240.03 1976,1216.95 1978.47,1194.13 1980.94,1171.8 1983.41,1150.14 1985.88,1129.34 1988.35,1109.61 1990.82,1091.14 1993.29,1074.12 1995.77,1058.73 1998.24,1045.15 2000.71,1033.44 2003.18,1023.6 2005.65,1015.68 2008.12,1009.65 2010.59,1005.49 2013.06,1003.15 2015.54,1002.58 2018.01,1003.68 2020.48,1006.35 2022.95,1010.46 2025.42,1015.87 2027.89,1022.4 2030.36,1029.87 2032.83,1038.11 2035.31,1047.11 2037.78,1056.77 2040.25,1067.01 2042.72,1077.73 2045.19,1088.87 2047.66,1100.34 2050.13,1112.07 2052.6,1124 2055.08,1136.08 2057.55,1148.24 2060.02,1160.44 2062.49,1172.64 2064.96,1184.8 2067.43,1196.89 2069.9,1208.88 2072.37,1220.75 2074.85,1232.48 2077.32,1244.06 2079.79,1255.46 2082.26,1266.68 2084.73,1277.7 2087.2,1288.52 2089.67,1299.13 2092.14,1309.52 2094.62,1319.69 2097.09,1329.63 2099.56,1339.34 2102.03,1348.84 2104.5,1358.1 2106.97,1367.14 2109.44,1375.95 2111.91,1384.54 2114.38,1392.91 2116.86,1401.06 2119.33,1408.99 2121.8,1416.71 2124.27,1424.22 2126.74,1431.53 2129.21,1438.63 2131.68,1445.52 2134.15,1452.23 2136.63,1458.73 2139.1,1465.06 2141.57,1471.19 2144.04,1477.15 2146.51,1482.94 2148.98,1488.55 2151.45,1494 2153.92,1499.28 2156.4,1504.41 2158.87,1509.38 2161.34,1514.2 2163.81,1518.87 2166.28,1523.41 2168.75,1527.8 2171.22,1532.06 2173.69,1536.18 2176.17,1540.18 2178.64,1544.05 2181.11,1547.81 2183.58,1551.44 2186.05,1554.96 2188.52,1558.37 2190.99,1561.68 2193.46,1564.87 2195.94,1567.97 2198.41,1570.97 2200.88,1573.87 2203.35,1576.68 2205.82,1579.39 2208.29,1582.02 2210.76,1584.57 2213.23,1587.03 2215.71,1589.41 2218.18,1591.71 2220.65,1593.94 2223.12,1596.09 2225.59,1598.17 2228.06,1600.19 2230.53,1602.13 2233,1604.01 2235.47,1605.83 2237.95,1607.58 2240.42,1609.28 2242.89,1610.91 2245.36,1612.49 2247.83,1614.02 2250.3,1615.49 2252.77,1616.91 2255.24,1618.27 2257.72,1619.59 2260.19,1620.86 2262.66,1622.09 2265.13,1623.27 2267.6,1624.41 2270.07,1625.5 2272.54,1626.56 2275.01,1627.57 2277.49,1628.55 2279.96,1629.49 2282.43,1630.39 2284.9,1631.26 2287.37,1632.09 2289.84,1632.9 2292.31,1633.67 2294.78,1634.41 2297.26,1635.12 2299.73,1635.81 2302.2,1636.47 2304.67,1637.1 2307.14,1637.72 2309.61,1638.31 2312.08,1638.88 2314.55,1639.43 2317.03,1639.96 2319.5,1640.48 2321.97,1640.99 2324.44,1641.48 2326.91,1641.96 2329.38,1642.42 2331.85,1642.88 2334.32,1643.33 2336.8,1643.77 2339.27,1644.21 2341.74,1644.63 2344.21,1645.05 2346.68,1645.46 2349.15,1645.86 2351.62,1646.26 2354.09,1646.64 2356.56,1647.02 2359.04,1647.38 2361.51,1647.74 2363.98,1648.08 2366.45,1648.41 2368.92,1648.72 2371.39,1649.02 2373.86,1649.31 2376.33,1649.57 2378.81,1649.83 2381.28,1650.06 2383.75,1650.27 2386.22,1650.47 2388.69,1650.64 2391.16,1650.79 2393.63,1650.92 2396.1,1651.03 2398.58,1651.12 2401.05,1651.19 2403.52,1651.22 2405.99,1651.24 2408.46,1651.23 2410.93,1651.19 2413.4,1651.13 2415.87,1651.03 2418.35,1650.91 2420.82,1650.76 2423.29,1650.58 2425.76,1650.36 2428.23,1650.12 2430.7,1649.83 2433.17,1649.51 2435.64,1649.16 2438.12,1648.76 2440.59,1648.32 2443.06,1647.84 2445.53,1647.31 2448,1646.74 2450.47,1646.11 2452.94,1645.43 2455.41,1644.7 2457.89,1643.91 2460.36,1643.05 2462.83,1642.13 2465.3,1641.13 2467.77,1640.07 2470.24,1638.92 2472.71,1637.69 2475.18,1636.36 2477.66,1634.94 2480.13,1633.41 2482.6,1631.78 2485.07,1630.02 2487.54,1628.14 2490.01,1626.11 2492.48,1623.94 2494.95,1621.62 2497.42,1619.12 2499.9,1616.44 2502.37,1613.56 2504.84,1610.47 2507.31,1607.15 2509.78,1603.59 2512.25,1599.75 2514.72,1595.63 2517.19,1591.2 2519.67,1586.43 2522.14,1581.3 2524.61,1575.79 2527.08,1569.87 2529.55,1563.49 2532.02,1556.62 2534.49,1549.22 2536.96,1541.25 2539.44,1532.67 2541.91,1523.45 2544.38,1513.54 2546.85,1502.92 2549.32,1491.55 2551.79,1479.39 2554.26,1466.41 2556.73,1452.57 2559.21,1437.84 2561.68,1422.19 2564.15,1405.58 2566.62,1387.99 2569.09,1369.45 2571.56,1350 2574.03,1329.69 2576.5,1308.61 2578.98,1286.83 2581.45,1264.47 2583.92,1241.63 2586.39,1218.45 2588.86,1195.08 2591.33,1171.69 2593.8,1148.43 2596.27,1125.52 2598.75,1103.16 2601.22,1081.53 2603.69,1060.85 2606.16,1041.32 2608.63,1023.12 2611.1,1006.39 2613.57,991.241 2616.04,977.777 2618.51,966.059 2620.99,956.123 2623.46,947.981 2625.93,941.614 2628.4,936.979 2630.87,934.011 2633.34,932.649 2635.81,932.809 2638.28,934.399 2640.76,937.322 "></polyline>
<polyline clip-path="url(#clip962)" style="stroke:#c271d2; stroke-linecap:round; stroke-linejoin:round; stroke-width:8; stroke-opacity:1; fill:none" points="172.001,522.428 174.473,510.6 176.944,499.718 179.415,489.866 181.886,481.129 184.357,473.593 186.829,467.345 189.3,462.474 191.771,459.066 194.242,457.21 196.714,456.99 199.185,458.491 201.656,461.79 204.127,466.958 206.598,474.058 209.07,483.141 211.541,494.247 214.012,507.396 216.483,522.589 218.955,539.802 221.426,558.992 223.897,580.092 226.368,603.009 228.84,627.614 231.311,653.758 233.782,681.275 236.253,709.98 238.724,739.672 241.196,770.129 243.667,801.137 246.138,832.467 248.609,863.887 251.081,895.186 253.552,926.167 256.023,956.653 258.494,986.483 260.965,1015.51 263.437,1043.62 265.908,1070.7 268.379,1096.68 270.85,1121.5 273.322,1145.13 275.793,1167.54 278.264,1188.72 280.735,1208.69 283.206,1227.44 285.678,1245.03 288.149,1261.47 290.62,1276.81 293.091,1291.1 295.563,1304.37 298.034,1316.68 300.505,1328.08 302.976,1338.61 305.448,1348.3 307.919,1357.22 310.39,1365.4 312.861,1372.87 315.332,1379.7 317.804,1385.9 320.275,1391.52 322.746,1396.6 325.217,1401.15 327.689,1405.21 330.16,1408.82 332.631,1411.99 335.102,1414.74 337.573,1417.1 340.045,1419.1 342.516,1420.73 344.987,1422.03 347.458,1423.01 349.93,1423.69 352.401,1424.07 354.872,1424.16 357.343,1423.99 359.814,1423.55 362.286,1422.86 364.757,1421.92 367.228,1420.75 369.699,1419.35 372.171,1417.73 374.642,1415.89 377.113,1413.83 379.584,1411.57 382.056,1409.1 384.527,1406.43 386.998,1403.56 389.469,1400.5 391.94,1397.24 394.412,1393.78 396.883,1390.14 399.354,1386.3 401.825,1382.27 404.297,1378.06 406.768,1373.66 409.239,1369.07 411.71,1364.29 414.181,1359.32 416.653,1354.17 419.124,1348.82 421.595,1343.28 424.066,1337.55 426.538,1331.63 429.009,1325.52 431.48,1319.2 433.951,1312.69 436.422,1305.98 438.894,1299.07 441.365,1291.96 443.836,1284.64 446.307,1277.11 448.779,1269.37 451.25,1261.43 453.721,1253.26 456.192,1244.88 458.664,1236.29 461.135,1227.47 463.606,1218.43 466.077,1209.16 468.548,1199.66 471.02,1189.94 473.491,1179.98 475.962,1169.78 478.433,1159.35 480.905,1148.67 483.376,1137.76 485.847,1126.6 488.318,1115.2 490.789,1103.55 493.261,1091.66 495.732,1079.52 498.203,1067.13 500.674,1054.5 503.146,1041.62 505.617,1028.49 508.088,1015.12 510.559,1001.51 513.03,987.664 515.502,973.586 517.973,959.274 520.444,944.73 522.915,929.958 525.387,914.964 527.858,899.755 530.329,884.343 532.8,868.738 535.272,852.955 537.743,837.012 540.214,820.925 542.685,804.716 545.156,788.408 547.628,772.025 550.099,755.593 552.57,739.142 555.041,722.704 557.513,706.31 559.984,689.996 562.455,673.797 564.926,657.712 567.397,641.801 569.869,626.152 572.34,610.854 574.811,595.999 577.282,581.679 579.754,567.988 582.225,555.024 584.696,542.882 587.167,531.663 589.638,521.467 592.11,512.396 594.581,504.556 597.052,498.051 599.523,492.989 601.995,489.479 604.466,487.631 606.937,487.558 609.408,489.373 611.88,493.192 614.351,499.131 616.822,507.311 619.293,517.877 621.764,530.894 624.236,546.274 626.707,563.913 629.178,583.696 631.649,605.493 634.121,629.164 636.592,654.554 639.063,681.497 641.534,709.815 644.005,739.314 646.477,769.792 648.948,801.031 651.419,832.801 653.89,864.86 656.362,896.954 658.833,928.815 661.304,960.164 663.775,990.733 666.246,1020.44 668.718,1049.18 671.189,1076.87 673.66,1103.4 676.131,1128.73 678.603,1152.78 681.074,1175.52 683.545,1196.92 686.016,1216.97 688.488,1235.68 690.959,1253.06 693.43,1269.15 695.901,1284 698.372,1297.66 700.844,1310.22 703.315,1321.77 705.786,1332.41 708.257,1342.27 710.729,1351.42 713.2,1359.79 715.671,1367.42 718.142,1374.36 720.613,1380.66 723.085,1386.36 725.556,1391.51 728.027,1396.13 730.498,1400.26 732.97,1403.94 735.441,1407.2 737.912,1410.07 740.383,1412.57 742.854,1414.72 745.326,1416.55 747.797,1418.08 750.268,1419.33 752.739,1420.33 755.211,1421.1 757.682,1421.64 760.153,1421.97 762.624,1422.1 765.096,1422.05 767.567,1421.82 770.038,1421.42 772.509,1420.87 774.98,1420.15 777.452,1419.29 779.923,1418.28 782.394,1417.13 784.865,1415.82 787.337,1414.38 789.808,1412.79 792.279,1411.06 794.75,1409.17 797.221,1407.14 799.693,1404.95 802.164,1402.62 804.635,1400.13 807.106,1397.48 809.578,1394.68 812.049,1391.71 814.52,1388.59 816.991,1385.3 819.462,1381.85 821.934,1378.23 824.405,1374.44 826.876,1370.48 829.347,1366.35 831.819,1362.04 834.29,1357.56 836.761,1352.9 839.232,1348.06 841.704,1343.05 844.175,1337.84 846.646,1332.45 849.117,1326.87 851.588,1321.1 854.06,1315.13 856.531,1308.96 859.002,1302.58 861.473,1296 863.945,1289.22 866.416,1282.22 868.887,1275.01 871.358,1267.58 873.829,1259.94 876.301,1252.06 878.772,1243.96 881.243,1235.63 883.714,1227.06 886.186,1218.26 888.657,1209.21 891.128,1199.92 893.599,1190.37 896.07,1180.57 898.542,1170.51 901.013,1160.19 903.484,1149.6 905.955,1138.74 908.427,1127.6 910.898,1116.18 913.369,1104.48 915.84,1092.49 918.312,1080.21 920.783,1067.64 923.254,1054.77 925.725,1041.6 928.196,1028.12 930.668,1014.33 933.139,1000.24 935.61,985.826 938.081,971.103 940.553,956.064 943.024,940.705 945.495,925.023 947.966,909.02 950.437,892.694 952.909,876.048 955.38,859.085 957.851,841.81 960.322,824.228 962.794,806.346 965.265,788.172 967.736,769.716 970.207,750.988 972.678,732.001 975.15,712.767 977.621,693.301 980.092,673.647 982.563,653.824 985.035,633.846 987.506,613.733 989.977,593.518 992.448,573.239 994.92,552.946 997.391,532.697 999.862,512.559 1002.33,492.608 1004.8,472.928 1007.28,453.615 1009.75,434.77 1012.22,416.507 1014.69,398.947 1017.16,382.219 1019.63,366.463 1022.1,351.828 1024.57,338.47 1027.05,326.555 1029.52,316.207 1031.99,307.684 1034.46,301.295 1036.93,297.315 1039.4,295.993 1041.87,297.547 1044.34,302.166 1046.82,310.01 1049.29,321.209 1051.76,335.865 1054.23,354.05 1056.7,375.806 1059.17,401.146 1061.64,430.055 1064.11,462.492 1066.59,498.152 1069.06,536.597 1071.53,577.387 1074,620.08 1076.47,664.235 1078.94,709.407 1081.41,755.152 1083.88,801.025 1086.35,846.577 1088.83,891.362 1091.3,934.93 1093.77,976.892 1096.24,1017.08 1098.71,1055.33 1101.18,1091.53 1103.65,1125.58 1106.12,1157.43 1108.6,1187.06 1111.07,1214.48 1113.54,1239.74 1116.01,1262.92 1118.48,1284.14 1120.95,1303.56 1123.42,1321.35 1125.89,1337.61 1128.37,1352.37 1130.84,1365.76 1133.31,1377.87 1135.78,1388.8 1138.25,1398.65 1140.72,1407.5 1143.19,1415.42 1145.66,1422.49 1148.14,1428.76 1150.61,1434.3 1153.08,1439.15 1155.55,1443.36 1158.02,1446.98 1160.49,1450.06 1162.96,1452.63 1165.43,1454.74 1167.91,1456.4 1170.38,1457.65 1172.85,1458.51 1175.32,1459.01 1177.79,1459.16 1180.26,1458.99 1182.73,1458.51 1185.2,1457.74 1187.68,1456.69 1190.15,1455.37 1192.62,1453.8 1195.09,1451.98 1197.56,1449.92 1200.03,1447.63 1202.5,1445.1 1204.97,1442.36 1207.44,1439.4 1209.92,1436.22 1212.39,1432.83 1214.86,1429.24 1217.33,1425.44 1219.8,1421.45 1222.27,1417.26 1224.74,1412.87 1227.21,1408.3 1229.69,1403.53 1232.16,1398.57 1234.63,1393.42 1237.1,1388.07 1239.57,1382.54 1242.04,1376.81 1244.51,1370.88 1246.98,1364.76 1249.46,1358.44 1251.93,1351.93 1254.4,1345.21 1256.87,1338.3 1259.34,1331.18 1261.81,1323.87 1264.28,1316.35 1266.75,1308.62 1269.23,1300.69 1271.7,1292.55 1274.17,1284.2 1276.64,1275.64 1279.11,1266.86 1281.58,1257.87 1284.05,1248.67 1286.52,1239.25 1289,1229.62 1291.47,1219.77 1293.94,1209.71 1296.41,1199.44 1298.88,1188.96 1301.35,1178.27 1303.82,1167.37 1306.29,1156.28 1308.77,1144.98 1311.24,1133.5 1313.71,1121.82 1316.18,1109.97 1318.65,1097.93 1321.12,1085.72 1323.59,1073.36 1326.06,1060.87 1328.53,1048.25 1331.01,1035.52 1333.48,1022.71 1335.95,1009.82 1338.42,996.883 1340.89,983.906 1343.36,970.91 1345.83,957.915 1348.3,944.939 1350.78,932.003 1353.25,919.127 1355.72,906.333 1358.19,893.642 1360.66,881.07 1363.13,868.629 1365.6,856.329 1368.07,844.179 1370.55,832.185 1373.02,820.35 1375.49,808.676 1377.96,797.163 1380.43,785.808 1382.9,774.606 1385.37,763.551 1387.84,752.639 1390.32,741.866 1392.79,731.219 1395.26,720.69 1397.73,710.271 1400.2,699.961 1402.67,689.758 1405.14,679.665 1407.61,669.689 1410.09,659.839 1412.56,650.125 1415.03,640.564 1417.5,631.172 1419.97,621.972 1422.44,612.987 1424.91,604.24 1427.38,595.76 1429.86,587.587 1432.33,579.762 1434.8,572.332 1437.27,565.344 1439.74,558.85 1442.21,552.904 1444.68,547.562 1447.15,542.885 1449.63,538.936 1452.1,535.779 1454.57,533.484 1457.04,532.121 1459.51,531.766 1461.98,532.474 1464.45,534.324 1466.92,537.397 1469.39,541.764 1471.87,547.484 1474.34,554.603 1476.81,563.158 1479.28,573.172 1481.75,584.656 1484.22,597.609 1486.69,612.021 1489.16,627.866 1491.64,645.109 1494.11,663.706 1496.58,683.62 1499.05,704.731 1501.52,726.893 1503.99,749.961 1506.46,773.794 1508.93,798.247 1511.41,823.182 1513.88,848.458 1516.35,873.938 1518.82,899.485 1521.29,924.964 1523.76,950.242 1526.23,975.185 1528.7,999.663 1531.18,1023.55 1533.65,1046.73 1536.12,1069.16 1538.59,1090.79 1541.06,1111.59 1543.53,1131.5 1546,1150.5 1548.47,1168.58 1550.95,1185.72 1553.42,1201.92 1555.89,1217.19 1558.36,1231.53 1560.83,1244.98 1563.3,1257.56 1565.77,1269.31 1568.24,1280.27 1570.72,1290.47 1573.19,1299.91 1575.66,1308.65 1578.13,1316.7 1580.6,1324.1 1583.07,1330.89 1585.54,1337.08 1588.01,1342.72 1590.48,1347.82 1592.96,1352.42 1595.43,1356.52 1597.9,1360.17 1600.37,1363.37 1602.84,1366.14 1605.31,1368.51 1607.78,1370.49 1610.25,1372.09 1612.73,1373.35 1615.2,1374.26 1617.67,1374.85 1620.14,1375.12 1622.61,1375.09 1625.08,1374.77 1627.55,1374.16 1630.02,1373.28 1632.5,1372.14 1634.97,1370.73 1637.44,1369.08 1639.91,1367.18 1642.38,1365.04 1644.85,1362.67 1647.32,1360.07 1649.79,1357.24 1652.27,1354.19 1654.74,1350.93 1657.21,1347.45 1659.68,1343.75 1662.15,1339.85 1664.62,1335.73 1667.09,1331.41 1669.56,1326.88 1672.04,1322.14 1674.51,1317.2 1676.98,1312.05 1679.45,1306.7 1681.92,1301.14 1684.39,1295.38 1686.86,1289.42 1689.33,1283.25 1691.81,1276.87 1694.28,1270.29 1696.75,1263.51 1699.22,1256.52 1701.69,1249.32 1704.16,1241.91 1706.63,1234.3 1709.1,1226.47 1711.57,1218.43 1714.05,1210.18 1716.52,1201.72 1718.99,1193.04 1721.46,1184.14 1723.93,1175.02 1726.4,1165.69 1728.87,1156.14 1731.34,1146.37 1733.82,1136.38 1736.29,1126.17 1738.76,1115.74 1741.23,1105.1 1743.7,1094.23 1746.17,1083.16 1748.64,1071.86 1751.11,1060.35 1753.59,1048.63 1756.06,1036.69 1758.53,1024.54 1761,1012.2 1763.47,999.656 1765.94,986.922 1768.41,973.997 1770.88,960.884 1773.36,947.59 1775.83,934.122 1778.3,920.488 1780.77,906.702 1783.24,892.774 1785.71,878.721 1788.18,864.559 1790.65,850.307 1793.13,835.984 1795.6,821.614 1798.07,807.219 1800.54,792.826 1803.01,778.463 1805.48,764.159 1807.95,749.945 1810.42,735.854 1812.9,721.922 1815.37,708.169 1817.84,694.601 1820.31,681.295 1822.78,668.334 1825.25,655.799 1827.72,643.771 1830.19,632.33 1832.67,621.555 1835.14,611.525 1837.61,602.317 1840.08,594.01 1842.55,586.678 1845.02,580.399 1847.49,575.246 1849.96,571.294 1852.43,568.616 1854.91,567.285 1857.38,567.373 1859.85,568.95 1862.32,572.088 1864.79,576.856 1867.26,583.323 1869.73,591.557 1872.2,601.627 1874.68,613.552 1877.15,627.26 1879.62,642.669 1882.09,659.688 1884.56,678.217 1887.03,698.148 1889.5,719.366 1891.97,741.746 1894.45,765.153 1896.92,789.448 1899.39,814.48 1901.86,840.092 1904.33,866.116 1906.8,892.377 1909.27,918.693 1911.74,944.871 1914.22,970.713 1916.69,996.086 1919.16,1020.91 1921.63,1045.09 1924.1,1068.54 1926.57,1091.21 1929.04,1113.03 1931.51,1133.94 1933.99,1153.93 1936.46,1172.95 1938.93,1190.99 1941.4,1208.05 1943.87,1224.14 1946.34,1239.27 1948.81,1253.46 1951.28,1266.76 1953.76,1279.22 1956.23,1290.89 1958.7,1301.85 1961.17,1312.15 1963.64,1321.79 1966.11,1330.8 1968.58,1339.22 1971.05,1347.08 1973.52,1354.43 1976,1361.29 1978.47,1367.68 1980.94,1373.65 1983.41,1379.21 1985.88,1384.38 1988.35,1389.19 1990.82,1393.65 1993.29,1397.77 1995.77,1401.57 1998.24,1405.05 2000.71,1408.25 2003.18,1411.16 2005.65,1413.79 2008.12,1416.16 2010.59,1418.27 2013.06,1420.13 2015.54,1421.75 2018.01,1423.12 2020.48,1424.26 2022.95,1425.18 2025.42,1425.87 2027.89,1426.35 2030.36,1426.61 2032.83,1426.66 2035.31,1426.5 2037.78,1426.14 2040.25,1425.58 2042.72,1424.83 2045.19,1423.89 2047.66,1422.76 2050.13,1421.45 2052.6,1419.95 2055.08,1418.27 2057.55,1416.42 2060.02,1414.38 2062.49,1412.17 2064.96,1409.78 2067.43,1407.21 2069.9,1404.47 2072.37,1401.56 2074.85,1398.47 2077.32,1395.21 2079.79,1391.78 2082.26,1388.17 2084.73,1384.38 2087.2,1380.43 2089.67,1376.29 2092.14,1371.97 2094.62,1367.48 2097.09,1362.81 2099.56,1357.95 2102.03,1352.91 2104.5,1347.68 2106.97,1342.27 2109.44,1336.66 2111.91,1330.86 2114.38,1324.86 2116.86,1318.67 2119.33,1312.28 2121.8,1305.68 2124.27,1298.87 2126.74,1291.85 2129.21,1284.62 2131.68,1277.17 2134.15,1269.5 2136.63,1261.61 2139.1,1253.48 2141.57,1245.13 2144.04,1236.53 2146.51,1227.7 2148.98,1218.62 2151.45,1209.29 2153.92,1199.71 2156.4,1189.87 2158.87,1179.77 2161.34,1169.4 2163.81,1158.75 2166.28,1147.83 2168.75,1136.63 2171.22,1125.14 2173.69,1113.36 2176.17,1101.29 2178.64,1088.91 2181.11,1076.23 2183.58,1063.24 2186.05,1049.93 2188.52,1036.31 2190.99,1022.36 2193.46,1008.09 2195.94,993.491 2198.41,978.557 2200.88,963.284 2203.35,947.666 2205.82,931.7 2208.29,915.383 2210.76,898.713 2213.23,881.69 2215.71,864.314 2218.18,846.587 2220.65,828.511 2223.12,810.09 2225.59,791.327 2228.06,772.228 2230.53,752.8 2233,733.051 2235.47,712.988 2237.95,692.621 2240.42,671.961 2242.89,651.048 2245.36,629.916 2247.83,608.565 2250.3,587.003 2252.77,565.25 2255.24,543.339 2257.72,521.311 2260.19,499.218 2262.66,477.125 2265.13,455.107 2267.6,433.248 2270.07,411.646 2272.54,390.409 2275.01,369.653 2277.49,349.509 2279.96,330.118 2282.43,311.629 2284.9,294.204 2287.37,278.018 2289.84,263.253 2292.31,250.103 2294.78,238.765 2297.26,229.449 2299.73,222.534 2302.2,218.384 2304.67,217.324 2307.14,219.642 2309.61,225.584 2312.08,235.358 2314.55,249.133 2317.03,267.038 2319.5,289.162 2321.97,315.556 2324.44,346.232 2326.91,381.174 2329.38,420.236 2331.85,462.9 2334.32,508.604 2336.8,556.787 2339.27,606.884 2341.74,658.333 2344.21,710.571 2346.68,763.032 2349.15,815.151 2351.62,866.362 2354.09,916.099 2356.56,963.844 2359.04,1009.37 2361.51,1052.5 2363.98,1093.1 2366.45,1131.08 2368.92,1166.39 2371.39,1199.04 2373.86,1229.05 2376.33,1256.51 2378.81,1281.56 2381.28,1304.36 2383.75,1325.13 2386.22,1344.09 2388.69,1361.26 2391.16,1376.79 2393.63,1390.8 2396.1,1403.44 2398.58,1414.8 2401.05,1425.01 2403.52,1434.15 2405.99,1442.33 2408.46,1449.61 2410.93,1456.07 2413.4,1461.78 2415.87,1466.77 2418.35,1471.12 2420.82,1474.89 2423.29,1478.12 2425.76,1480.85 2428.23,1483.12 2430.7,1484.96 2433.17,1486.41 2435.64,1487.48 2438.12,1488.21 2440.59,1488.61 2443.06,1488.71 2445.53,1488.53 2448,1488.07 2450.47,1487.35 2452.94,1486.39 2455.41,1485.19 2457.89,1483.77 2460.36,1482.12 2462.83,1480.27 2465.3,1478.21 2467.77,1475.95 2470.24,1473.5 2472.71,1470.86 2475.18,1468.05 2477.66,1465.05 2480.13,1461.89 2482.6,1458.55 2485.07,1455.05 2487.54,1451.39 2490.01,1447.57 2492.48,1443.59 2494.95,1439.45 2497.42,1435.15 2499.9,1430.7 2502.37,1426.09 2504.84,1421.32 2507.31,1416.41 2509.78,1411.34 2512.25,1406.13 2514.72,1400.76 2517.19,1395.25 2519.67,1389.6 2522.14,1383.8 2524.61,1377.87 2527.08,1371.79 2529.55,1365.58 2532.02,1359.23 2534.49,1352.76 2536.96,1346.15 2539.44,1339.43 2541.91,1332.59 2544.38,1325.65 2546.85,1318.6 2549.32,1311.45 2551.79,1304.22 2554.26,1296.91 2556.73,1289.53 2559.21,1282.09 2561.68,1274.6 2564.15,1267.08 2566.62,1259.52 2569.09,1251.95 2571.56,1244.38 2574.03,1236.84 2576.5,1229.33 2578.98,1221.88 2581.45,1214.49 2583.92,1207.17 2586.39,1199.95 2588.86,1192.82 2591.33,1185.79 2593.8,1178.88 2596.27,1172.09 2598.75,1165.42 2601.22,1158.88 2603.69,1152.47 2606.16,1146.18 2608.63,1140.01 2611.1,1133.94 2613.57,1127.97 2616.04,1122.09 2618.51,1116.27 2620.99,1110.52 2623.46,1104.81 2625.93,1099.13 2628.4,1093.45 2630.87,1087.75 2633.34,1082.03 2635.81,1076.26 2638.28,1070.42 2640.76,1064.51 "></polyline>
<polyline clip-path="url(#clip962)" style="stroke:#ac8d18; stroke-linecap:round; stroke-linejoin:round; stroke-width:8; stroke-opacity:1; fill:none" points="172.001,1573.44 174.473,1566.45 176.944,1558.9 179.415,1550.74 181.886,1541.94 184.357,1532.46 186.829,1522.26 189.3,1511.29 191.771,1499.53 194.242,1486.95 196.714,1473.5 199.185,1459.19 201.656,1443.98 204.127,1427.88 206.598,1410.89 209.07,1393.04 211.541,1374.36 214.012,1354.91 216.483,1334.75 218.955,1313.98 221.426,1292.7 223.897,1271.06 226.368,1249.2 228.84,1227.29 231.311,1205.51 233.782,1184.06 236.253,1163.13 238.724,1142.93 241.196,1123.65 243.667,1105.49 246.138,1088.64 248.609,1073.25 251.081,1059.47 253.552,1047.43 256.023,1037.2 258.494,1028.85 260.965,1022.42 263.437,1017.92 265.908,1015.34 268.379,1014.64 270.85,1015.74 273.322,1018.57 275.793,1023.05 278.264,1029.07 280.735,1036.52 283.206,1045.28 285.678,1055.22 288.149,1066.21 290.62,1078.14 293.091,1090.89 295.563,1104.32 298.034,1118.32 300.505,1132.8 302.976,1147.65 305.448,1162.77 307.919,1178.08 310.39,1193.5 312.861,1208.95 315.332,1224.37 317.804,1239.69 320.275,1254.87 322.746,1269.84 325.217,1284.58 327.689,1299.05 330.16,1313.21 332.631,1327.04 335.102,1340.52 337.573,1353.63 340.045,1366.35 342.516,1378.68 344.987,1390.62 347.458,1402.15 349.93,1413.27 352.401,1424 354.872,1434.33 357.343,1444.26 359.814,1453.81 362.286,1462.96 364.757,1471.75 367.228,1480.16 369.699,1488.22 372.171,1495.92 374.642,1503.29 377.113,1510.34 379.584,1517.06 382.056,1523.49 384.527,1529.62 386.998,1535.46 389.469,1541.04 391.94,1546.35 394.412,1551.41 396.883,1556.23 399.354,1560.83 401.825,1565.2 404.297,1569.35 406.768,1573.31 409.239,1577.06 411.71,1580.63 414.181,1584.03 416.653,1587.25 419.124,1590.3 421.595,1593.2 424.066,1595.95 426.538,1598.55 429.009,1601.02 431.48,1603.36 433.951,1605.56 436.422,1607.65 438.894,1609.62 441.365,1611.48 443.836,1613.23 446.307,1614.88 448.779,1616.42 451.25,1617.87 453.721,1619.22 456.192,1620.49 458.664,1621.66 461.135,1622.75 463.606,1623.75 466.077,1624.67 468.548,1625.51 471.02,1626.27 473.491,1626.96 475.962,1627.56 478.433,1628.1 480.905,1628.55 483.376,1628.94 485.847,1629.24 488.318,1629.48 490.789,1629.64 493.261,1629.72 495.732,1629.72 498.203,1629.65 500.674,1629.49 503.146,1629.26 505.617,1628.94 508.088,1628.53 510.559,1628.03 513.03,1627.43 515.502,1626.73 517.973,1625.93 520.444,1625.03 522.915,1624.01 525.387,1622.88 527.858,1621.63 530.329,1620.25 532.8,1618.73 535.272,1617.06 537.743,1615.24 540.214,1613.25 542.685,1611.07 545.156,1608.7 547.628,1606.11 550.099,1603.3 552.57,1600.24 555.041,1596.91 557.513,1593.31 559.984,1589.4 562.455,1585.16 564.926,1580.62 567.397,1575.72 569.869,1570.42 572.34,1564.66 574.811,1558.4 577.282,1551.6 579.754,1544.19 582.225,1536.16 584.696,1527.45 587.167,1518.02 589.638,1507.85 592.11,1496.91 594.581,1485.15 597.052,1472.57 599.523,1459.12 601.995,1444.78 604.466,1429.55 606.937,1413.4 609.408,1396.31 611.88,1378.27 614.351,1359.27 616.822,1339.3 619.293,1318.34 621.764,1296.43 624.236,1273.79 626.707,1250.63 629.178,1227.17 631.649,1203.61 634.121,1180.15 636.592,1157 639.063,1134.35 641.534,1112.39 644.005,1091.33 646.477,1071.35 648.948,1052.64 651.419,1035.37 653.89,1019.73 656.362,1005.9 658.833,994.047 661.304,984.348 663.775,976.938 666.246,971.733 668.718,968.696 671.189,967.793 673.66,968.98 676.131,972.198 678.603,977.374 681.074,984.424 683.545,993.247 686.016,1003.73 688.488,1015.75 690.959,1029.17 693.43,1043.82 695.901,1059.56 698.372,1076.19 700.844,1093.52 703.315,1111.34 705.786,1129.45 708.257,1147.59 710.729,1165.64 713.2,1183.73 715.671,1201.79 718.142,1219.73 720.613,1237.49 723.085,1255 725.556,1272.2 728.027,1289.04 730.498,1305.48 732.97,1321.49 735.441,1337.02 737.912,1352.07 740.383,1366.62 742.854,1380.67 745.326,1394.2 747.797,1407.23 750.268,1419.75 752.739,1431.76 755.211,1443.27 757.682,1454.28 760.153,1464.82 762.624,1474.88 765.096,1484.49 767.567,1493.66 770.038,1502.39 772.509,1510.7 774.98,1518.62 777.452,1526.14 779.923,1533.3 782.394,1540.1 784.865,1546.57 787.337,1552.71 789.808,1558.55 792.279,1564.09 794.75,1569.36 797.221,1574.35 799.693,1579.09 802.164,1583.59 804.635,1587.86 807.106,1591.91 809.578,1595.75 812.049,1599.4 814.52,1602.86 816.991,1606.13 819.462,1609.24 821.934,1612.19 824.405,1614.98 826.876,1617.63 829.347,1620.13 831.819,1622.51 834.29,1624.76 836.761,1626.9 839.232,1628.92 841.704,1630.83 844.175,1632.65 846.646,1634.36 849.117,1635.99 851.588,1637.52 854.06,1638.97 856.531,1640.34 859.002,1641.63 861.473,1642.85 863.945,1644 866.416,1645.08 868.887,1646.1 871.358,1647.05 873.829,1647.94 876.301,1648.78 878.772,1649.56 881.243,1650.28 883.714,1650.95 886.186,1651.58 888.657,1652.15 891.128,1652.67 893.599,1653.15 896.07,1653.58 898.542,1653.96 901.013,1654.3 903.484,1654.59 905.955,1654.84 908.427,1655.04 910.898,1655.2 913.369,1655.32 915.84,1655.39 918.312,1655.41 920.783,1655.39 923.254,1655.32 925.725,1655.2 928.196,1655.03 930.668,1654.81 933.139,1654.53 935.61,1654.2 938.081,1653.81 940.553,1653.35 943.024,1652.83 945.495,1652.25 947.966,1651.59 950.437,1650.86 952.909,1650.05 955.38,1649.15 957.851,1648.15 960.322,1647.06 962.794,1645.86 965.265,1644.54 967.736,1643.09 970.207,1641.5 972.678,1639.76 975.15,1637.86 977.621,1635.79 980.092,1633.51 982.563,1631.01 985.035,1628.27 987.506,1625.29 989.977,1622.03 992.448,1618.47 994.92,1614.58 997.391,1610.33 999.862,1605.67 1002.33,1600.56 1004.8,1594.95 1007.28,1588.79 1009.75,1582.03 1012.22,1574.6 1014.69,1566.43 1017.16,1557.45 1019.63,1547.6 1022.1,1536.78 1024.57,1524.92 1027.05,1511.93 1029.52,1497.74 1031.99,1482.24 1034.46,1465.28 1036.93,1446.76 1039.4,1426.6 1041.87,1404.75 1044.34,1381.19 1046.82,1355.93 1049.29,1329.01 1051.76,1300.49 1054.23,1270.48 1056.7,1239.1 1059.17,1206.5 1061.64,1172.87 1064.11,1138.43 1066.59,1103.65 1069.06,1069.02 1071.53,1035.06 1074,1002.22 1076.47,970.942 1078.94,941.628 1081.41,914.66 1083.88,890.389 1086.35,869.138 1088.83,851.204 1091.3,836.853 1093.77,826.265 1096.24,819.378 1098.71,816.109 1101.18,816.347 1103.65,819.953 1106.12,826.761 1108.6,836.575 1111.07,849.169 1113.54,864.292 1116.01,881.661 1118.48,900.966 1120.95,921.868 1123.42,944.001 1125.89,967.146 1128.37,991.141 1130.84,1015.76 1133.31,1040.79 1135.78,1066.03 1138.25,1091.33 1140.72,1116.51 1143.19,1141.44 1145.66,1166 1148.14,1190.08 1150.61,1213.6 1153.08,1236.48 1155.55,1258.68 1158.02,1280.14 1160.49,1300.81 1162.96,1320.68 1165.43,1339.73 1167.91,1357.96 1170.38,1375.37 1172.85,1391.96 1175.32,1407.74 1177.79,1422.72 1180.26,1436.91 1182.73,1450.35 1185.2,1463.06 1187.68,1475.06 1190.15,1486.4 1192.62,1497.1 1195.09,1507.18 1197.56,1516.68 1200.03,1525.63 1202.5,1534.05 1204.97,1541.98 1207.44,1549.43 1209.92,1556.44 1212.39,1563.02 1214.86,1569.2 1217.33,1575.01 1219.8,1580.47 1222.27,1585.59 1224.74,1590.4 1227.21,1594.91 1229.69,1599.15 1232.16,1603.14 1234.63,1606.87 1237.1,1610.38 1239.57,1613.68 1242.04,1616.78 1244.51,1619.68 1246.98,1622.41 1249.46,1624.97 1251.93,1627.38 1254.4,1629.64 1256.87,1631.76 1259.34,1633.75 1261.81,1635.62 1264.28,1637.37 1266.75,1639.02 1269.23,1640.55 1271.7,1641.99 1274.17,1643.33 1276.64,1644.58 1279.11,1645.76 1281.58,1646.85 1284.05,1647.86 1286.52,1648.8 1289,1649.67 1291.47,1650.48 1293.94,1651.22 1296.41,1651.9 1298.88,1652.52 1301.35,1653.09 1303.82,1653.6 1306.29,1654.05 1308.77,1654.45 1311.24,1654.81 1313.71,1655.11 1316.18,1655.36 1318.65,1655.56 1321.12,1655.71 1323.59,1655.81 1326.06,1655.86 1328.53,1655.87 1331.01,1655.83 1333.48,1655.73 1335.95,1655.59 1338.42,1655.4 1340.89,1655.15 1343.36,1654.86 1345.83,1654.51 1348.3,1654.1 1350.78,1653.64 1353.25,1653.12 1355.72,1652.54 1358.19,1651.9 1360.66,1651.2 1363.13,1650.43 1365.6,1649.59 1368.07,1648.67 1370.55,1647.68 1373.02,1646.62 1375.49,1645.47 1377.96,1644.23 1380.43,1642.9 1382.9,1641.47 1385.37,1639.94 1387.84,1638.3 1390.32,1636.54 1392.79,1634.66 1395.26,1632.66 1397.73,1630.51 1400.2,1628.22 1402.67,1625.77 1405.14,1623.15 1407.61,1620.35 1410.09,1617.36 1412.56,1614.16 1415.03,1610.74 1417.5,1607.09 1419.97,1603.18 1422.44,1599.01 1424.91,1594.55 1427.38,1589.78 1429.86,1584.69 1432.33,1579.24 1434.8,1573.41 1437.27,1567.19 1439.74,1560.54 1442.21,1553.43 1444.68,1545.86 1447.15,1537.79 1449.63,1529.19 1452.1,1520.06 1454.57,1510.35 1457.04,1500.06 1459.51,1489.16 1461.98,1477.63 1464.45,1465.47 1466.92,1452.66 1469.39,1439.2 1471.87,1425.11 1474.34,1410.4 1476.81,1395.1 1479.28,1379.26 1481.75,1362.92 1484.22,1346.14 1486.69,1329.01 1489.16,1311.59 1491.64,1293.99 1494.11,1276.3 1496.58,1258.61 1499.05,1241.07 1501.52,1223.84 1503.99,1207.08 1506.46,1190.94 1508.93,1175.54 1511.41,1161.01 1513.88,1147.47 1516.35,1135.02 1518.82,1123.75 1521.29,1113.74 1523.76,1105.08 1526.23,1097.83 1528.7,1092.03 1531.18,1087.74 1533.65,1084.98 1536.12,1083.69 1538.59,1083.84 1541.06,1085.38 1543.53,1088.25 1546,1092.38 1548.47,1097.72 1550.95,1104.19 1553.42,1111.72 1555.89,1120.2 1558.36,1129.57 1560.83,1139.71 1563.3,1150.53 1565.77,1161.92 1568.24,1173.76 1570.72,1186 1573.19,1198.56 1575.66,1211.39 1578.13,1224.39 1580.6,1237.51 1583.07,1250.68 1585.54,1263.84 1588.01,1276.94 1590.48,1289.93 1592.96,1302.78 1595.43,1315.45 1597.9,1327.89 1600.37,1340.1 1602.84,1352.05 1605.31,1363.72 1607.78,1375.1 1610.25,1386.18 1612.73,1396.94 1615.2,1407.37 1617.67,1417.47 1620.14,1427.23 1622.61,1436.66 1625.08,1445.75 1627.55,1454.52 1630.02,1462.95 1632.5,1471.05 1634.97,1478.83 1637.44,1486.29 1639.91,1493.45 1642.38,1500.3 1644.85,1506.85 1647.32,1513.12 1649.79,1519.11 1652.27,1524.84 1654.74,1530.31 1657.21,1535.53 1659.68,1540.51 1662.15,1545.25 1664.62,1549.77 1667.09,1554.08 1669.56,1558.18 1672.04,1562.08 1674.51,1565.79 1676.98,1569.32 1679.45,1572.66 1681.92,1575.84 1684.39,1578.86 1686.86,1581.71 1689.33,1584.41 1691.81,1586.97 1694.28,1589.38 1696.75,1591.66 1699.22,1593.8 1701.69,1595.82 1704.16,1597.71 1706.63,1599.48 1709.1,1601.14 1711.57,1602.68 1714.05,1604.11 1716.52,1605.44 1718.99,1606.67 1721.46,1607.79 1723.93,1608.82 1726.4,1609.75 1728.87,1610.58 1731.34,1611.32 1733.82,1611.97 1736.29,1612.52 1738.76,1612.99 1741.23,1613.36 1743.7,1613.64 1746.17,1613.82 1748.64,1613.91 1751.11,1613.91 1753.59,1613.81 1756.06,1613.62 1758.53,1613.32 1761,1612.92 1763.47,1612.41 1765.94,1611.79 1768.41,1611.06 1770.88,1610.21 1773.36,1609.24 1775.83,1608.15 1778.3,1606.93 1780.77,1605.57 1783.24,1604.07 1785.71,1602.41 1788.18,1600.6 1790.65,1598.61 1793.13,1596.44 1795.6,1594.08 1798.07,1591.51 1800.54,1588.72 1803.01,1585.69 1805.48,1582.42 1807.95,1578.88 1810.42,1575.06 1812.9,1570.94 1815.37,1566.51 1817.84,1561.78 1820.31,1556.7 1822.78,1551.22 1825.25,1545.32 1827.72,1538.95 1830.19,1532.08 1832.67,1524.69 1835.14,1516.74 1837.61,1508.21 1840.08,1499.08 1842.55,1489.33 1845.02,1478.96 1847.49,1467.94 1849.96,1456.27 1852.43,1443.95 1854.91,1430.97 1857.38,1417.34 1859.85,1403.05 1862.32,1388.13 1864.79,1372.57 1867.26,1356.39 1869.73,1339.62 1872.2,1322.26 1874.68,1304.4 1877.15,1286.19 1879.62,1267.79 1882.09,1249.33 1884.56,1230.96 1887.03,1212.83 1889.5,1195.08 1891.97,1177.86 1894.45,1161.29 1896.92,1145.52 1899.39,1130.69 1901.86,1116.91 1904.33,1104.33 1906.8,1093.07 1909.27,1083.27 1911.74,1075.04 1914.22,1068.5 1916.69,1063.67 1919.16,1060.5 1921.63,1058.98 1924.1,1059.1 1926.57,1060.82 1929.04,1064.11 1931.51,1068.92 1933.99,1075.19 1936.46,1082.83 1938.93,1091.78 1941.4,1101.93 1943.87,1113.19 1946.34,1125.43 1948.81,1138.53 1951.28,1152.35 1953.76,1166.75 1956.23,1181.56 1958.7,1196.61 1961.17,1211.79 1963.64,1227.11 1966.11,1242.53 1968.58,1257.95 1971.05,1273.33 1973.52,1288.59 1976,1303.67 1978.47,1318.54 1980.94,1333.13 1983.41,1347.42 1985.88,1361.38 1988.35,1374.97 1990.82,1388.18 1993.29,1400.99 1995.77,1413.39 1998.24,1425.38 2000.71,1436.95 2003.18,1448.08 2005.65,1458.8 2008.12,1469.09 2010.59,1478.96 2013.06,1488.42 2015.54,1497.47 2018.01,1506.12 2020.48,1514.39 2022.95,1522.27 2025.42,1529.79 2027.89,1536.96 2030.36,1543.79 2032.83,1550.28 2035.31,1556.47 2037.78,1562.34 2040.25,1567.93 2042.72,1573.24 2045.19,1578.29 2047.66,1583.08 2050.13,1587.63 2052.6,1591.95 2055.08,1596.05 2057.55,1599.94 2060.02,1603.63 2062.49,1607.13 2064.96,1610.45 2067.43,1613.6 2069.9,1616.58 2072.37,1619.41 2074.85,1622.1 2077.32,1624.64 2079.79,1627.06 2082.26,1629.35 2084.73,1631.52 2087.2,1633.57 2089.67,1635.52 2092.14,1637.37 2094.62,1639.12 2097.09,1640.78 2099.56,1642.35 2102.03,1643.84 2104.5,1645.25 2106.97,1646.58 2109.44,1647.84 2111.91,1649.03 2114.38,1650.16 2116.86,1651.22 2119.33,1652.23 2121.8,1653.18 2124.27,1654.07 2126.74,1654.91 2129.21,1655.7 2131.68,1656.45 2134.15,1657.15 2136.63,1657.8 2139.1,1658.41 2141.57,1658.98 2144.04,1659.5 2146.51,1659.99 2148.98,1660.44 2151.45,1660.85 2153.92,1661.22 2156.4,1661.56 2158.87,1661.86 2161.34,1662.12 2163.81,1662.35 2166.28,1662.55 2168.75,1662.71 2171.22,1662.84 2173.69,1662.93 2176.17,1662.99 2178.64,1663.01 2181.11,1663 2183.58,1662.94 2186.05,1662.85 2188.52,1662.72 2190.99,1662.55 2193.46,1662.34 2195.94,1662.08 2198.41,1661.77 2200.88,1661.41 2203.35,1661 2205.82,1660.55 2208.29,1660.03 2210.76,1659.46 2213.23,1658.83 2215.71,1658.13 2218.18,1657.35 2220.65,1656.5 2223.12,1655.55 2225.59,1654.52 2228.06,1653.38 2230.53,1652.12 2233,1650.75 2235.47,1649.24 2237.95,1647.59 2240.42,1645.78 2242.89,1643.79 2245.36,1641.59 2247.83,1639.18 2250.3,1636.53 2252.77,1633.65 2255.24,1630.49 2257.72,1627.03 2260.19,1623.25 2262.66,1619.09 2265.13,1614.51 2267.6,1609.46 2270.07,1603.89 2272.54,1597.72 2275.01,1590.9 2277.49,1583.34 2279.96,1574.97 2282.43,1565.7 2284.9,1555.44 2287.37,1544.1 2289.84,1531.56 2292.31,1517.73 2294.78,1502.5 2297.26,1485.75 2299.73,1467.32 2302.2,1447.03 2304.67,1424.76 2307.14,1400.43 2309.61,1374 2312.08,1345.46 2314.55,1314.84 2317.03,1282.24 2319.5,1247.75 2321.97,1211.53 2324.44,1173.78 2326.91,1134.72 2329.38,1094.74 2331.85,1054.46 2334.32,1014.55 2336.8,975.604 2339.27,938.199 2341.74,902.868 2344.21,870.111 2346.68,840.391 2349.15,814.135 2351.62,791.732 2354.09,773.538 2356.56,759.824 2359.04,750.547 2361.51,745.59 2363.98,744.81 2366.45,748.027 2368.92,755.03 2371.39,765.568 2373.86,779.361 2376.33,796.089 2378.81,815.4 2381.28,836.907 2383.75,860.187 2386.22,884.843 2388.69,910.693 2391.16,937.473 2393.63,964.925 2396.1,992.809 2398.58,1020.91 2401.05,1049.03 2403.52,1076.99 2405.99,1104.63 2408.46,1131.83 2410.93,1158.46 2413.4,1184.43 2415.87,1209.68 2418.35,1234.12 2420.82,1257.69 2423.29,1280.38 2425.76,1302.15 2428.23,1322.99 2430.7,1342.91 2433.17,1361.88 2435.64,1379.93 2438.12,1397.06 2440.59,1413.29 2443.06,1428.64 2445.53,1443.16 2448,1456.87 2450.47,1469.8 2452.94,1481.99 2455.41,1493.48 2457.89,1504.29 2460.36,1514.46 2462.83,1524.02 2465.3,1533 2467.77,1541.43 2470.24,1549.35 2472.71,1556.77 2475.18,1563.74 2477.66,1570.27 2480.13,1576.4 2482.6,1582.15 2485.07,1587.54 2487.54,1592.6 2490.01,1597.35 2492.48,1601.8 2494.95,1605.98 2497.42,1609.9 2499.9,1613.58 2502.37,1617.04 2504.84,1620.28 2507.31,1623.33 2509.78,1626.19 2512.25,1628.88 2514.72,1631.41 2517.19,1633.78 2519.67,1636.01 2522.14,1638.11 2524.61,1640.08 2527.08,1641.93 2529.55,1643.67 2532.02,1645.3 2534.49,1646.84 2536.96,1648.28 2539.44,1649.64 2541.91,1650.92 2544.38,1652.12 2546.85,1653.25 2549.32,1654.31 2551.79,1655.31 2554.26,1656.24 2556.73,1657.12 2559.21,1657.95 2561.68,1658.72 2564.15,1659.44 2566.62,1660.12 2569.09,1660.76 2571.56,1661.35 2574.03,1661.9 2576.5,1662.42 2578.98,1662.9 2581.45,1663.34 2583.92,1663.76 2586.39,1664.14 2588.86,1664.5 2591.33,1664.83 2593.8,1665.13 2596.27,1665.41 2598.75,1665.66 2601.22,1665.89 2603.69,1666.1 2606.16,1666.29 2608.63,1666.46 2611.1,1666.61 2613.57,1666.74 2616.04,1666.86 2618.51,1666.95 2620.99,1667.03 2623.46,1667.09 2625.93,1667.14 2628.4,1667.17 2630.87,1667.19 2633.34,1667.18 2635.81,1667.17 2638.28,1667.13 2640.76,1667.08 "></polyline>
<polyline clip-path="url(#clip962)" style="stroke:#00a9ad; stroke-linecap:round; stroke-linejoin:round; stroke-width:8; stroke-opacity:1; fill:none" points="172.001,1666.86 174.473,1667.17 176.944,1667.45 179.415,1667.71 181.886,1667.94 184.357,1668.16 186.829,1668.34 189.3,1668.5 191.771,1668.63 194.242,1668.74 196.714,1668.81 199.185,1668.85 201.656,1668.85 204.127,1668.82 206.598,1668.75 209.07,1668.64 211.541,1668.48 214.012,1668.28 216.483,1668.02 218.955,1667.72 221.426,1667.35 223.897,1666.93 226.368,1666.44 228.84,1665.89 231.311,1665.26 233.782,1664.55 236.253,1663.77 238.724,1662.89 241.196,1661.93 243.667,1660.88 246.138,1659.72 248.609,1658.47 251.081,1657.11 253.552,1655.64 256.023,1654.07 258.494,1652.38 260.965,1650.59 263.437,1648.68 265.908,1646.67 268.379,1644.55 270.85,1642.32 273.322,1640 275.793,1637.59 278.264,1635.1 280.735,1632.53 283.206,1629.89 285.678,1627.2 288.149,1624.46 290.62,1621.69 293.091,1618.89 295.563,1616.09 298.034,1613.3 300.505,1610.53 302.976,1607.78 305.448,1605.09 307.919,1602.45 310.39,1599.88 312.861,1597.39 315.332,1594.99 317.804,1592.7 320.275,1590.51 322.746,1588.45 325.217,1586.51 327.689,1584.71 330.16,1583.04 332.631,1581.51 335.102,1580.12 337.573,1578.88 340.045,1577.78 342.516,1576.83 344.987,1576.02 347.458,1575.35 349.93,1574.82 352.401,1574.43 354.872,1574.17 357.343,1574.04 359.814,1574.03 362.286,1574.14 364.757,1574.36 367.228,1574.69 369.699,1575.12 372.171,1575.65 374.642,1576.28 377.113,1576.99 379.584,1577.77 382.056,1578.64 384.527,1579.57 386.998,1580.57 389.469,1581.62 391.94,1582.73 394.412,1583.89 396.883,1585.09 399.354,1586.33 401.825,1587.61 404.297,1588.92 406.768,1590.25 409.239,1591.61 411.71,1592.99 414.181,1594.39 416.653,1595.81 419.124,1597.23 421.595,1598.66 424.066,1600.1 426.538,1601.54 429.009,1602.98 431.48,1604.42 433.951,1605.86 436.422,1607.29 438.894,1608.72 441.365,1610.14 443.836,1611.55 446.307,1612.95 448.779,1614.34 451.25,1615.71 453.721,1617.07 456.192,1618.42 458.664,1619.75 461.135,1621.07 463.606,1622.37 466.077,1623.65 468.548,1624.91 471.02,1626.15 473.491,1627.38 475.962,1628.59 478.433,1629.78 480.905,1630.94 483.376,1632.09 485.847,1633.22 488.318,1634.33 490.789,1635.42 493.261,1636.48 495.732,1637.53 498.203,1638.55 500.674,1639.56 503.146,1640.54 505.617,1641.51 508.088,1642.45 510.559,1643.37 513.03,1644.28 515.502,1645.16 517.973,1646.02 520.444,1646.86 522.915,1647.68 525.387,1648.48 527.858,1649.26 530.329,1650.02 532.8,1650.76 535.272,1651.48 537.743,1652.17 540.214,1652.85 542.685,1653.51 545.156,1654.15 547.628,1654.76 550.099,1655.36 552.57,1655.93 555.041,1656.48 557.513,1657.02 559.984,1657.52 562.455,1658.01 564.926,1658.48 567.397,1658.92 569.869,1659.34 572.34,1659.73 574.811,1660.1 577.282,1660.45 579.754,1660.77 582.225,1661.06 584.696,1661.32 587.167,1661.56 589.638,1661.76 592.11,1661.92 594.581,1662.05 597.052,1662.15 599.523,1662.2 601.995,1662.2 604.466,1662.17 606.937,1662.08 609.408,1661.94 611.88,1661.74 614.351,1661.49 616.822,1661.17 619.293,1660.78 621.764,1660.33 624.236,1659.79 626.707,1659.17 629.178,1658.45 631.649,1657.63 634.121,1656.7 636.592,1655.64 639.063,1654.47 641.534,1653.16 644.005,1651.7 646.477,1650.11 648.948,1648.36 651.419,1646.45 653.89,1644.37 656.362,1642.12 658.833,1639.7 661.304,1637.09 663.775,1634.3 666.246,1631.31 668.718,1628.13 671.189,1624.77 673.66,1621.23 676.131,1617.53 678.603,1613.66 681.074,1609.65 683.545,1605.5 686.016,1601.23 688.488,1596.86 690.959,1592.41 693.43,1587.89 695.901,1583.34 698.372,1578.77 700.844,1574.22 703.315,1569.71 705.786,1565.27 708.257,1560.93 710.729,1556.71 713.2,1552.64 715.671,1548.71 718.142,1544.96 720.613,1541.4 723.085,1538.05 725.556,1534.92 728.027,1532.02 730.498,1529.35 732.97,1526.94 735.441,1524.77 737.912,1522.86 740.383,1521.2 742.854,1519.79 745.326,1518.62 747.797,1517.7 750.268,1517.02 752.739,1516.57 755.211,1516.34 757.682,1516.32 760.153,1516.5 762.624,1516.88 765.096,1517.45 767.567,1518.18 770.038,1519.09 772.509,1520.14 774.98,1521.35 777.452,1522.68 779.923,1524.14 782.394,1525.71 784.865,1527.39 787.337,1529.15 789.808,1531.01 792.279,1532.94 794.75,1534.93 797.221,1536.99 799.693,1539.1 802.164,1541.26 804.635,1543.46 807.106,1545.69 809.578,1547.94 812.049,1550.22 814.52,1552.52 816.991,1554.83 819.462,1557.14 821.934,1559.46 824.405,1561.78 826.876,1564.1 829.347,1566.41 831.819,1568.71 834.29,1571 836.761,1573.27 839.232,1575.52 841.704,1577.76 844.175,1579.97 846.646,1582.16 849.117,1584.33 851.588,1586.47 854.06,1588.59 856.531,1590.67 859.002,1592.73 861.473,1594.76 863.945,1596.76 866.416,1598.73 868.887,1600.67 871.358,1602.57 873.829,1604.44 876.301,1606.29 878.772,1608.1 881.243,1609.87 883.714,1611.62 886.186,1613.33 888.657,1615.01 891.128,1616.65 893.599,1618.27 896.07,1619.85 898.542,1621.4 901.013,1622.92 903.484,1624.41 905.955,1625.87 908.427,1627.3 910.898,1628.69 913.369,1630.06 915.84,1631.4 918.312,1632.7 920.783,1633.98 923.254,1635.23 925.725,1636.45 928.196,1637.64 930.668,1638.81 933.139,1639.95 935.61,1641.06 938.081,1642.14 940.553,1643.2 943.024,1644.24 945.495,1645.24 947.966,1646.23 950.437,1647.18 952.909,1648.12 955.38,1649.03 957.851,1649.91 960.322,1650.78 962.794,1651.61 965.265,1652.43 967.736,1653.22 970.207,1653.99 972.678,1654.74 975.15,1655.47 977.621,1656.17 980.092,1656.85 982.563,1657.51 985.035,1658.14 987.506,1658.76 989.977,1659.35 992.448,1659.92 994.92,1660.47 997.391,1661 999.862,1661.5 1002.33,1661.98 1004.8,1662.43 1007.28,1662.86 1009.75,1663.26 1012.22,1663.64 1014.69,1663.99 1017.16,1664.31 1019.63,1664.59 1022.1,1664.85 1024.57,1665.07 1027.05,1665.26 1029.52,1665.41 1031.99,1665.52 1034.46,1665.59 1036.93,1665.61 1039.4,1665.58 1041.87,1665.49 1044.34,1665.34 1046.82,1665.12 1049.29,1664.82 1051.76,1664.44 1054.23,1663.98 1056.7,1663.41 1059.17,1662.73 1061.64,1661.94 1064.11,1661.02 1066.59,1659.95 1069.06,1658.71 1071.53,1657.31 1074,1655.71 1076.47,1653.91 1078.94,1651.9 1081.41,1649.65 1083.88,1647.15 1086.35,1644.38 1088.83,1641.34 1091.3,1637.99 1093.77,1634.34 1096.24,1630.37 1098.71,1626.09 1101.18,1621.48 1103.65,1616.56 1106.12,1611.34 1108.6,1605.83 1111.07,1600.04 1113.54,1594.01 1116.01,1587.76 1118.48,1581.31 1120.95,1574.71 1123.42,1568 1125.89,1561.21 1128.37,1554.38 1130.84,1547.58 1133.31,1540.85 1135.78,1534.23 1138.25,1527.77 1140.72,1521.52 1143.19,1515.5 1145.66,1509.75 1148.14,1504.3 1150.61,1499.19 1153.08,1494.44 1155.55,1490.06 1158.02,1486.08 1160.49,1482.5 1162.96,1479.33 1165.43,1476.56 1167.91,1474.19 1170.38,1472.22 1172.85,1470.63 1175.32,1469.42 1177.79,1468.58 1180.26,1468.1 1182.73,1467.95 1185.2,1468.12 1187.68,1468.6 1190.15,1469.35 1192.62,1470.36 1195.09,1471.61 1197.56,1473.09 1200.03,1474.77 1202.5,1476.64 1204.97,1478.68 1207.44,1480.88 1209.92,1483.22 1212.39,1485.69 1214.86,1488.27 1217.33,1490.95 1219.8,1493.72 1222.27,1496.56 1224.74,1499.47 1227.21,1502.42 1229.69,1505.42 1232.16,1508.46 1234.63,1511.51 1237.1,1514.59 1239.57,1517.67 1242.04,1520.77 1244.51,1523.86 1246.98,1526.94 1249.46,1530.02 1251.93,1533.08 1254.4,1536.12 1256.87,1539.13 1259.34,1542.12 1261.81,1545.09 1264.28,1548.02 1266.75,1550.91 1269.23,1553.78 1271.7,1556.6 1274.17,1559.39 1276.64,1562.14 1279.11,1564.84 1281.58,1567.51 1284.05,1570.13 1286.52,1572.71 1289,1575.24 1291.47,1577.73 1293.94,1580.18 1296.41,1582.58 1298.88,1584.93 1301.35,1587.24 1303.82,1589.51 1306.29,1591.73 1308.77,1593.9 1311.24,1596.03 1313.71,1598.12 1316.18,1600.17 1318.65,1602.17 1321.12,1604.13 1323.59,1606.04 1326.06,1607.92 1328.53,1609.75 1331.01,1611.54 1333.48,1613.29 1335.95,1615.01 1338.42,1616.68 1340.89,1618.31 1343.36,1619.91 1345.83,1621.46 1348.3,1622.98 1350.78,1624.47 1353.25,1625.91 1355.72,1627.32 1358.19,1628.7 1360.66,1630.04 1363.13,1631.35 1365.6,1632.62 1368.07,1633.86 1370.55,1635.07 1373.02,1636.25 1375.49,1637.39 1377.96,1638.51 1380.43,1639.59 1382.9,1640.65 1385.37,1641.67 1387.84,1642.66 1390.32,1643.63 1392.79,1644.57 1395.26,1645.47 1397.73,1646.35 1400.2,1647.21 1402.67,1648.03 1405.14,1648.83 1407.61,1649.6 1410.09,1650.34 1412.56,1651.06 1415.03,1651.75 1417.5,1652.41 1419.97,1653.05 1422.44,1653.66 1424.91,1654.24 1427.38,1654.8 1429.86,1655.33 1432.33,1655.83 1434.8,1656.3 1437.27,1656.74 1439.74,1657.16 1442.21,1657.54 1444.68,1657.9 1447.15,1658.22 1449.63,1658.51 1452.1,1658.77 1454.57,1659 1457.04,1659.18 1459.51,1659.34 1461.98,1659.45 1464.45,1659.52 1466.92,1659.56 1469.39,1659.54 1471.87,1659.49 1474.34,1659.38 1476.81,1659.22 1479.28,1659.01 1481.75,1658.74 1484.22,1658.41 1486.69,1658.01 1489.16,1657.56 1491.64,1657.03 1494.11,1656.42 1496.58,1655.74 1499.05,1654.98 1501.52,1654.13 1503.99,1653.19 1506.46,1652.16 1508.93,1651.03 1511.41,1649.8 1513.88,1648.47 1516.35,1647.03 1518.82,1645.49 1521.29,1643.85 1523.76,1642.09 1526.23,1640.23 1528.7,1638.26 1531.18,1636.18 1533.65,1633.99 1536.12,1631.69 1538.59,1629.3 1541.06,1626.82 1543.53,1624.25 1546,1621.61 1548.47,1618.9 1550.95,1616.13 1553.42,1613.31 1555.89,1610.45 1558.36,1607.57 1560.83,1604.67 1563.3,1601.77 1565.77,1598.88 1568.24,1596.03 1570.72,1593.2 1573.19,1590.43 1575.66,1587.71 1578.13,1585.08 1580.6,1582.53 1583.07,1580.07 1585.54,1577.72 1588.01,1575.49 1590.48,1573.39 1592.96,1571.41 1595.43,1569.57 1597.9,1567.86 1600.37,1566.3 1602.84,1564.89 1605.31,1563.63 1607.78,1562.51 1610.25,1561.54 1612.73,1560.73 1615.2,1560.05 1617.67,1559.52 1620.14,1559.13 1622.61,1558.88 1625.08,1558.75 1627.55,1558.76 1630.02,1558.88 1632.5,1559.13 1634.97,1559.49 1637.44,1559.95 1639.91,1560.52 1642.38,1561.19 1644.85,1561.95 1647.32,1562.79 1649.79,1563.71 1652.27,1564.71 1654.74,1565.77 1657.21,1566.9 1659.68,1568.08 1662.15,1569.31 1664.62,1570.6 1667.09,1571.93 1669.56,1573.29 1672.04,1574.69 1674.51,1576.13 1676.98,1577.58 1679.45,1579.07 1681.92,1580.57 1684.39,1582.08 1686.86,1583.61 1689.33,1585.16 1691.81,1586.7 1694.28,1588.26 1696.75,1589.81 1699.22,1591.37 1701.69,1592.92 1704.16,1594.47 1706.63,1596.02 1709.1,1597.55 1711.57,1599.08 1714.05,1600.6 1716.52,1602.1 1718.99,1603.59 1721.46,1605.07 1723.93,1606.54 1726.4,1607.98 1728.87,1609.41 1731.34,1610.82 1733.82,1612.22 1736.29,1613.59 1738.76,1614.94 1741.23,1616.27 1743.7,1617.58 1746.17,1618.87 1748.64,1620.14 1751.11,1621.39 1753.59,1622.61 1756.06,1623.81 1758.53,1624.99 1761,1626.14 1763.47,1627.27 1765.94,1628.38 1768.41,1629.46 1770.88,1630.52 1773.36,1631.55 1775.83,1632.56 1778.3,1633.55 1780.77,1634.51 1783.24,1635.45 1785.71,1636.36 1788.18,1637.24 1790.65,1638.11 1793.13,1638.94 1795.6,1639.75 1798.07,1640.53 1800.54,1641.29 1803.01,1642.02 1805.48,1642.72 1807.95,1643.39 1810.42,1644.04 1812.9,1644.66 1815.37,1645.24 1817.84,1645.8 1820.31,1646.33 1822.78,1646.83 1825.25,1647.3 1827.72,1647.73 1830.19,1648.13 1832.67,1648.49 1835.14,1648.82 1837.61,1649.11 1840.08,1649.35 1842.55,1649.55 1845.02,1649.71 1847.49,1649.82 1849.96,1649.87 1852.43,1649.88 1854.91,1649.82 1857.38,1649.71 1859.85,1649.53 1862.32,1649.29 1864.79,1648.98 1867.26,1648.59 1869.73,1648.12 1872.2,1647.57 1874.68,1646.93 1877.15,1646.19 1879.62,1645.35 1882.09,1644.4 1884.56,1643.34 1887.03,1642.15 1889.5,1640.83 1891.97,1639.38 1894.45,1637.79 1896.92,1636.06 1899.39,1634.17 1901.86,1632.14 1904.33,1629.94 1906.8,1627.59 1909.27,1625.07 1911.74,1622.38 1914.22,1619.52 1916.69,1616.49 1919.16,1613.29 1921.63,1609.94 1924.1,1606.43 1926.57,1602.79 1929.04,1599.02 1931.51,1595.12 1933.99,1591.13 1936.46,1587.05 1938.93,1582.89 1941.4,1578.68 1943.87,1574.44 1946.34,1570.19 1948.81,1565.94 1951.28,1561.72 1953.76,1557.56 1956.23,1553.49 1958.7,1549.53 1961.17,1545.7 1963.64,1542.01 1966.11,1538.48 1968.58,1535.14 1971.05,1531.98 1973.52,1529.03 1976,1526.3 1978.47,1523.79 1980.94,1521.52 1983.41,1519.48 1985.88,1517.69 1988.35,1516.14 1990.82,1514.84 1993.29,1513.78 1995.77,1512.96 1998.24,1512.37 2000.71,1512.01 2003.18,1511.87 2005.65,1511.95 2008.12,1512.22 2010.59,1512.69 2013.06,1513.35 2015.54,1514.18 2018.01,1515.17 2020.48,1516.33 2022.95,1517.62 2025.42,1519.06 2027.89,1520.62 2030.36,1522.29 2032.83,1524.06 2035.31,1525.93 2037.78,1527.89 2040.25,1529.92 2042.72,1532.03 2045.19,1534.19 2047.66,1536.41 2050.13,1538.67 2052.6,1540.97 2055.08,1543.3 2057.55,1545.66 2060.02,1548.04 2062.49,1550.44 2064.96,1552.85 2067.43,1555.26 2069.9,1557.68 2072.37,1560.09 2074.85,1562.5 2077.32,1564.9 2079.79,1567.29 2082.26,1569.67 2084.73,1572.02 2087.2,1574.36 2089.67,1576.68 2092.14,1578.97 2094.62,1581.24 2097.09,1583.48 2099.56,1585.69 2102.03,1587.88 2104.5,1590.03 2106.97,1592.16 2109.44,1594.25 2111.91,1596.31 2114.38,1598.34 2116.86,1600.33 2119.33,1602.3 2121.8,1604.23 2124.27,1606.12 2126.74,1607.98 2129.21,1609.81 2131.68,1611.6 2134.15,1613.36 2136.63,1615.08 2139.1,1616.77 2141.57,1618.43 2144.04,1620.06 2146.51,1621.65 2148.98,1623.21 2151.45,1624.73 2153.92,1626.23 2156.4,1627.69 2158.87,1629.12 2161.34,1630.52 2163.81,1631.89 2166.28,1633.23 2168.75,1634.54 2171.22,1635.82 2173.69,1637.08 2176.17,1638.3 2178.64,1639.5 2181.11,1640.66 2183.58,1641.81 2186.05,1642.92 2188.52,1644.01 2190.99,1645.07 2193.46,1646.11 2195.94,1647.12 2198.41,1648.11 2200.88,1649.07 2203.35,1650.01 2205.82,1650.93 2208.29,1651.82 2210.76,1652.69 2213.23,1653.54 2215.71,1654.37 2218.18,1655.17 2220.65,1655.96 2223.12,1656.72 2225.59,1657.46 2228.06,1658.19 2230.53,1658.89 2233,1659.57 2235.47,1660.24 2237.95,1660.88 2240.42,1661.5 2242.89,1662.11 2245.36,1662.7 2247.83,1663.26 2250.3,1663.81 2252.77,1664.34 2255.24,1664.85 2257.72,1665.34 2260.19,1665.82 2262.66,1666.27 2265.13,1666.71 2267.6,1667.12 2270.07,1667.52 2272.54,1667.89 2275.01,1668.24 2277.49,1668.57 2279.96,1668.87 2282.43,1669.15 2284.9,1669.4 2287.37,1669.62 2289.84,1669.82 2292.31,1669.99 2294.78,1670.12 2297.26,1670.22 2299.73,1670.28 2302.2,1670.29 2304.67,1670.27 2307.14,1670.19 2309.61,1670.05 2312.08,1669.86 2314.55,1669.59 2317.03,1669.25 2319.5,1668.82 2321.97,1668.3 2324.44,1667.67 2326.91,1666.93 2329.38,1666.06 2331.85,1665.04 2334.32,1663.87 2336.8,1662.52 2339.27,1660.98 2341.74,1659.23 2344.21,1657.26 2346.68,1655.05 2349.15,1652.58 2351.62,1649.82 2354.09,1646.77 2356.56,1643.4 2359.04,1639.71 2361.51,1635.67 2363.98,1631.3 2366.45,1626.59 2368.92,1621.54 2371.39,1616.16 2373.86,1610.47 2376.33,1604.49 2378.81,1598.25 2381.28,1591.77 2383.75,1585.08 2386.22,1578.23 2388.69,1571.26 2391.16,1564.21 2393.63,1557.14 2396.1,1550.11 2398.58,1543.16 2401.05,1536.34 2403.52,1529.7 2405.99,1523.28 2408.46,1517.11 2410.93,1511.24 2413.4,1505.71 2415.87,1500.54 2418.35,1495.76 2420.82,1491.38 2423.29,1487.42 2425.76,1483.88 2428.23,1480.76 2430.7,1478.07 2433.17,1475.8 2435.64,1473.94 2438.12,1472.48 2440.59,1471.42 2443.06,1470.73 2445.53,1470.4 2448,1470.41 2450.47,1470.74 2452.94,1471.36 2455.41,1472.26 2457.89,1473.42 2460.36,1474.83 2462.83,1476.45 2465.3,1478.27 2467.77,1480.28 2470.24,1482.46 2472.71,1484.79 2475.18,1487.25 2477.66,1489.84 2480.13,1492.53 2482.6,1495.31 2485.07,1498.17 2487.54,1501.09 2490.01,1504.07 2492.48,1507.09 2494.95,1510.15 2497.42,1513.23 2499.9,1516.34 2502.37,1519.46 2504.84,1522.58 2507.31,1525.7 2509.78,1528.82 2512.25,1531.92 2514.72,1535.01 2517.19,1538.08 2519.67,1541.13 2522.14,1544.15 2524.61,1547.14 2527.08,1550.1 2529.55,1553.02 2532.02,1555.91 2534.49,1558.76 2536.96,1561.57 2539.44,1564.34 2541.91,1567.07 2544.38,1569.76 2546.85,1572.4 2549.32,1575 2551.79,1577.55 2554.26,1580.06 2556.73,1582.52 2559.21,1584.94 2561.68,1587.31 2564.15,1589.64 2566.62,1591.92 2569.09,1594.16 2571.56,1596.35 2574.03,1598.5 2576.5,1600.6 2578.98,1602.66 2581.45,1604.68 2583.92,1606.66 2586.39,1608.59 2588.86,1610.48 2591.33,1612.33 2593.8,1614.14 2596.27,1615.91 2598.75,1617.64 2601.22,1619.34 2603.69,1620.99 2606.16,1622.61 2608.63,1624.19 2611.1,1625.74 2613.57,1627.25 2616.04,1628.72 2618.51,1630.17 2620.99,1631.57 2623.46,1632.95 2625.93,1634.29 2628.4,1635.61 2630.87,1636.89 2633.34,1638.14 2635.81,1639.36 2638.28,1640.56 2640.76,1641.72 "></polyline>
<path clip-path="url(#clip960)" d="M254.293 466.353 L698.205 466.353 L698.205 103.473 L254.293 103.473  Z" fill="#ffffff" fill-rule="evenodd" fill-opacity="1"></path>
<polyline clip-path="url(#clip960)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="254.293,466.353 698.205,466.353 698.205,103.473 254.293,103.473 254.293,466.353 "></polyline>
<polyline clip-path="url(#clip960)" style="stroke:#009af9; stroke-linecap:round; stroke-linejoin:round; stroke-width:8; stroke-opacity:1; fill:none" points="281.724,155.313 446.307,155.313 "></polyline>
<path clip-path="url(#clip960)" d="M488.923 150.649 Q488.206 150.232 487.349 150.047 Q486.516 149.839 485.497 149.839 Q481.886 149.839 479.942 152.2 Q478.02 154.538 478.02 158.936 L478.02 172.593 L473.738 172.593 L473.738 146.667 L478.02 146.667 L478.02 150.695 Q479.363 148.334 481.516 147.2 Q483.668 146.042 486.747 146.042 Q487.187 146.042 487.719 146.112 Q488.252 146.158 488.9 146.274 L488.923 150.649 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M505.173 159.561 Q500.011 159.561 498.02 160.741 Q496.03 161.922 496.03 164.769 Q496.03 167.038 497.511 168.38 Q499.016 169.7 501.585 169.7 Q505.127 169.7 507.256 167.2 Q509.409 164.677 509.409 160.51 L509.409 159.561 L505.173 159.561 M513.668 157.802 L513.668 172.593 L509.409 172.593 L509.409 168.658 Q507.951 171.019 505.775 172.153 Q503.599 173.264 500.451 173.264 Q496.469 173.264 494.108 171.042 Q491.77 168.797 491.77 165.047 Q491.77 160.672 494.687 158.45 Q497.627 156.228 503.437 156.228 L509.409 156.228 L509.409 155.811 Q509.409 152.871 507.465 151.274 Q505.543 149.653 502.048 149.653 Q499.826 149.653 497.719 150.186 Q495.613 150.718 493.668 151.783 L493.668 147.848 Q496.006 146.945 498.205 146.505 Q500.405 146.042 502.488 146.042 Q508.113 146.042 510.891 148.959 Q513.668 151.876 513.668 157.802 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M541.052 159.653 Q541.052 154.954 539.108 152.292 Q537.187 149.607 533.807 149.607 Q530.427 149.607 528.483 152.292 Q526.562 154.954 526.562 159.653 Q526.562 164.352 528.483 167.038 Q530.427 169.7 533.807 169.7 Q537.187 169.7 539.108 167.038 Q541.052 164.352 541.052 159.653 M526.562 150.603 Q527.904 148.288 529.941 147.177 Q532.002 146.042 534.849 146.042 Q539.571 146.042 542.511 149.792 Q545.474 153.542 545.474 159.653 Q545.474 165.765 542.511 169.515 Q539.571 173.264 534.849 173.264 Q532.002 173.264 529.941 172.153 Q527.904 171.019 526.562 168.704 L526.562 172.593 L522.279 172.593 L522.279 136.575 L526.562 136.575 L526.562 150.603 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M571.145 159.653 Q571.145 154.954 569.2 152.292 Q567.279 149.607 563.9 149.607 Q560.52 149.607 558.575 152.292 Q556.654 154.954 556.654 159.653 Q556.654 164.352 558.575 167.038 Q560.52 169.7 563.9 169.7 Q567.279 169.7 569.2 167.038 Q571.145 164.352 571.145 159.653 M556.654 150.603 Q557.997 148.288 560.034 147.177 Q562.094 146.042 564.941 146.042 Q569.663 146.042 572.603 149.792 Q575.566 153.542 575.566 159.653 Q575.566 165.765 572.603 169.515 Q569.663 173.264 564.941 173.264 Q562.094 173.264 560.034 172.153 Q557.997 171.019 556.654 168.704 L556.654 172.593 L552.372 172.593 L552.372 136.575 L556.654 136.575 L556.654 150.603 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M582.626 146.667 L586.886 146.667 L586.886 172.593 L582.626 172.593 L582.626 146.667 M582.626 136.575 L586.886 136.575 L586.886 141.968 L582.626 141.968 L582.626 136.575 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M600.01 139.306 L600.01 146.667 L608.784 146.667 L608.784 149.978 L600.01 149.978 L600.01 164.052 Q600.01 167.223 600.867 168.126 Q601.747 169.028 604.409 169.028 L608.784 169.028 L608.784 172.593 L604.409 172.593 Q599.478 172.593 597.603 170.764 Q595.728 168.913 595.728 164.052 L595.728 149.978 L592.603 149.978 L592.603 146.667 L595.728 146.667 L595.728 139.306 L600.01 139.306 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M630.913 147.431 L630.913 151.459 Q629.108 150.533 627.163 150.07 Q625.219 149.607 623.135 149.607 Q619.964 149.607 618.367 150.579 Q616.793 151.552 616.793 153.496 Q616.793 154.978 617.927 155.834 Q619.061 156.667 622.487 157.431 L623.946 157.755 Q628.483 158.728 630.381 160.51 Q632.302 162.269 632.302 165.44 Q632.302 169.052 629.432 171.158 Q626.584 173.264 621.584 173.264 Q619.501 173.264 617.233 172.848 Q614.987 172.454 612.487 171.644 L612.487 167.246 Q614.848 168.473 617.14 169.098 Q619.432 169.7 621.677 169.7 Q624.686 169.7 626.307 168.681 Q627.927 167.64 627.927 165.765 Q627.927 164.028 626.746 163.103 Q625.589 162.177 621.631 161.32 L620.149 160.973 Q616.191 160.14 614.432 158.427 Q612.672 156.69 612.672 153.681 Q612.672 150.024 615.265 148.033 Q617.858 146.042 622.626 146.042 Q624.987 146.042 627.07 146.39 Q629.154 146.737 630.913 147.431 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><polyline clip-path="url(#clip960)" style="stroke:#e26f46; stroke-linecap:round; stroke-linejoin:round; stroke-width:8; stroke-opacity:1; fill:none" points="281.724,207.153 446.307,207.153 "></polyline>
<path clip-path="url(#clip960)" d="M490.243 188.415 L490.243 191.957 L486.168 191.957 Q483.877 191.957 482.974 192.882 Q482.094 193.808 482.094 196.216 L482.094 198.507 L489.108 198.507 L489.108 201.818 L482.094 201.818 L482.094 224.433 L477.812 224.433 L477.812 201.818 L473.738 201.818 L473.738 198.507 L477.812 198.507 L477.812 196.702 Q477.812 192.373 479.826 190.406 Q481.84 188.415 486.215 188.415 L490.243 188.415 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M503.854 201.493 Q500.428 201.493 498.437 204.179 Q496.446 206.841 496.446 211.493 Q496.446 216.146 498.414 218.831 Q500.405 221.493 503.854 221.493 Q507.256 221.493 509.247 218.808 Q511.238 216.123 511.238 211.493 Q511.238 206.887 509.247 204.202 Q507.256 201.493 503.854 201.493 M503.854 197.882 Q509.409 197.882 512.58 201.493 Q515.752 205.105 515.752 211.493 Q515.752 217.859 512.58 221.493 Q509.409 225.104 503.854 225.104 Q498.275 225.104 495.104 221.493 Q491.955 217.859 491.955 211.493 Q491.955 205.105 495.104 201.493 Q498.275 197.882 503.854 197.882 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M542.904 198.507 L533.529 211.123 L543.39 224.433 L538.367 224.433 L530.821 214.248 L523.275 224.433 L518.252 224.433 L528.321 210.868 L519.108 198.507 L524.131 198.507 L531.006 207.743 L537.881 198.507 L542.904 198.507 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M570.126 210.405 L570.126 212.489 L550.543 212.489 Q550.821 216.887 553.182 219.202 Q555.566 221.493 559.802 221.493 Q562.256 221.493 564.548 220.892 Q566.862 220.29 569.131 219.086 L569.131 223.114 Q566.839 224.086 564.432 224.595 Q562.025 225.104 559.548 225.104 Q553.344 225.104 549.71 221.493 Q546.099 217.882 546.099 211.725 Q546.099 205.359 549.525 201.632 Q552.974 197.882 558.807 197.882 Q564.038 197.882 567.071 201.262 Q570.126 204.618 570.126 210.405 M565.867 209.155 Q565.821 205.66 563.9 203.577 Q562.001 201.493 558.853 201.493 Q555.288 201.493 553.136 203.507 Q551.006 205.521 550.682 209.179 L565.867 209.155 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M593.645 199.271 L593.645 203.299 Q591.839 202.373 589.895 201.91 Q587.95 201.447 585.867 201.447 Q582.696 201.447 581.099 202.419 Q579.524 203.392 579.524 205.336 Q579.524 206.818 580.659 207.674 Q581.793 208.507 585.219 209.271 L586.677 209.595 Q591.214 210.568 593.112 212.35 Q595.034 214.109 595.034 217.28 Q595.034 220.892 592.163 222.998 Q589.316 225.104 584.316 225.104 Q582.233 225.104 579.964 224.688 Q577.719 224.294 575.219 223.484 L575.219 219.086 Q577.58 220.313 579.872 220.938 Q582.163 221.54 584.409 221.54 Q587.418 221.54 589.038 220.521 Q590.659 219.48 590.659 217.605 Q590.659 215.868 589.478 214.943 Q588.321 214.017 584.362 213.16 L582.881 212.813 Q578.923 211.98 577.163 210.267 Q575.404 208.53 575.404 205.521 Q575.404 201.864 577.997 199.873 Q580.589 197.882 585.358 197.882 Q587.719 197.882 589.802 198.23 Q591.886 198.577 593.645 199.271 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><polyline clip-path="url(#clip960)" style="stroke:#3da44d; stroke-linecap:round; stroke-linejoin:round; stroke-width:8; stroke-opacity:1; fill:none" points="281.724,258.993 446.307,258.993 "></polyline>
<path clip-path="url(#clip960)" d="M495.451 260.625 L495.451 276.273 L491.192 276.273 L491.192 260.764 Q491.192 257.083 489.756 255.255 Q488.321 253.426 485.451 253.426 Q482.002 253.426 480.011 255.625 Q478.02 257.824 478.02 261.62 L478.02 276.273 L473.738 276.273 L473.738 240.255 L478.02 240.255 L478.02 254.375 Q479.548 252.037 481.608 250.88 Q483.692 249.722 486.4 249.722 Q490.868 249.722 493.159 252.5 Q495.451 255.255 495.451 260.625 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M515.729 263.241 Q510.566 263.241 508.576 264.421 Q506.585 265.602 506.585 268.449 Q506.585 270.718 508.067 272.06 Q509.571 273.38 512.141 273.38 Q515.682 273.38 517.812 270.88 Q519.965 268.357 519.965 264.19 L519.965 263.241 L515.729 263.241 M524.224 261.482 L524.224 276.273 L519.965 276.273 L519.965 272.338 Q518.506 274.699 516.33 275.833 Q514.154 276.944 511.006 276.944 Q507.025 276.944 504.664 274.722 Q502.326 272.477 502.326 268.727 Q502.326 264.352 505.242 262.13 Q508.182 259.908 513.992 259.908 L519.965 259.908 L519.965 259.491 Q519.965 256.551 518.02 254.954 Q516.099 253.333 512.604 253.333 Q510.381 253.333 508.275 253.866 Q506.168 254.398 504.224 255.463 L504.224 251.528 Q506.562 250.625 508.761 250.185 Q510.96 249.722 513.043 249.722 Q518.668 249.722 521.446 252.639 Q524.224 255.556 524.224 261.482 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M530.52 250.347 L534.779 250.347 L540.103 270.579 L545.404 250.347 L550.427 250.347 L555.751 270.579 L561.052 250.347 L565.312 250.347 L558.529 276.273 L553.506 276.273 L547.927 255.023 L542.326 276.273 L537.302 276.273 L530.52 250.347 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M571.608 240.255 L575.89 240.255 L575.89 261.528 L588.598 250.347 L594.038 250.347 L580.288 262.477 L594.617 276.273 L589.061 276.273 L575.89 263.611 L575.89 276.273 L571.608 276.273 L571.608 240.255 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M615.751 251.111 L615.751 255.139 Q613.946 254.213 612.001 253.75 Q610.057 253.287 607.973 253.287 Q604.802 253.287 603.205 254.259 Q601.631 255.232 601.631 257.176 Q601.631 258.658 602.765 259.514 Q603.899 260.347 607.325 261.111 L608.784 261.435 Q613.321 262.408 615.219 264.19 Q617.14 265.949 617.14 269.12 Q617.14 272.732 614.27 274.838 Q611.422 276.944 606.422 276.944 Q604.339 276.944 602.071 276.528 Q599.825 276.134 597.325 275.324 L597.325 270.926 Q599.686 272.153 601.978 272.778 Q604.27 273.38 606.515 273.38 Q609.524 273.38 611.145 272.361 Q612.765 271.32 612.765 269.445 Q612.765 267.708 611.584 266.783 Q610.427 265.857 606.469 265 L604.987 264.653 Q601.029 263.82 599.27 262.107 Q597.51 260.37 597.51 257.361 Q597.51 253.704 600.103 251.713 Q602.696 249.722 607.464 249.722 Q609.825 249.722 611.909 250.07 Q613.992 250.417 615.751 251.111 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><polyline clip-path="url(#clip960)" style="stroke:#c271d2; stroke-linecap:round; stroke-linejoin:round; stroke-width:8; stroke-opacity:1; fill:none" points="281.724,310.833 446.307,310.833 "></polyline>
<path clip-path="url(#clip960)" d="M473.738 292.095 L477.997 292.095 L477.997 328.113 L473.738 328.113 L473.738 292.095 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M486.909 302.187 L491.168 302.187 L491.168 328.113 L486.909 328.113 L486.909 302.187 M486.909 292.095 L491.168 292.095 L491.168 297.488 L486.909 297.488 L486.909 292.095 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M504.293 294.826 L504.293 302.187 L513.066 302.187 L513.066 305.498 L504.293 305.498 L504.293 319.572 Q504.293 322.743 505.15 323.646 Q506.029 324.548 508.692 324.548 L513.066 324.548 L513.066 328.113 L508.692 328.113 Q503.761 328.113 501.886 326.284 Q500.011 324.433 500.011 319.572 L500.011 305.498 L496.886 305.498 L496.886 302.187 L500.011 302.187 L500.011 294.826 L504.293 294.826 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M522.881 294.826 L522.881 302.187 L531.654 302.187 L531.654 305.498 L522.881 305.498 L522.881 319.572 Q522.881 322.743 523.738 323.646 Q524.617 324.548 527.279 324.548 L531.654 324.548 L531.654 328.113 L527.279 328.113 Q522.349 328.113 520.474 326.284 Q518.599 324.433 518.599 319.572 L518.599 305.498 L515.474 305.498 L515.474 302.187 L518.599 302.187 L518.599 294.826 L522.881 294.826 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M537.256 292.095 L541.515 292.095 L541.515 328.113 L537.256 328.113 L537.256 292.095 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M572.603 314.085 L572.603 316.169 L553.02 316.169 Q553.298 320.567 555.659 322.882 Q558.043 325.173 562.279 325.173 Q564.733 325.173 567.025 324.572 Q569.339 323.97 571.608 322.766 L571.608 326.794 Q569.316 327.766 566.909 328.275 Q564.501 328.784 562.025 328.784 Q555.821 328.784 552.187 325.173 Q548.576 321.562 548.576 315.405 Q548.576 309.039 552.001 305.312 Q555.451 301.562 561.284 301.562 Q566.515 301.562 569.548 304.942 Q572.603 308.298 572.603 314.085 M568.344 312.835 Q568.298 309.34 566.376 307.257 Q564.478 305.173 561.33 305.173 Q557.765 305.173 555.613 307.187 Q553.483 309.201 553.159 312.859 L568.344 312.835 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M607.788 292.095 L607.788 295.637 L603.714 295.637 Q601.422 295.637 600.52 296.562 Q599.64 297.488 599.64 299.896 L599.64 302.187 L606.654 302.187 L606.654 305.498 L599.64 305.498 L599.64 328.113 L595.358 328.113 L595.358 305.498 L591.284 305.498 L591.284 302.187 L595.358 302.187 L595.358 300.382 Q595.358 296.053 597.372 294.086 Q599.385 292.095 603.76 292.095 L607.788 292.095 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M611.353 302.187 L615.612 302.187 L615.612 328.113 L611.353 328.113 L611.353 302.187 M611.353 292.095 L615.612 292.095 L615.612 297.488 L611.353 297.488 L611.353 292.095 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M641.052 302.951 L641.052 306.979 Q639.246 306.053 637.302 305.59 Q635.357 305.127 633.274 305.127 Q630.103 305.127 628.506 306.099 Q626.932 307.072 626.932 309.016 Q626.932 310.498 628.066 311.354 Q629.2 312.187 632.626 312.951 L634.084 313.275 Q638.621 314.248 640.52 316.03 Q642.441 317.789 642.441 320.96 Q642.441 324.572 639.57 326.678 Q636.723 328.784 631.723 328.784 Q629.64 328.784 627.371 328.368 Q625.126 327.974 622.626 327.164 L622.626 322.766 Q624.987 323.993 627.279 324.618 Q629.57 325.22 631.816 325.22 Q634.825 325.22 636.445 324.201 Q638.066 323.16 638.066 321.285 Q638.066 319.548 636.885 318.623 Q635.728 317.697 631.77 316.84 L630.288 316.493 Q626.33 315.66 624.571 313.947 Q622.811 312.21 622.811 309.201 Q622.811 305.544 625.404 303.553 Q627.996 301.562 632.765 301.562 Q635.126 301.562 637.209 301.91 Q639.293 302.257 641.052 302.951 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M670.774 312.465 L670.774 328.113 L666.515 328.113 L666.515 312.604 Q666.515 308.923 665.08 307.095 Q663.644 305.266 660.774 305.266 Q657.325 305.266 655.334 307.465 Q653.344 309.664 653.344 313.46 L653.344 328.113 L649.061 328.113 L649.061 292.095 L653.344 292.095 L653.344 306.215 Q654.871 303.877 656.931 302.72 Q659.015 301.562 661.723 301.562 Q666.191 301.562 668.482 304.34 Q670.774 307.095 670.774 312.465 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><polyline clip-path="url(#clip960)" style="stroke:#ac8d18; stroke-linecap:round; stroke-linejoin:round; stroke-width:8; stroke-opacity:1; fill:none" points="281.724,362.673 446.307,362.673 "></polyline>
<path clip-path="url(#clip960)" d="M492.511 367.013 Q492.511 362.314 490.567 359.652 Q488.645 356.967 485.266 356.967 Q481.886 356.967 479.942 359.652 Q478.02 362.314 478.02 367.013 Q478.02 371.712 479.942 374.398 Q481.886 377.06 485.266 377.06 Q488.645 377.06 490.567 374.398 Q492.511 371.712 492.511 367.013 M478.02 357.963 Q479.363 355.648 481.4 354.537 Q483.46 353.402 486.307 353.402 Q491.03 353.402 493.969 357.152 Q496.932 360.902 496.932 367.013 Q496.932 373.125 493.969 376.875 Q491.03 380.624 486.307 380.624 Q483.46 380.624 481.4 379.513 Q479.363 378.379 478.02 376.064 L478.02 379.953 L473.738 379.953 L473.738 343.935 L478.02 343.935 L478.02 357.963 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M503.992 354.027 L508.252 354.027 L508.252 379.953 L503.992 379.953 L503.992 354.027 M503.992 343.935 L508.252 343.935 L508.252 349.328 L503.992 349.328 L503.992 343.935 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M534.224 366.689 Q534.224 362.06 532.302 359.513 Q530.404 356.967 526.955 356.967 Q523.529 356.967 521.608 359.513 Q519.71 362.06 519.71 366.689 Q519.71 371.296 521.608 373.842 Q523.529 376.388 526.955 376.388 Q530.404 376.388 532.302 373.842 Q534.224 371.296 534.224 366.689 M538.483 376.736 Q538.483 383.356 535.543 386.574 Q532.603 389.814 526.539 389.814 Q524.293 389.814 522.303 389.467 Q520.312 389.143 518.437 388.449 L518.437 384.305 Q520.312 385.324 522.141 385.81 Q523.969 386.296 525.867 386.296 Q530.057 386.296 532.14 384.097 Q534.224 381.921 534.224 377.5 L534.224 375.393 Q532.904 377.685 530.844 378.819 Q528.784 379.953 525.914 379.953 Q521.145 379.953 518.228 376.319 Q515.312 372.685 515.312 366.689 Q515.312 360.671 518.228 357.037 Q521.145 353.402 525.914 353.402 Q528.784 353.402 530.844 354.537 Q532.904 355.671 534.224 357.963 L534.224 354.027 L538.483 354.027 L538.483 376.736 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M575.45 343.935 L575.45 347.477 L571.376 347.477 Q569.085 347.477 568.182 348.402 Q567.302 349.328 567.302 351.736 L567.302 354.027 L574.316 354.027 L574.316 357.338 L567.302 357.338 L567.302 379.953 L563.02 379.953 L563.02 357.338 L558.946 357.338 L558.946 354.027 L563.02 354.027 L563.02 352.222 Q563.02 347.893 565.034 345.926 Q567.048 343.935 571.423 343.935 L575.45 343.935 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M579.015 354.027 L583.274 354.027 L583.274 379.953 L579.015 379.953 L579.015 354.027 M579.015 343.935 L583.274 343.935 L583.274 349.328 L579.015 349.328 L579.015 343.935 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M608.714 354.791 L608.714 358.819 Q606.909 357.893 604.964 357.43 Q603.02 356.967 600.936 356.967 Q597.765 356.967 596.168 357.939 Q594.594 358.912 594.594 360.856 Q594.594 362.338 595.728 363.194 Q596.862 364.027 600.288 364.791 L601.747 365.115 Q606.284 366.088 608.182 367.87 Q610.103 369.629 610.103 372.8 Q610.103 376.412 607.233 378.518 Q604.385 380.624 599.385 380.624 Q597.302 380.624 595.034 380.208 Q592.788 379.814 590.288 379.004 L590.288 374.606 Q592.649 375.833 594.941 376.458 Q597.233 377.06 599.478 377.06 Q602.487 377.06 604.108 376.041 Q605.728 375 605.728 373.125 Q605.728 371.388 604.547 370.463 Q603.39 369.537 599.432 368.68 L597.95 368.333 Q593.992 367.5 592.233 365.787 Q590.473 364.05 590.473 361.041 Q590.473 357.384 593.066 355.393 Q595.659 353.402 600.427 353.402 Q602.788 353.402 604.872 353.75 Q606.955 354.097 608.714 354.791 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M638.436 364.305 L638.436 379.953 L634.177 379.953 L634.177 364.444 Q634.177 360.763 632.742 358.935 Q631.307 357.106 628.436 357.106 Q624.987 357.106 622.996 359.305 Q621.006 361.504 621.006 365.3 L621.006 379.953 L616.723 379.953 L616.723 343.935 L621.006 343.935 L621.006 358.055 Q622.533 355.717 624.594 354.56 Q626.677 353.402 629.385 353.402 Q633.853 353.402 636.145 356.18 Q638.436 358.935 638.436 364.305 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><polyline clip-path="url(#clip960)" style="stroke:#00a9ad; stroke-linecap:round; stroke-linejoin:round; stroke-width:8; stroke-opacity:1; fill:none" points="281.724,414.513 446.307,414.513 "></polyline>
<path clip-path="url(#clip960)" d="M492.164 406.631 L492.164 410.659 Q490.358 409.733 488.414 409.27 Q486.469 408.807 484.386 408.807 Q481.215 408.807 479.618 409.779 Q478.044 410.752 478.044 412.696 Q478.044 414.178 479.178 415.034 Q480.312 415.867 483.738 416.631 L485.196 416.955 Q489.733 417.928 491.631 419.71 Q493.553 421.469 493.553 424.64 Q493.553 428.252 490.682 430.358 Q487.835 432.464 482.835 432.464 Q480.752 432.464 478.483 432.048 Q476.238 431.654 473.738 430.844 L473.738 426.446 Q476.099 427.673 478.391 428.298 Q480.682 428.9 482.928 428.9 Q485.937 428.9 487.557 427.881 Q489.178 426.84 489.178 424.965 Q489.178 423.228 487.997 422.303 Q486.84 421.377 482.881 420.52 L481.4 420.173 Q477.442 419.34 475.682 417.627 Q473.923 415.89 473.923 412.881 Q473.923 409.224 476.516 407.233 Q479.108 405.242 483.877 405.242 Q486.238 405.242 488.321 405.59 Q490.405 405.937 492.164 406.631 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M521.886 416.145 L521.886 431.793 L517.627 431.793 L517.627 416.284 Q517.627 412.603 516.191 410.775 Q514.756 408.946 511.886 408.946 Q508.437 408.946 506.446 411.145 Q504.455 413.344 504.455 417.14 L504.455 431.793 L500.173 431.793 L500.173 395.775 L504.455 395.775 L504.455 409.895 Q505.983 407.557 508.043 406.4 Q510.127 405.242 512.835 405.242 Q517.303 405.242 519.594 408.02 Q521.886 410.775 521.886 416.145 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M542.164 418.761 Q537.002 418.761 535.011 419.941 Q533.02 421.122 533.02 423.969 Q533.02 426.238 534.502 427.58 Q536.006 428.9 538.576 428.9 Q542.117 428.9 544.247 426.4 Q546.4 423.877 546.4 419.71 L546.4 418.761 L542.164 418.761 M550.659 417.002 L550.659 431.793 L546.4 431.793 L546.4 427.858 Q544.941 430.219 542.765 431.353 Q540.589 432.464 537.441 432.464 Q533.46 432.464 531.099 430.242 Q528.761 427.997 528.761 424.247 Q528.761 419.872 531.677 417.65 Q534.617 415.428 540.427 415.428 L546.4 415.428 L546.4 415.011 Q546.4 412.071 544.455 410.474 Q542.534 408.853 539.039 408.853 Q536.816 408.853 534.71 409.386 Q532.603 409.918 530.659 410.983 L530.659 407.048 Q532.997 406.145 535.196 405.705 Q537.395 405.242 539.478 405.242 Q545.103 405.242 547.881 408.159 Q550.659 411.076 550.659 417.002 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M574.455 409.849 Q573.737 409.432 572.881 409.247 Q572.048 409.039 571.029 409.039 Q567.418 409.039 565.474 411.4 Q563.552 413.738 563.552 418.136 L563.552 431.793 L559.27 431.793 L559.27 405.867 L563.552 405.867 L563.552 409.895 Q564.895 407.534 567.048 406.4 Q569.2 405.242 572.279 405.242 Q572.719 405.242 573.251 405.312 Q573.784 405.358 574.432 405.474 L574.455 409.849 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M578.761 395.775 L583.043 395.775 L583.043 417.048 L595.751 405.867 L601.191 405.867 L587.441 417.997 L601.77 431.793 L596.214 431.793 L583.043 419.131 L583.043 431.793 L578.761 431.793 L578.761 395.775 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip960)" d="M622.904 406.631 L622.904 410.659 Q621.098 409.733 619.154 409.27 Q617.209 408.807 615.126 408.807 Q611.955 408.807 610.358 409.779 Q608.784 410.752 608.784 412.696 Q608.784 414.178 609.918 415.034 Q611.052 415.867 614.478 416.631 L615.936 416.955 Q620.473 417.928 622.371 419.71 Q624.293 421.469 624.293 424.64 Q624.293 428.252 621.422 430.358 Q618.575 432.464 613.575 432.464 Q611.492 432.464 609.223 432.048 Q606.978 431.654 604.478 430.844 L604.478 426.446 Q606.839 427.673 609.131 428.298 Q611.422 428.9 613.668 428.9 Q616.677 428.9 618.297 427.881 Q619.918 426.84 619.918 424.965 Q619.918 423.228 618.737 422.303 Q617.58 421.377 613.621 420.52 L612.14 420.173 Q608.182 419.34 606.422 417.627 Q604.663 415.89 604.663 412.881 Q604.663 409.224 607.256 407.233 Q609.848 405.242 614.617 405.242 Q616.978 405.242 619.061 405.59 Q621.145 405.937 622.904 406.631 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path></svg>
</div>
</div>
<p>A successful example of hierarchical composition!</p>
<p>To really see the benefits of hierarchical composition, let’s take a look at how we could have achieved this composition without the layered approach.</p>
<div id="38" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb13-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define the (flattened) composition pattern</span></span>
<span id="cb13-2">flattened_pattern <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ocompose</span>(eco_pattern, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, land_pattern)</span>
<span id="cb13-3"></span>
<span id="cb13-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#Compose</span></span>
<span id="cb13-5">eco_sys2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">oapply</span>(flattened_pattern, [rabbit_growth, rabbitfox_predation, fox_decline, rabbithawk_predation, hawk_decline, air_sys, water_sys]);</span></code></pre></div>
</details>
</div>
<p>While this strategy produces the same composite system,<sup>3</sup> it lacks the clarity of the hierarchical approach which we can see from the flattened composition pattern:</p>
<div id="40" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/01/resource_sharers/index_files/figure-html/cell-21-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
</section>
<section id="what-next" class="level2">
<h2 class="anchored" data-anchor-id="what-next">What next?</h2>
<p>You can find more composite dynamical systems (including a multi-city SIR model and a cellular automata) in the documentation for <a href="https://algebraicjulia.github.io/AlgebraicDynamics.jl/dev/">AlgebraicDynamics.jl</a>. As this package develops, a large class of open projects is to implement black and grey boxing functors between operad algebras, such as: - A bridge from <a href="https://algebraicjulia.github.io/AlgebraicPetri.jl/stable/">AlgebraicPetri</a> to AlgebraicDynamics - Integrators (beyond Euler’s method), including ones that take advantage of hierarchical and compositional structure - An implementation of the claim “every machine is a resource sharer and every composition of machines is a composition of resource sharers”</p>



</section>


<div id="quarto-appendix" class="default"><section class="quarto-appendix-contents" id="quarto-bibliography"><h2 class="anchored quarto-appendix-heading">References</h2><div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="0">
<div id="ref-1704.02051" class="csl-entry">
Baez, John C., and Blake S. Pollard. 2017. <span>“A Compositional Framework for Reaction Networks.”</span> <a href="https://doi.org/10.1142/S0129055X17500283">https://doi.org/10.1142/S0129055X17500283</a>.
</div>
<div id="ref-1305.0297" class="csl-entry">
Spivak, David I. 2013. <span>“The Operad of Wiring Diagrams: Formalizing a Graphical Language for Databases, Recursion, and Plug-and-Play Circuits.”</span>
</div>
</div></section><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>

<ol>
<li id="fn1"><p>Undirected wiring diagrams form an operad where operadic composition is given by a pushout, shown in <span class="citation" data-cites="1305.0297">(Spivak 2013)</span>. <a href="https://www.algebraicjulia.org/assets/slides/mit-seminar-2020/#15">Here</a> you can learn more about the operadic composition of undirected wiring diagrams as well as the <code>@relation</code> macro for specifying undirected wiring diagrams.↩︎</p></li>
<li id="fn2"><p>This interpretation of composition of dynamical systems is mathemetized by the cospan algebra <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BDynam%7D"> defined in <span class="citation" data-cites="1704.02051">(Baez and Pollard 2017)</span>.↩︎</p></li>
<li id="fn3"><p>Functoriality of the cospan algebra <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BDynam%7D"> implies that the resource sharers <code>eco_sys</code> and <code>eco_sys2</code> have identical dynamics even though the dynamics are described by different expressions.↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>models</category>
  <category>attributed-c-sets</category>
  <category>dynamical systems</category>
  <guid>https://blog.algebraicjulia.org/post/2021/01/resource_sharers/</guid>
  <pubDate>Mon, 25 Jan 2021 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Composing open dynamical systems I: Directed composition</title>
  <dc:creator>Sophie Libkind and James Fairbanks</dc:creator>
  <link>https://blog.algebraicjulia.org/post/2021/01/machines/</link>
  <description><![CDATA[ 





<div class="hidden">
<p>$$ <!-- Number systems --> </p>
<!-- Categories -->
<!-- Graphs -->
<!-- Double categories -->
<!-- Acsets -->
<!-- Wiring diagrams -->
<!-- Dynamical systems -->
<p>$$</p>
</div>
<p>There is a discrepancy between how scientists conceive of their models and how they are implemented in a computer program. Informally, scientists represent their models as a composition of many primitive interactions. For example, an ecologist studying an ecosystem with one hundred species examines interactions between pairs of species and takes the full ecosystem to be a composite of these primitive systems. However, when the scientist sits down at a computer to encode the model, this modular structure is lost. The ecologist must simply write down a 100-variable ODE.</p>
<p>In <a href="https://github.com/AlgebraicJulia/AlgebraicDynamics.jl">AlgebraicDynamics.jl</a> (see also <a href="https://algebraicjulia.github.io/AlgebraicDynamics.jl/dev/">the documentation</a>), we introduce a modeling framework which allows the user to encode a complex dynamical system as the composite of primitive dynamical systems. Following the mathematics of operads and operad algebras, we explicitly represent the composition syntax itself as an algebraic object. While traditional modeling tools use a fixed syntax that is provided by the tool, the operadic approach provides a level-shift, where syntax is elevated to become flexible and programmable. Users can define new syntaxes adapted to their domains yet still interoperate between different syntaxes using the infrastructure built for operads.</p>
<p>So what is this process that builds complex systems out of primitive ones? First, start with rules for how to combine primitive systems. This <em>theory of composition</em> is an algebraic structure that specifies a composition syntax. Then, choose a pattern which follows the rules of the syntax — called a <em>composition pattern</em> — and primitive systems to compose. Lastly, the <code>oapply</code> method returns the composite system. The meat of this post is to give examples this general approach.</p>
<p>The category theoretic parallel is: - a <em>theory of composition</em> implements an operad, - a <em>composition pattern</em> implements a morphism (also called a term or an expression) in the operad, and - the <code>oapply</code> method implements an operad algebra.</p>
<p>We are interested in two distinct styles of composition (1) composition via directed communication and (2) composition via undirected communication.<sup>1</sup> We call dynamical systems that compose via directed communication <em>machines</em> and dynamical systems that compose via undirected communcation <em>resource sharers</em>. A zoo of composition theories is given below with directed theories in purple and undirected theories in blue.</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2021/01/machines/_svgs/9554aea724e7c8262f5dae60574f0897d60b454c.svg" class="img-fluid">
</div>
<p>In the following series of blog posts, we will explore the different species of this zoo and their implementations. In this post, we begin with directed theories. We choose to demonstrate the simpler theories to make the code readable and the examples constrained. These posts also showcase several categorical features of attributed <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets such as functorial data migration, <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set transformations, and (co)limits of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets.</p>
<section id="composition-of-machines" class="level2">
<h2 class="anchored" data-anchor-id="composition-of-machines">Composition of machines</h2>
<p>Machines are dynamical systems which compose via directed communication. Informally, a machine consists of five component parts: - inputs - states - outputs - dynamics for evolution - a readout function</p>
<p>We will assume throughout this blog post that the evolution rule is an ODE with exogenous variables (also called a driven or forced ODE). Exogenous variables drive the dynamics but their values are determined elsewhere. For example, in the differential equation <img src="https://latex.codecogs.com/png.latex?%5Cdot%20r(t)%20=%20%5Calpha%20r(t)%20-%20%5Cbeta%20r(t)h(t),"> <img src="https://latex.codecogs.com/png.latex?h"> is an exogenous variable which drives the system, while <img src="https://latex.codecogs.com/png.latex?%5Calpha"> and <img src="https://latex.codecogs.com/png.latex?%5Cbeta"> are (fixed) parameters. Following the informal defintion, we implement a machine as a struct below.</p>
<div id="2" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb1-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> Machine{T}</span>
<span id="cb1-2">    ninputs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span></span>
<span id="cb1-3">    nstates<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span></span>
<span id="cb1-4">    noutputs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span></span>
<span id="cb1-5">    dynamics<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Function</span></span>
<span id="cb1-6">    readout<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Function</span></span>
<span id="cb1-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb1-8"></span>
<span id="cb1-9"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nstates</span>(m<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Machine</span>)  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> m.nstates</span>
<span id="cb1-10"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ninputs</span>(m<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Machine</span>)  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> m.ninputs</span>
<span id="cb1-11"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">noutputs</span>(m<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Machine</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> m.noutputs</span></code></pre></div>
</details>
</div>
<p>Following the general approach, we will first define a composition syntax. Here is our first set of rules for composing machines: for each machine (locally called the receiver), each input of that machine is wired to the output of a machine (locally called the sender). The sender transmits its output to the receiver which uses the information as input to its evolution function. In the special case where the sender and receiver are the same machine, the composition induces a feedback loop.</p>
<p>This composition syntax is captured by the category of single-input port graphs, which is defined by the schema <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSch%7D(%5Cmathsf%7BSIPortGraph%7D)"> below. \</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2021/01/machines/_svgs/56f285758b653532591609b7f68ce9ef91685643.svg" class="img-fluid">
</div>
<p>A single-input port graph is a <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set over <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSch%7D(%5Cmathsf%7BSIPortGraph%7D)">, i.e.&nbsp;a functor <img src="https://latex.codecogs.com/png.latex?d:%20%5Cmathsf%7BSch%7D(%5Cmathsf%7BSIPortGraph%7D)%20%5Cto%20%5Cmathsf%7BSet%7D."> This composition pattern consists of 1. a set of boxes <img src="https://latex.codecogs.com/png.latex?d(%5Ctextrm%7BBox%7D)">. 2. Every box <img src="https://latex.codecogs.com/png.latex?b"> has a set of in-ports <img src="https://latex.codecogs.com/png.latex?d(%5Coperatorname%7Bbox_%7Bin%7D%7D)%5E%7B-1%7D(b)%20%5Csubseteq%20d(P_%7B%5Ctextrm%7Bin%7D%7D)"> and a set of out-ports <img src="https://latex.codecogs.com/png.latex?d(%5Coperatorname%7Bbox_%7Bout%7D%7D)%5E%7B-1%7D(b)%20%5Csubseteq%20d(P_%7B%5Ctextrm%7Bout%7D%7D)">. 3. Every in-port <img src="https://latex.codecogs.com/png.latex?p%20%5Cin%20d(P_%7B%5Ctextrm%7Bin%7D%7D)"> is fed information by a unique out-port <img src="https://latex.codecogs.com/png.latex?d(%5Coperatorname%7Bwire%7D)(p)%20%5Cin%20d(P_%7B%5Ctextrm%7Bout%7D%7D)">.</p>
<p>Implemented in Catlab, we have:</p>
<div id="4" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb2-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab.CategoricalAlgebra</span></span>
<span id="cb2-2"></span>
<span id="cb2-3"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@present</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SchSIPortGraph</span>(FreeSchema) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">begin</span>        </span>
<span id="cb2-4">    Box<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span></span>
<span id="cb2-5">    InPort<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span></span>
<span id="cb2-6">    OutPort<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Ob</span></span>
<span id="cb2-7">    </span>
<span id="cb2-8">    in_port_box<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(InPort, Box)</span>
<span id="cb2-9">    out_port_box<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(OutPort, Box)</span>
<span id="cb2-10">    wire<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Hom</span>(InPort, OutPort)</span>
<span id="cb2-11"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb2-12"></span>
<span id="cb2-13"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@abstract_acset_type</span> AbstractSIPortGraph</span>
<span id="cb2-14"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@acset_type</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SIPortGraph</span>(SchSIPortGraph,</span>
<span id="cb2-15">  index<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>in_port_box, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>out_port_box, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>wire]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;:</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;"> AbstractSIPortGraph</span></span></code></pre></div>
</details>
</div>
<p>A machine may fill a box<sup>2</sup> of the composition pattern if 1. the number of in-ports of the box equals the number of inputs to the machine, and 2. the number of out-ports of the box equals the number of outputs of the machine.</p>
<p>The following method checks if a machine fills a chosen box of a composition pattern.</p>
<div id="6" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb3-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fills</span>(m<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Machine</span>, d<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">AbstractSIPortGraph</span>, b<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>)</span>
<span id="cb3-2">    b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">≤</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nparts</span>(d, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>Box) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">||</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">error</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Trying to fill box </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>b<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">, when </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>d<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;"> has fewer than </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>b<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;"> boxes"</span>)</span>
<span id="cb3-3">    </span>
<span id="cb3-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ninputs</span>(m) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">incident</span>(d, b, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>in_port_box))) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">noutputs</span>(m) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">incident</span>(d, b, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>out_port_box)))</span>
<span id="cb3-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
</details>
</div>
<p>Now, given (1) a composition pattern and (2) a primitive machine filling each box, we can produce a new machine — the composite of the primitive machines — using the <code>oapply</code> method defined below. This composite machine has no inputs and no outputs. Its dynamics are induced by the driven dynamics of the primitive machines where the wires define how to set the inputs of each primitive machine.<sup>3</sup> We think of information of type <code>T</code> flowing along the wires.</p>
<div id="8" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb4-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span>  <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab.CategoricalAlgebra.FinSets</span></span>
<span id="cb4-2"></span>
<span id="cb4-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">oapply</span>(d<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">SIPortGraph</span>, xs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Vector{Machine{T}}</span>) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">where</span> T  </span>
<span id="cb4-4">    </span>
<span id="cb4-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> box <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parts</span>(d, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>Box)</span>
<span id="cb4-6">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fills</span>(xs[box], d, box) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">||</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">error</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>(xs[box])<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;"> does not fill box </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>box<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb4-7">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb4-8">    </span>
<span id="cb4-9">    States <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coproduct</span>((FinSet<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">∘</span>nstates).(xs))</span>
<span id="cb4-10">    Outputs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coproduct</span>((FinSet<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">∘</span>noutputs).(xs))</span>
<span id="cb4-11">    </span>
<span id="cb4-12">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">internal_readout</span>(u)</span>
<span id="cb4-13">        readouts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">zeros</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apex</span>(Outputs)))</span>
<span id="cb4-14">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> box <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parts</span>(d, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>Box)</span>
<span id="cb4-15">            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">view</span>(readouts, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">legs</span>(Outputs)[box](<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>)) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.=</span> xs[box].<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">readout</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">view</span>(u, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">legs</span>(States)[box](<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>)))</span>
<span id="cb4-16">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb4-17">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> readouts</span>
<span id="cb4-18">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb4-19">    </span>
<span id="cb4-20">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">v</span>(u,p,t)</span>
<span id="cb4-21">        dotu <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">zero</span>(u)</span>
<span id="cb4-22">        readouts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">internal_readout</span>(u)</span>
<span id="cb4-23">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> box <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parts</span>(d, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>Box)</span>
<span id="cb4-24">            inputs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">view</span>(readouts, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">subpart</span>(d, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">incident</span>(d, box, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>in_port_box), <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>wire))</span>
<span id="cb4-25">            vars <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">legs</span>(States)[box](<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>)</span>
<span id="cb4-26">            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">view</span>(dotu, vars) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.=</span> xs[box].<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dynamics</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">view</span>(u, vars), inputs, t)</span>
<span id="cb4-27">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb4-28">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> dotu</span>
<span id="cb4-29">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb4-30">    </span>
<span id="cb4-31">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Machine</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{T}</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apex</span>(States)), <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, v, x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb4-32"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
</details>
</div>
<p>We check that the machines have the correct signature for the box it fills when we construct the total system, not when we run it. This validation allows modeling software to reject malformed models and gives dynamical systems modelers the advantages associated with static type checking.</p>
<section id="example-the-lotka-volterra-predator-prey-model" class="level3">
<h3 class="anchored" data-anchor-id="example-the-lotka-volterra-predator-prey-model">Example: the Lotka-Volterra predator-prey model</h3>
<p>A standard Lotka-Volterra predator-prey model is the composition of two machines:</p>
<ol type="1">
<li><p>Evolution of a rabbit population — this machine takes one input which represents a population of predators, <img src="https://latex.codecogs.com/png.latex?h">, that hunt rabbits. This machine has one output which emits the rabbit population <img src="https://latex.codecogs.com/png.latex?r">. The dynamics of this machine is the driven ODE <img src="https://latex.codecogs.com/png.latex?%5Cdot%20r%20=%20%5Calpha%20r%20-%20%5Cbeta%20r%20h."></p></li>
<li><p>Evoluation of a fox population — this machine takes one input which represents a population of prey, <img src="https://latex.codecogs.com/png.latex?e">, that are eaten by foxes. This machine has one output which emits the fox population <img src="https://latex.codecogs.com/png.latex?f">. The dynamics of this machine is the driven ODE <img src="https://latex.codecogs.com/png.latex?%5Cdot%20f%20=%5Cgamma%20fe%20-%20%5Cdelta%20f%20."></p></li>
</ol>
<p>Since foxes hunt rabbit, these machines compose by setting the fox population to be the input for rabbit evolution. Likewise, we set the rabbit population to be the input for fox evolution. We depict this composition — both the composition pattern and the primitive machines — as</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/01/machines/lv_composition.svg" class="img-fluid quarto-figure quarto-figure-center figure-img"></p>
</figure>
</div>
<p>and implement this composition in Julia as</p>
<div id="10" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb5-1">α, β, γ, δ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.015</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.015</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span></span>
<span id="cb5-2"></span>
<span id="cb5-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dotr</span>(x, p, t) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [α<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>x[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> β<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>x[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>p[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]</span>
<span id="cb5-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dotf</span>(x, p, t) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [γ<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>x[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>p[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> δ<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>x[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]</span>
<span id="cb5-5"></span>
<span id="cb5-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define the primitive systems</span></span>
<span id="cb5-7">rabbit <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Machine</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{Float64}</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, dotr, x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> x)</span>
<span id="cb5-8">fox    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Machine</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{Float64}</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, dotf, x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> x)</span>
<span id="cb5-9"></span>
<span id="cb5-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define the composition pattern</span></span>
<span id="cb5-11">rabbitfox_pattern <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SIPortGraph</span>()</span>
<span id="cb5-12"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_parts!</span>(rabbitfox_pattern, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>Box,     <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb5-13"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_parts!</span>(rabbitfox_pattern, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>OutPort, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, out_port_box<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>])</span>
<span id="cb5-14"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_parts!</span>(rabbitfox_pattern, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>InPort,  <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, in_port_box<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>], wire<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])</span>
<span id="cb5-15"></span>
<span id="cb5-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Compose</span></span>
<span id="cb5-17">rabbitfox_sys <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">oapply</span>(rabbitfox_pattern, [rabbit, fox])</span></code></pre></div>
</details>
</div>
<p>The machine <code>rabbitfox_sys</code> now represents the complete Lotka-Volterra model. We can approximate a trajectory of the ecosystem using the solver in <a href="https://github.com/SciML/DifferentialEquations.jl">DifferentialEquations.jl</a> and plot the result.</p>
<div id="12" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<!--?xml version="1.0" encoding="utf-8"?-->
<svg xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" width="672" height="480" viewbox="0 0 2688 1920">
<defs>
  <clippath id="clip170">
    <rect x="0" y="0" width="2688" height="1920"></rect>
  </clippath>
</defs>
<path clip-path="url(#clip170)" d="M0 1920 L2688 1920 L2688 0 L0 0  Z" fill="#ffffff" fill-rule="evenodd" fill-opacity="1"></path>
<defs>
  <clippath id="clip171">
    <rect x="537" y="0" width="1883" height="1883"></rect>
  </clippath>
</defs>
<path clip-path="url(#clip170)" d="M382.132 1592.38 L2640.76 1592.38 L2640.76 127.792 L382.132 127.792  Z" fill="#ffffff" fill-rule="evenodd" fill-opacity="1"></path>
<defs>
  <clippath id="clip172">
    <rect x="382" y="127" width="2260" height="1466"></rect>
  </clippath>
</defs>
<polyline clip-path="url(#clip172)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="382.132,1592.38 382.132,127.792 "></polyline>
<polyline clip-path="url(#clip172)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="833.857,1592.38 833.857,127.792 "></polyline>
<polyline clip-path="url(#clip172)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="1285.58,1592.38 1285.58,127.792 "></polyline>
<polyline clip-path="url(#clip172)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="1737.31,1592.38 1737.31,127.792 "></polyline>
<polyline clip-path="url(#clip172)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="2189.03,1592.38 2189.03,127.792 "></polyline>
<polyline clip-path="url(#clip172)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="2640.76,1592.38 2640.76,127.792 "></polyline>
<polyline clip-path="url(#clip172)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="382.132,1551.75 2640.76,1551.75 "></polyline>
<polyline clip-path="url(#clip172)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="382.132,1200.67 2640.76,1200.67 "></polyline>
<polyline clip-path="url(#clip172)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="382.132,849.584 2640.76,849.584 "></polyline>
<polyline clip-path="url(#clip172)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="382.132,498.501 2640.76,498.501 "></polyline>
<polyline clip-path="url(#clip172)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="382.132,147.417 2640.76,147.417 "></polyline>
<polyline clip-path="url(#clip170)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="382.132,1592.38 2640.76,1592.38 "></polyline>
<polyline clip-path="url(#clip170)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="382.132,1592.38 382.132,1573.49 "></polyline>
<polyline clip-path="url(#clip170)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="833.857,1592.38 833.857,1573.49 "></polyline>
<polyline clip-path="url(#clip170)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="1285.58,1592.38 1285.58,1573.49 "></polyline>
<polyline clip-path="url(#clip170)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="1737.31,1592.38 1737.31,1573.49 "></polyline>
<polyline clip-path="url(#clip170)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="2189.03,1592.38 2189.03,1573.49 "></polyline>
<polyline clip-path="url(#clip170)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="2640.76,1592.38 2640.76,1573.49 "></polyline>
<path clip-path="url(#clip170)" d="M382.132 1625.61 Q378.521 1625.61 376.692 1629.17 Q374.887 1632.71 374.887 1639.84 Q374.887 1646.95 376.692 1650.51 Q378.521 1654.06 382.132 1654.06 Q385.766 1654.06 387.572 1650.51 Q389.4 1646.95 389.4 1639.84 Q389.4 1632.71 387.572 1629.17 Q385.766 1625.61 382.132 1625.61 M382.132 1621.9 Q387.942 1621.9 390.998 1626.51 Q394.076 1631.09 394.076 1639.84 Q394.076 1648.57 390.998 1653.18 Q387.942 1657.76 382.132 1657.76 Q376.322 1657.76 373.243 1653.18 Q370.188 1648.57 370.188 1639.84 Q370.188 1631.09 373.243 1626.51 Q376.322 1621.9 382.132 1621.9 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M812.63 1653.15 L828.949 1653.15 L828.949 1657.09 L807.005 1657.09 L807.005 1653.15 Q809.667 1650.4 814.25 1645.77 Q818.857 1641.12 820.037 1639.77 Q822.283 1637.25 823.162 1635.51 Q824.065 1633.76 824.065 1632.07 Q824.065 1629.31 822.121 1627.57 Q820.199 1625.84 817.098 1625.84 Q814.899 1625.84 812.445 1626.6 Q810.014 1627.37 807.237 1628.92 L807.237 1624.2 Q810.061 1623.06 812.514 1622.48 Q814.968 1621.9 817.005 1621.9 Q822.375 1621.9 825.57 1624.59 Q828.764 1627.27 828.764 1631.76 Q828.764 1633.89 827.954 1635.82 Q827.167 1637.71 825.061 1640.31 Q824.482 1640.98 821.38 1644.2 Q818.278 1647.39 812.63 1653.15 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M848.764 1625.61 Q845.153 1625.61 843.324 1629.17 Q841.519 1632.71 841.519 1639.84 Q841.519 1646.95 843.324 1650.51 Q845.153 1654.06 848.764 1654.06 Q852.398 1654.06 854.204 1650.51 Q856.033 1646.95 856.033 1639.84 Q856.033 1632.71 854.204 1629.17 Q852.398 1625.61 848.764 1625.61 M848.764 1621.9 Q854.574 1621.9 857.63 1626.51 Q860.709 1631.09 860.709 1639.84 Q860.709 1648.57 857.63 1653.18 Q854.574 1657.76 848.764 1657.76 Q842.954 1657.76 839.875 1653.18 Q836.82 1648.57 836.82 1639.84 Q836.82 1631.09 839.875 1626.51 Q842.954 1621.9 848.764 1621.9 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1273.75 1626.6 L1261.95 1645.05 L1273.75 1645.05 L1273.75 1626.6 M1272.53 1622.53 L1278.41 1622.53 L1278.41 1645.05 L1283.34 1645.05 L1283.34 1648.94 L1278.41 1648.94 L1278.41 1657.09 L1273.75 1657.09 L1273.75 1648.94 L1258.15 1648.94 L1258.15 1644.43 L1272.53 1622.53 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1301.07 1625.61 Q1297.46 1625.61 1295.63 1629.17 Q1293.82 1632.71 1293.82 1639.84 Q1293.82 1646.95 1295.63 1650.51 Q1297.46 1654.06 1301.07 1654.06 Q1304.7 1654.06 1306.51 1650.51 Q1308.34 1646.95 1308.34 1639.84 Q1308.34 1632.71 1306.51 1629.17 Q1304.7 1625.61 1301.07 1625.61 M1301.07 1621.9 Q1306.88 1621.9 1309.93 1626.51 Q1313.01 1631.09 1313.01 1639.84 Q1313.01 1648.57 1309.93 1653.18 Q1306.88 1657.76 1301.07 1657.76 Q1295.26 1657.76 1292.18 1653.18 Q1289.12 1648.57 1289.12 1639.84 Q1289.12 1631.09 1292.18 1626.51 Q1295.26 1621.9 1301.07 1621.9 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1722.71 1637.95 Q1719.56 1637.95 1717.71 1640.1 Q1715.88 1642.25 1715.88 1646 Q1715.88 1649.73 1717.71 1651.9 Q1719.56 1654.06 1722.71 1654.06 Q1725.86 1654.06 1727.69 1651.9 Q1729.54 1649.73 1729.54 1646 Q1729.54 1642.25 1727.69 1640.1 Q1725.86 1637.95 1722.71 1637.95 M1731.99 1623.29 L1731.99 1627.55 Q1730.23 1626.72 1728.43 1626.28 Q1726.65 1625.84 1724.89 1625.84 Q1720.26 1625.84 1717.8 1628.96 Q1715.37 1632.09 1715.03 1638.41 Q1716.39 1636.39 1718.45 1635.33 Q1720.51 1634.24 1722.99 1634.24 Q1728.2 1634.24 1731.21 1637.41 Q1734.24 1640.56 1734.24 1646 Q1734.24 1651.32 1731.09 1654.54 Q1727.94 1657.76 1722.71 1657.76 Q1716.72 1657.76 1713.54 1653.18 Q1710.37 1648.57 1710.37 1639.84 Q1710.37 1631.65 1714.26 1626.79 Q1718.15 1621.9 1724.7 1621.9 Q1726.46 1621.9 1728.24 1622.25 Q1730.05 1622.6 1731.99 1623.29 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1752.29 1625.61 Q1748.68 1625.61 1746.85 1629.17 Q1745.05 1632.71 1745.05 1639.84 Q1745.05 1646.95 1746.85 1650.51 Q1748.68 1654.06 1752.29 1654.06 Q1755.93 1654.06 1757.73 1650.51 Q1759.56 1646.95 1759.56 1639.84 Q1759.56 1632.71 1757.73 1629.17 Q1755.93 1625.61 1752.29 1625.61 M1752.29 1621.9 Q1758.1 1621.9 1761.16 1626.51 Q1764.24 1631.09 1764.24 1639.84 Q1764.24 1648.57 1761.16 1653.18 Q1758.1 1657.76 1752.29 1657.76 Q1746.48 1657.76 1743.41 1653.18 Q1740.35 1648.57 1740.35 1639.84 Q1740.35 1631.09 1743.41 1626.51 Q1746.48 1621.9 1752.29 1621.9 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M2173.9 1640.68 Q2170.57 1640.68 2168.65 1642.46 Q2166.75 1644.24 2166.75 1647.37 Q2166.75 1650.49 2168.65 1652.27 Q2170.57 1654.06 2173.9 1654.06 Q2177.24 1654.06 2179.16 1652.27 Q2181.08 1650.47 2181.08 1647.37 Q2181.08 1644.24 2179.16 1642.46 Q2177.26 1640.68 2173.9 1640.68 M2169.23 1638.69 Q2166.22 1637.95 2164.53 1635.89 Q2162.86 1633.82 2162.86 1630.86 Q2162.86 1626.72 2165.8 1624.31 Q2168.77 1621.9 2173.9 1621.9 Q2179.07 1621.9 2182.01 1624.31 Q2184.95 1626.72 2184.95 1630.86 Q2184.95 1633.82 2183.26 1635.89 Q2181.59 1637.95 2178.6 1638.69 Q2181.98 1639.47 2183.86 1641.76 Q2185.76 1644.06 2185.76 1647.37 Q2185.76 1652.39 2182.68 1655.07 Q2179.62 1657.76 2173.9 1657.76 Q2168.19 1657.76 2165.11 1655.07 Q2162.05 1652.39 2162.05 1647.37 Q2162.05 1644.06 2163.95 1641.76 Q2165.85 1639.47 2169.23 1638.69 M2167.52 1631.3 Q2167.52 1633.99 2169.18 1635.49 Q2170.87 1637 2173.9 1637 Q2176.91 1637 2178.6 1635.49 Q2180.32 1633.99 2180.32 1631.3 Q2180.32 1628.62 2178.6 1627.11 Q2176.91 1625.61 2173.9 1625.61 Q2170.87 1625.61 2169.18 1627.11 Q2167.52 1628.62 2167.52 1631.3 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M2204.07 1625.61 Q2200.45 1625.61 2198.63 1629.17 Q2196.82 1632.71 2196.82 1639.84 Q2196.82 1646.95 2198.63 1650.51 Q2200.45 1654.06 2204.07 1654.06 Q2207.7 1654.06 2209.51 1650.51 Q2211.33 1646.95 2211.33 1639.84 Q2211.33 1632.71 2209.51 1629.17 Q2207.7 1625.61 2204.07 1625.61 M2204.07 1621.9 Q2209.88 1621.9 2212.93 1626.51 Q2216.01 1631.09 2216.01 1639.84 Q2216.01 1648.57 2212.93 1653.18 Q2209.88 1657.76 2204.07 1657.76 Q2198.26 1657.76 2195.18 1653.18 Q2192.12 1648.57 2192.12 1639.84 Q2192.12 1631.09 2195.18 1626.51 Q2198.26 1621.9 2204.07 1621.9 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M2600.36 1653.15 L2608 1653.15 L2608 1626.79 L2599.69 1628.45 L2599.69 1624.2 L2607.96 1622.53 L2612.63 1622.53 L2612.63 1653.15 L2620.27 1653.15 L2620.27 1657.09 L2600.36 1657.09 L2600.36 1653.15 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M2639.71 1625.61 Q2636.1 1625.61 2634.27 1629.17 Q2632.47 1632.71 2632.47 1639.84 Q2632.47 1646.95 2634.27 1650.51 Q2636.1 1654.06 2639.71 1654.06 Q2643.35 1654.06 2645.15 1650.51 Q2646.98 1646.95 2646.98 1639.84 Q2646.98 1632.71 2645.15 1629.17 Q2643.35 1625.61 2639.71 1625.61 M2639.71 1621.9 Q2645.52 1621.9 2648.58 1626.51 Q2651.66 1631.09 2651.66 1639.84 Q2651.66 1648.57 2648.58 1653.18 Q2645.52 1657.76 2639.71 1657.76 Q2633.9 1657.76 2630.83 1653.18 Q2627.77 1648.57 2627.77 1639.84 Q2627.77 1631.09 2630.83 1626.51 Q2633.9 1621.9 2639.71 1621.9 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M2669.88 1625.61 Q2666.27 1625.61 2664.44 1629.17 Q2662.63 1632.71 2662.63 1639.84 Q2662.63 1646.95 2664.44 1650.51 Q2666.27 1654.06 2669.88 1654.06 Q2673.51 1654.06 2675.32 1650.51 Q2677.14 1646.95 2677.14 1639.84 Q2677.14 1632.71 2675.32 1629.17 Q2673.51 1625.61 2669.88 1625.61 M2669.88 1621.9 Q2675.69 1621.9 2678.74 1626.51 Q2681.82 1631.09 2681.82 1639.84 Q2681.82 1648.57 2678.74 1653.18 Q2675.69 1657.76 2669.88 1657.76 Q2664.07 1657.76 2660.99 1653.18 Q2657.93 1648.57 2657.93 1639.84 Q2657.93 1631.09 2660.99 1626.51 Q2664.07 1621.9 2669.88 1621.9 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1433.32 1694.05 L1473.52 1694.05 L1473.52 1699.46 L1456.65 1699.46 L1456.65 1741.57 L1450.19 1741.57 L1450.19 1699.46 L1433.32 1699.46 L1433.32 1694.05 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1477.47 1705.92 L1483.32 1705.92 L1483.32 1741.57 L1477.47 1741.57 L1477.47 1705.92 M1477.47 1692.04 L1483.32 1692.04 L1483.32 1699.46 L1477.47 1699.46 L1477.47 1692.04 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1523.33 1712.76 Q1525.53 1708.82 1528.58 1706.94 Q1531.64 1705.06 1535.78 1705.06 Q1541.35 1705.06 1544.37 1708.98 Q1547.39 1712.86 1547.39 1720.05 L1547.39 1741.57 L1541.51 1741.57 L1541.51 1720.24 Q1541.51 1715.12 1539.69 1712.64 Q1537.88 1710.15 1534.15 1710.15 Q1529.6 1710.15 1526.96 1713.18 Q1524.32 1716.2 1524.32 1721.42 L1524.32 1741.57 L1518.43 1741.57 L1518.43 1720.24 Q1518.43 1715.09 1516.62 1712.64 Q1514.8 1710.15 1511.01 1710.15 Q1506.53 1710.15 1503.88 1713.21 Q1501.24 1716.23 1501.24 1721.42 L1501.24 1741.57 L1495.35 1741.57 L1495.35 1705.92 L1501.24 1705.92 L1501.24 1711.46 Q1503.25 1708.18 1506.05 1706.62 Q1508.85 1705.06 1512.7 1705.06 Q1516.58 1705.06 1519.29 1707.03 Q1522.03 1709.01 1523.33 1712.76 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1589.57 1722.28 L1589.57 1725.15 L1562.64 1725.15 Q1563.02 1731.19 1566.27 1734.38 Q1569.55 1737.53 1575.37 1737.53 Q1578.75 1737.53 1581.9 1736.7 Q1585.08 1735.87 1588.2 1734.22 L1588.2 1739.75 Q1585.05 1741.09 1581.74 1741.79 Q1578.43 1742.49 1575.02 1742.49 Q1566.49 1742.49 1561.49 1737.53 Q1556.53 1732.56 1556.53 1724.09 Q1556.53 1715.34 1561.24 1710.22 Q1565.98 1705.06 1574 1705.06 Q1581.2 1705.06 1585.37 1709.71 Q1589.57 1714.32 1589.57 1722.28 M1583.71 1720.56 Q1583.65 1715.76 1581.01 1712.89 Q1578.4 1710.03 1574.07 1710.03 Q1569.17 1710.03 1566.2 1712.8 Q1563.28 1715.56 1562.83 1720.59 L1583.71 1720.56 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><polyline clip-path="url(#clip170)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="382.132,1592.38 382.132,127.792 "></polyline>
<polyline clip-path="url(#clip170)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="382.132,1551.75 401.03,1551.75 "></polyline>
<polyline clip-path="url(#clip170)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="382.132,1200.67 401.03,1200.67 "></polyline>
<polyline clip-path="url(#clip170)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="382.132,849.584 401.03,849.584 "></polyline>
<polyline clip-path="url(#clip170)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="382.132,498.501 401.03,498.501 "></polyline>
<polyline clip-path="url(#clip170)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="382.132,147.417 401.03,147.417 "></polyline>
<path clip-path="url(#clip170)" d="M329.868 1537.55 Q326.257 1537.55 324.428 1541.11 Q322.622 1544.66 322.622 1551.79 Q322.622 1558.89 324.428 1562.46 Q326.257 1566 329.868 1566 Q333.502 1566 335.307 1562.46 Q337.136 1558.89 337.136 1551.79 Q337.136 1544.66 335.307 1541.11 Q333.502 1537.55 329.868 1537.55 M329.868 1533.85 Q335.678 1533.85 338.733 1538.45 Q341.812 1543.04 341.812 1551.79 Q341.812 1560.51 338.733 1565.12 Q335.678 1569.7 329.868 1569.7 Q324.057 1569.7 320.979 1565.12 Q317.923 1560.51 317.923 1551.79 Q317.923 1543.04 320.979 1538.45 Q324.057 1533.85 329.868 1533.85 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M289.752 1183.39 L308.108 1183.39 L308.108 1187.32 L294.034 1187.32 L294.034 1195.79 Q295.053 1195.45 296.072 1195.29 Q297.09 1195.1 298.109 1195.1 Q303.896 1195.1 307.275 1198.27 Q310.655 1201.44 310.655 1206.86 Q310.655 1212.44 307.183 1215.54 Q303.71 1218.62 297.391 1218.62 Q295.215 1218.62 292.947 1218.25 Q290.701 1217.88 288.294 1217.14 L288.294 1212.44 Q290.377 1213.57 292.599 1214.13 Q294.822 1214.68 297.298 1214.68 Q301.303 1214.68 303.641 1212.58 Q305.979 1210.47 305.979 1206.86 Q305.979 1203.25 303.641 1201.14 Q301.303 1199.04 297.298 1199.04 Q295.423 1199.04 293.548 1199.45 Q291.697 1199.87 289.752 1200.75 L289.752 1183.39 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M329.868 1186.47 Q326.257 1186.47 324.428 1190.03 Q322.622 1193.57 322.622 1200.7 Q322.622 1207.81 324.428 1211.37 Q326.257 1214.92 329.868 1214.92 Q333.502 1214.92 335.307 1211.37 Q337.136 1207.81 337.136 1200.7 Q337.136 1193.57 335.307 1190.03 Q333.502 1186.47 329.868 1186.47 M329.868 1182.76 Q335.678 1182.76 338.733 1187.37 Q341.812 1191.95 341.812 1200.7 Q341.812 1209.43 338.733 1214.04 Q335.678 1218.62 329.868 1218.62 Q324.057 1218.62 320.979 1214.04 Q317.923 1209.43 317.923 1200.7 Q317.923 1191.95 320.979 1187.37 Q324.057 1182.76 329.868 1182.76 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M260.354 862.929 L267.993 862.929 L267.993 836.563 L259.683 838.23 L259.683 833.971 L267.947 832.304 L272.623 832.304 L272.623 862.929 L280.261 862.929 L280.261 866.864 L260.354 866.864 L260.354 862.929 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M299.706 835.383 Q296.095 835.383 294.266 838.948 Q292.46 842.489 292.46 849.619 Q292.46 856.725 294.266 860.29 Q296.095 863.832 299.706 863.832 Q303.34 863.832 305.146 860.29 Q306.974 856.725 306.974 849.619 Q306.974 842.489 305.146 838.948 Q303.34 835.383 299.706 835.383 M299.706 831.679 Q305.516 831.679 308.571 836.286 Q311.65 840.869 311.65 849.619 Q311.65 858.346 308.571 862.952 Q305.516 867.535 299.706 867.535 Q293.896 867.535 290.817 862.952 Q287.761 858.346 287.761 849.619 Q287.761 840.869 290.817 836.286 Q293.896 831.679 299.706 831.679 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M329.868 835.383 Q326.257 835.383 324.428 838.948 Q322.622 842.489 322.622 849.619 Q322.622 856.725 324.428 860.29 Q326.257 863.832 329.868 863.832 Q333.502 863.832 335.307 860.29 Q337.136 856.725 337.136 849.619 Q337.136 842.489 335.307 838.948 Q333.502 835.383 329.868 835.383 M329.868 831.679 Q335.678 831.679 338.733 836.286 Q341.812 840.869 341.812 849.619 Q341.812 858.346 338.733 862.952 Q335.678 867.535 329.868 867.535 Q324.057 867.535 320.979 862.952 Q317.923 858.346 317.923 849.619 Q317.923 840.869 320.979 836.286 Q324.057 831.679 329.868 831.679 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M260.354 511.845 L267.993 511.845 L267.993 485.48 L259.683 487.146 L259.683 482.887 L267.947 481.221 L272.623 481.221 L272.623 511.845 L280.261 511.845 L280.261 515.781 L260.354 515.781 L260.354 511.845 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M289.752 481.221 L308.108 481.221 L308.108 485.156 L294.034 485.156 L294.034 493.628 Q295.053 493.281 296.072 493.119 Q297.09 492.933 298.109 492.933 Q303.896 492.933 307.275 496.105 Q310.655 499.276 310.655 504.693 Q310.655 510.271 307.183 513.373 Q303.71 516.452 297.391 516.452 Q295.215 516.452 292.947 516.081 Q290.701 515.711 288.294 514.97 L288.294 510.271 Q290.377 511.406 292.599 511.961 Q294.822 512.517 297.298 512.517 Q301.303 512.517 303.641 510.41 Q305.979 508.304 305.979 504.693 Q305.979 501.082 303.641 498.975 Q301.303 496.869 297.298 496.869 Q295.423 496.869 293.548 497.285 Q291.697 497.702 289.752 498.582 L289.752 481.221 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M329.868 484.299 Q326.257 484.299 324.428 487.864 Q322.622 491.406 322.622 498.535 Q322.622 505.642 324.428 509.207 Q326.257 512.748 329.868 512.748 Q333.502 512.748 335.307 509.207 Q337.136 505.642 337.136 498.535 Q337.136 491.406 335.307 487.864 Q333.502 484.299 329.868 484.299 M329.868 480.596 Q335.678 480.596 338.733 485.202 Q341.812 489.785 341.812 498.535 Q341.812 507.262 338.733 511.869 Q335.678 516.452 329.868 516.452 Q324.057 516.452 320.979 511.869 Q317.923 507.262 317.923 498.535 Q317.923 489.785 320.979 485.202 Q324.057 480.596 329.868 480.596 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M263.572 160.762 L279.891 160.762 L279.891 164.697 L257.947 164.697 L257.947 160.762 Q260.609 158.007 265.192 153.378 Q269.799 148.725 270.979 147.382 Q273.224 144.859 274.104 143.123 Q275.007 141.364 275.007 139.674 Q275.007 136.919 273.062 135.183 Q271.141 133.447 268.039 133.447 Q265.84 133.447 263.387 134.211 Q260.956 134.975 258.178 136.526 L258.178 131.804 Q261.002 130.669 263.456 130.091 Q265.91 129.512 267.947 129.512 Q273.317 129.512 276.511 132.197 Q279.706 134.882 279.706 139.373 Q279.706 141.503 278.896 143.424 Q278.109 145.322 276.002 147.915 Q275.423 148.586 272.322 151.804 Q269.22 154.998 263.572 160.762 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M299.706 133.216 Q296.095 133.216 294.266 136.781 Q292.46 140.322 292.46 147.452 Q292.46 154.558 294.266 158.123 Q296.095 161.665 299.706 161.665 Q303.34 161.665 305.146 158.123 Q306.974 154.558 306.974 147.452 Q306.974 140.322 305.146 136.781 Q303.34 133.216 299.706 133.216 M299.706 129.512 Q305.516 129.512 308.571 134.119 Q311.65 138.702 311.65 147.452 Q311.65 156.179 308.571 160.785 Q305.516 165.368 299.706 165.368 Q293.896 165.368 290.817 160.785 Q287.761 156.179 287.761 147.452 Q287.761 138.702 290.817 134.119 Q293.896 129.512 299.706 129.512 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M329.868 133.216 Q326.257 133.216 324.428 136.781 Q322.622 140.322 322.622 147.452 Q322.622 154.558 324.428 158.123 Q326.257 161.665 329.868 161.665 Q333.502 161.665 335.307 158.123 Q337.136 154.558 337.136 147.452 Q337.136 140.322 335.307 136.781 Q333.502 133.216 329.868 133.216 M329.868 129.512 Q335.678 129.512 338.733 134.119 Q341.812 138.702 341.812 147.452 Q341.812 156.179 338.733 160.785 Q335.678 165.368 329.868 165.368 Q324.057 165.368 320.979 160.785 Q317.923 156.179 317.923 147.452 Q317.923 138.702 320.979 134.119 Q324.057 129.512 329.868 129.512 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M161.134 1093.52 L178.99 1093.52 L178.99 1085.43 Q178.99 1080.95 176.667 1078.5 Q174.343 1076.05 170.046 1076.05 Q165.781 1076.05 163.458 1078.5 Q161.134 1080.95 161.134 1085.43 L161.134 1093.52 M155.851 1099.95 L155.851 1085.43 Q155.851 1077.45 159.479 1073.37 Q163.076 1069.27 170.046 1069.27 Q177.08 1069.27 180.677 1073.37 Q184.274 1077.45 184.274 1085.43 L184.274 1093.52 L203.371 1093.52 L203.371 1099.95 L155.851 1099.95 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M171.829 1049.4 Q171.829 1054.12 175.521 1056.85 Q179.181 1059.59 185.579 1059.59 Q191.976 1059.59 195.668 1056.88 Q199.329 1054.15 199.329 1049.4 Q199.329 1044.73 195.636 1041.99 Q191.944 1039.25 185.579 1039.25 Q179.245 1039.25 175.553 1041.99 Q171.829 1044.73 171.829 1049.4 M166.863 1049.4 Q166.863 1041.77 171.829 1037.41 Q176.794 1033.04 185.579 1033.04 Q194.331 1033.04 199.329 1037.41 Q204.294 1041.77 204.294 1049.4 Q204.294 1057.08 199.329 1061.44 Q194.331 1065.76 185.579 1065.76 Q176.794 1065.76 171.829 1061.44 Q166.863 1057.08 166.863 1049.4 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M198.024 1017.67 L216.93 1017.67 L216.93 1023.56 L167.723 1023.56 L167.723 1017.67 L173.134 1017.67 Q169.951 1015.83 168.423 1013.02 Q166.863 1010.19 166.863 1006.28 Q166.863 999.784 172.02 995.742 Q177.176 991.668 185.579 991.668 Q193.981 991.668 199.138 995.742 Q204.294 999.784 204.294 1006.28 Q204.294 1010.19 202.766 1013.02 Q201.206 1015.83 198.024 1017.67 M185.579 997.747 Q179.117 997.747 175.457 1000.42 Q171.765 1003.06 171.765 1007.71 Q171.765 1012.36 175.457 1015.03 Q179.117 1017.67 185.579 1017.67 Q192.04 1017.67 195.732 1015.03 Q199.392 1012.36 199.392 1007.71 Q199.392 1003.06 195.732 1000.42 Q192.04 997.747 185.579 997.747 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M189.303 982.565 L167.723 982.565 L167.723 976.708 L189.08 976.708 Q194.14 976.708 196.687 974.735 Q199.201 972.761 199.201 968.815 Q199.201 964.072 196.177 961.335 Q193.154 958.566 187.934 958.566 L167.723 958.566 L167.723 952.709 L203.371 952.709 L203.371 958.566 L197.896 958.566 Q201.143 960.698 202.734 963.531 Q204.294 966.332 204.294 970.056 Q204.294 976.199 200.474 979.382 Q196.655 982.565 189.303 982.565 M166.863 967.828 L166.863 967.828 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M153.846 940.646 L153.846 934.79 L203.371 934.79 L203.371 940.646 L153.846 940.646 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M185.451 906.335 Q185.451 913.433 187.075 916.17 Q188.698 918.908 192.613 918.908 Q195.732 918.908 197.578 916.871 Q199.392 914.802 199.392 911.269 Q199.392 906.399 195.955 903.471 Q192.485 900.511 186.756 900.511 L185.451 900.511 L185.451 906.335 M183.032 894.654 L203.371 894.654 L203.371 900.511 L197.96 900.511 Q201.206 902.516 202.766 905.508 Q204.294 908.5 204.294 912.828 Q204.294 918.303 201.238 921.549 Q198.151 924.764 192.995 924.764 Q186.979 924.764 183.923 920.754 Q180.868 916.711 180.868 908.722 L180.868 900.511 L180.295 900.511 Q176.253 900.511 174.057 903.184 Q171.829 905.826 171.829 910.632 Q171.829 913.688 172.561 916.584 Q173.293 919.48 174.757 922.154 L169.346 922.154 Q168.105 918.939 167.5 915.916 Q166.863 912.892 166.863 910.027 Q166.863 902.293 170.874 898.474 Q174.884 894.654 183.032 894.654 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M157.601 876.798 L167.723 876.798 L167.723 864.735 L172.274 864.735 L172.274 876.798 L191.626 876.798 Q195.987 876.798 197.228 875.621 Q198.469 874.411 198.469 870.751 L198.469 864.735 L203.371 864.735 L203.371 870.751 Q203.371 877.53 200.856 880.109 Q198.31 882.687 191.626 882.687 L172.274 882.687 L172.274 886.984 L167.723 886.984 L167.723 882.687 L157.601 882.687 L157.601 876.798 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M167.723 857.033 L167.723 851.176 L203.371 851.176 L203.371 857.033 L167.723 857.033 M153.846 857.033 L153.846 851.176 L161.262 851.176 L161.262 857.033 L153.846 857.033 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M171.829 825.109 Q171.829 829.819 175.521 832.557 Q179.181 835.294 185.579 835.294 Q191.976 835.294 195.668 832.589 Q199.329 829.851 199.329 825.109 Q199.329 820.43 195.636 817.693 Q191.944 814.956 185.579 814.956 Q179.245 814.956 175.553 817.693 Q171.829 820.43 171.829 825.109 M166.863 825.109 Q166.863 817.47 171.829 813.109 Q176.794 808.749 185.579 808.749 Q194.331 808.749 199.329 813.109 Q204.294 817.47 204.294 825.109 Q204.294 832.78 199.329 837.14 Q194.331 841.469 185.579 841.469 Q176.794 841.469 171.829 837.14 Q166.863 832.78 166.863 825.109 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M181.855 769.409 L203.371 769.409 L203.371 775.265 L182.046 775.265 Q176.985 775.265 174.47 777.239 Q171.956 779.212 171.956 783.159 Q171.956 787.901 174.98 790.639 Q178.003 793.376 183.223 793.376 L203.371 793.376 L203.371 799.264 L167.723 799.264 L167.723 793.376 L173.261 793.376 Q170.046 791.275 168.455 788.442 Q166.863 785.578 166.863 781.854 Q166.863 775.711 170.683 772.56 Q174.47 769.409 181.855 769.409 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M168.773 714.282 L174.311 714.282 Q173.038 716.765 172.402 719.438 Q171.765 722.112 171.765 724.976 Q171.765 729.337 173.102 731.533 Q174.439 733.697 177.112 733.697 Q179.149 733.697 180.327 732.138 Q181.473 730.578 182.523 725.867 L182.969 723.862 Q184.305 717.624 186.756 715.014 Q189.175 712.372 193.536 712.372 Q198.501 712.372 201.397 716.319 Q204.294 720.234 204.294 727.109 Q204.294 729.973 203.721 733.093 Q203.18 736.18 202.066 739.617 L196.018 739.617 Q197.705 736.371 198.565 733.22 Q199.392 730.069 199.392 726.981 Q199.392 722.844 197.992 720.616 Q196.559 718.388 193.981 718.388 Q191.594 718.388 190.321 720.011 Q189.048 721.602 187.87 727.045 L187.393 729.082 Q186.247 734.525 183.892 736.944 Q181.505 739.363 177.367 739.363 Q172.338 739.363 169.601 735.798 Q166.863 732.233 166.863 725.677 Q166.863 722.43 167.341 719.565 Q167.818 716.701 168.773 714.282 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M167.723 703.046 L167.723 697.19 L203.371 697.19 L203.371 703.046 L167.723 703.046 M153.846 703.046 L153.846 697.19 L161.262 697.19 L161.262 703.046 L153.846 703.046 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M167.723 687.482 L167.723 659.664 L173.07 659.664 L198.692 681.689 L198.692 659.664 L203.371 659.664 L203.371 688.278 L198.024 688.278 L172.402 666.253 L172.402 687.482 L167.723 687.482 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M184.083 620.229 L186.947 620.229 L186.947 647.156 Q192.995 646.774 196.177 643.527 Q199.329 640.249 199.329 634.424 Q199.329 631.05 198.501 627.899 Q197.673 624.716 196.018 621.597 L201.557 621.597 Q202.893 624.748 203.594 628.058 Q204.294 631.369 204.294 634.774 Q204.294 643.304 199.329 648.301 Q194.363 653.267 185.897 653.267 Q177.144 653.267 172.02 648.556 Q166.863 643.814 166.863 635.793 Q166.863 628.599 171.51 624.43 Q176.126 620.229 184.083 620.229 M182.364 626.085 Q177.558 626.149 174.693 628.79 Q171.829 631.4 171.829 635.729 Q171.829 640.631 174.598 643.591 Q177.367 646.519 182.396 646.965 L182.364 626.085 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M801.361 12.096 L809.544 12.096 L809.544 65.6895 L838.994 65.6895 L838.994 72.576 L801.361 72.576 L801.361 12.096 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M863.38 32.4315 Q857.385 32.4315 853.901 37.1306 Q850.417 41.7891 850.417 49.9314 Q850.417 58.0738 853.861 62.7728 Q857.344 67.4314 863.38 67.4314 Q869.335 67.4314 872.819 62.7323 Q876.303 58.0333 876.303 49.9314 Q876.303 41.8701 872.819 37.1711 Q869.335 32.4315 863.38 32.4315 M863.38 26.1121 Q873.102 26.1121 878.652 32.4315 Q884.202 38.7509 884.202 49.9314 Q884.202 61.0714 878.652 67.4314 Q873.102 73.7508 863.38 73.7508 Q853.618 73.7508 848.068 67.4314 Q842.559 61.0714 842.559 49.9314 Q842.559 38.7509 848.068 32.4315 Q853.618 26.1121 863.38 26.1121 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M903.93 14.324 L903.93 27.2059 L919.283 27.2059 L919.283 32.9987 L903.93 32.9987 L903.93 57.6282 Q903.93 63.1779 905.429 64.7578 Q906.968 66.3376 911.627 66.3376 L919.283 66.3376 L919.283 72.576 L911.627 72.576 Q902.998 72.576 899.717 69.3758 Q896.436 66.1351 896.436 57.6282 L896.436 32.9987 L890.967 32.9987 L890.967 27.2059 L896.436 27.2059 L896.436 14.324 L903.93 14.324 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M928.802 9.54393 L936.297 9.54393 L936.297 46.7717 L958.536 27.2059 L968.056 27.2059 L943.993 48.4326 L969.068 72.576 L959.346 72.576 L936.297 50.4176 L936.297 72.576 L928.802 72.576 L928.802 9.54393 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M996.29 49.7694 Q987.257 49.7694 983.773 51.8354 Q980.289 53.9013 980.289 58.8839 Q980.289 62.8538 982.882 65.2034 Q985.515 67.5124 990.012 67.5124 Q996.209 67.5124 999.936 63.1374 Q1003.7 58.7219 1003.7 51.4303 L1003.7 49.7694 L996.29 49.7694 M1011.16 46.6907 L1011.16 72.576 L1003.7 72.576 L1003.7 65.6895 Q1001.15 69.8214 997.344 71.8063 Q993.536 73.7508 988.027 73.7508 Q981.059 73.7508 976.927 69.8619 Q972.836 65.9325 972.836 59.3701 Q972.836 51.7138 977.94 47.825 Q983.085 43.9361 993.252 43.9361 L1003.7 43.9361 L1003.7 43.2069 Q1003.7 38.0623 1000.3 35.2672 Q996.939 32.4315 990.822 32.4315 Q986.933 32.4315 983.247 33.3632 Q979.56 34.295 976.157 36.1584 L976.157 29.2718 Q980.249 27.692 984.097 26.9223 Q987.946 26.1121 991.591 26.1121 Q1001.44 26.1121 1006.3 31.2163 Q1011.16 36.3204 1011.16 46.6907 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1022.74 46.5287 L1044.58 46.5287 L1044.58 53.1722 L1022.74 53.1722 L1022.74 46.5287 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1067.51 72.576 L1044.42 12.096 L1052.96 12.096 L1072.12 63.0159 L1091.32 12.096 L1099.83 12.096 L1076.78 72.576 L1067.51 72.576 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1119.48 32.4315 Q1113.48 32.4315 1110 37.1306 Q1106.52 41.7891 1106.52 49.9314 Q1106.52 58.0738 1109.96 62.7728 Q1113.44 67.4314 1119.48 67.4314 Q1125.43 67.4314 1128.92 62.7323 Q1132.4 58.0333 1132.4 49.9314 Q1132.4 41.8701 1128.92 37.1711 Q1125.43 32.4315 1119.48 32.4315 M1119.48 26.1121 Q1129.2 26.1121 1134.75 32.4315 Q1140.3 38.7509 1140.3 49.9314 Q1140.3 61.0714 1134.75 67.4314 Q1129.2 73.7508 1119.48 73.7508 Q1109.72 73.7508 1104.17 67.4314 Q1098.66 61.0714 1098.66 49.9314 Q1098.66 38.7509 1104.17 32.4315 Q1109.72 26.1121 1119.48 26.1121 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1152.66 9.54393 L1160.11 9.54393 L1160.11 72.576 L1152.66 72.576 L1152.66 9.54393 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1183.08 14.324 L1183.08 27.2059 L1198.43 27.2059 L1198.43 32.9987 L1183.08 32.9987 L1183.08 57.6282 Q1183.08 63.1779 1184.58 64.7578 Q1186.12 66.3376 1190.77 66.3376 L1198.43 66.3376 L1198.43 72.576 L1190.77 72.576 Q1182.15 72.576 1178.86 69.3758 Q1175.58 66.1351 1175.58 57.6282 L1175.58 32.9987 L1170.11 32.9987 L1170.11 27.2059 L1175.58 27.2059 L1175.58 14.324 L1183.08 14.324 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1247.04 48.0275 L1247.04 51.6733 L1212.77 51.6733 Q1213.26 59.3701 1217.39 63.421 Q1221.56 67.4314 1228.97 67.4314 Q1233.27 67.4314 1237.28 66.3781 Q1241.33 65.3249 1245.3 63.2184 L1245.3 70.267 Q1241.29 71.9684 1237.08 72.8596 Q1232.86 73.7508 1228.53 73.7508 Q1217.67 73.7508 1211.31 67.4314 Q1204.99 61.1119 1204.99 50.3365 Q1204.99 39.1965 1210.99 32.6746 Q1217.02 26.1121 1227.23 26.1121 Q1236.39 26.1121 1241.69 32.0264 Q1247.04 37.9003 1247.04 48.0275 M1239.59 45.84 Q1239.51 39.7232 1236.14 36.0774 Q1232.82 32.4315 1227.31 32.4315 Q1221.08 32.4315 1217.31 35.9558 Q1213.58 39.4801 1213.01 45.8805 L1239.59 45.84 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1285.57 34.1734 Q1284.31 33.4443 1282.81 33.1202 Q1281.35 32.7556 1279.57 32.7556 Q1273.25 32.7556 1269.85 36.8875 Q1266.49 40.9789 1266.49 48.6757 L1266.49 72.576 L1258.99 72.576 L1258.99 27.2059 L1266.49 27.2059 L1266.49 34.2544 Q1268.84 30.1225 1272.6 28.1376 Q1276.37 26.1121 1281.76 26.1121 Q1282.53 26.1121 1283.46 26.2337 Q1284.39 26.3147 1285.53 26.5172 L1285.57 34.1734 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1318.22 34.1734 Q1316.96 33.4443 1315.46 33.1202 Q1314 32.7556 1312.22 32.7556 Q1305.9 32.7556 1302.5 36.8875 Q1299.14 40.9789 1299.14 48.6757 L1299.14 72.576 L1291.64 72.576 L1291.64 27.2059 L1299.14 27.2059 L1299.14 34.2544 Q1301.49 30.1225 1305.25 28.1376 Q1309.02 26.1121 1314.41 26.1121 Q1315.18 26.1121 1316.11 26.2337 Q1317.04 26.3147 1318.18 26.5172 L1318.22 34.1734 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1346.65 49.7694 Q1337.62 49.7694 1334.14 51.8354 Q1330.65 53.9013 1330.65 58.8839 Q1330.65 62.8538 1333.24 65.2034 Q1335.88 67.5124 1340.37 67.5124 Q1346.57 67.5124 1350.3 63.1374 Q1354.07 58.7219 1354.07 51.4303 L1354.07 49.7694 L1346.65 49.7694 M1361.52 46.6907 L1361.52 72.576 L1354.07 72.576 L1354.07 65.6895 Q1351.51 69.8214 1347.71 71.8063 Q1343.9 73.7508 1338.39 73.7508 Q1331.42 73.7508 1327.29 69.8619 Q1323.2 65.9325 1323.2 59.3701 Q1323.2 51.7138 1328.3 47.825 Q1333.45 43.9361 1343.61 43.9361 L1354.07 43.9361 L1354.07 43.2069 Q1354.07 38.0623 1350.66 35.2672 Q1347.3 32.4315 1341.18 32.4315 Q1337.3 32.4315 1333.61 33.3632 Q1329.92 34.295 1326.52 36.1584 L1326.52 29.2718 Q1330.61 27.692 1334.46 26.9223 Q1338.31 26.1121 1341.95 26.1121 Q1351.8 26.1121 1356.66 31.2163 Q1361.52 36.3204 1361.52 46.6907 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1411.75 18.8205 L1411.75 41.5461 L1422.04 41.5461 Q1427.75 41.5461 1430.87 38.5889 Q1433.99 35.6318 1433.99 30.163 Q1433.99 24.7348 1430.87 21.7777 Q1427.75 18.8205 1422.04 18.8205 L1411.75 18.8205 M1403.57 12.096 L1422.04 12.096 Q1432.21 12.096 1437.39 16.714 Q1442.62 21.2916 1442.62 30.163 Q1442.62 39.1155 1437.39 43.6931 Q1432.21 48.2706 1422.04 48.2706 L1411.75 48.2706 L1411.75 72.576 L1403.57 72.576 L1403.57 12.096 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1478.11 34.1734 Q1476.85 33.4443 1475.35 33.1202 Q1473.89 32.7556 1472.11 32.7556 Q1465.79 32.7556 1462.39 36.8875 Q1459.03 40.9789 1459.03 48.6757 L1459.03 72.576 L1451.53 72.576 L1451.53 27.2059 L1459.03 27.2059 L1459.03 34.2544 Q1461.37 30.1225 1465.14 28.1376 Q1468.91 26.1121 1474.3 26.1121 Q1475.07 26.1121 1476 26.2337 Q1476.93 26.3147 1478.06 26.5172 L1478.11 34.1734 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1522.91 48.0275 L1522.91 51.6733 L1488.64 51.6733 Q1489.12 59.3701 1493.26 63.421 Q1497.43 67.4314 1504.84 67.4314 Q1509.13 67.4314 1513.15 66.3781 Q1517.2 65.3249 1521.17 63.2184 L1521.17 70.267 Q1517.16 71.9684 1512.94 72.8596 Q1508.73 73.7508 1504.4 73.7508 Q1493.54 73.7508 1487.18 67.4314 Q1480.86 61.1119 1480.86 50.3365 Q1480.86 39.1965 1486.85 32.6746 Q1492.89 26.1121 1503.1 26.1121 Q1512.25 26.1121 1517.56 32.0264 Q1522.91 37.9003 1522.91 48.0275 M1515.45 45.84 Q1515.37 39.7232 1512.01 36.0774 Q1508.69 32.4315 1503.18 32.4315 Q1496.94 32.4315 1493.17 35.9558 Q1489.45 39.4801 1488.88 45.8805 L1515.45 45.84 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1565 34.0924 L1565 9.54393 L1572.45 9.54393 L1572.45 72.576 L1565 72.576 L1565 65.7705 Q1562.65 69.8214 1559.04 71.8063 Q1555.48 73.7508 1550.45 73.7508 Q1542.23 73.7508 1537.05 67.1883 Q1531.9 60.6258 1531.9 49.9314 Q1531.9 39.2371 1537.05 32.6746 Q1542.23 26.1121 1550.45 26.1121 Q1555.48 26.1121 1559.04 28.0971 Q1562.65 30.0415 1565 34.0924 M1539.6 49.9314 Q1539.6 58.1548 1542.96 62.8538 Q1546.36 67.5124 1552.28 67.5124 Q1558.19 67.5124 1561.59 62.8538 Q1565 58.1548 1565 49.9314 Q1565 41.7081 1561.59 37.0496 Q1558.19 32.3505 1552.28 32.3505 Q1546.36 32.3505 1542.96 37.0496 Q1539.6 41.7081 1539.6 49.9314 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1608.42 49.7694 Q1599.39 49.7694 1595.91 51.8354 Q1592.42 53.9013 1592.42 58.8839 Q1592.42 62.8538 1595.01 65.2034 Q1597.65 67.5124 1602.14 67.5124 Q1608.34 67.5124 1612.07 63.1374 Q1615.84 58.7219 1615.84 51.4303 L1615.84 49.7694 L1608.42 49.7694 M1623.29 46.6907 L1623.29 72.576 L1615.84 72.576 L1615.84 65.6895 Q1613.28 69.8214 1609.48 71.8063 Q1605.67 73.7508 1600.16 73.7508 Q1593.19 73.7508 1589.06 69.8619 Q1584.97 65.9325 1584.97 59.3701 Q1584.97 51.7138 1590.07 47.825 Q1595.22 43.9361 1605.38 43.9361 L1615.84 43.9361 L1615.84 43.2069 Q1615.84 38.0623 1612.43 35.2672 Q1609.07 32.4315 1602.95 32.4315 Q1599.07 32.4315 1595.38 33.3632 Q1591.69 34.295 1588.29 36.1584 L1588.29 29.2718 Q1592.38 27.692 1596.23 26.9223 Q1600.08 26.1121 1603.72 26.1121 Q1613.57 26.1121 1618.43 31.2163 Q1623.29 36.3204 1623.29 46.6907 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1646.01 14.324 L1646.01 27.2059 L1661.37 27.2059 L1661.37 32.9987 L1646.01 32.9987 L1646.01 57.6282 Q1646.01 63.1779 1647.51 64.7578 Q1649.05 66.3376 1653.71 66.3376 L1661.37 66.3376 L1661.37 72.576 L1653.71 72.576 Q1645.08 72.576 1641.8 69.3758 Q1638.52 66.1351 1638.52 57.6282 L1638.52 32.9987 L1633.05 32.9987 L1633.05 27.2059 L1638.52 27.2059 L1638.52 14.324 L1646.01 14.324 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1688.75 32.4315 Q1682.76 32.4315 1679.27 37.1306 Q1675.79 41.7891 1675.79 49.9314 Q1675.79 58.0738 1679.23 62.7728 Q1682.72 67.4314 1688.75 67.4314 Q1694.71 67.4314 1698.19 62.7323 Q1701.67 58.0333 1701.67 49.9314 Q1701.67 41.8701 1698.19 37.1711 Q1694.71 32.4315 1688.75 32.4315 M1688.75 26.1121 Q1698.47 26.1121 1704.02 32.4315 Q1709.57 38.7509 1709.57 49.9314 Q1709.57 61.0714 1704.02 67.4314 Q1698.47 73.7508 1688.75 73.7508 Q1678.99 73.7508 1673.44 67.4314 Q1667.93 61.0714 1667.93 49.9314 Q1667.93 38.7509 1673.44 32.4315 Q1678.99 26.1121 1688.75 26.1121 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1748.22 34.1734 Q1746.96 33.4443 1745.46 33.1202 Q1744.01 32.7556 1742.22 32.7556 Q1735.9 32.7556 1732.5 36.8875 Q1729.14 40.9789 1729.14 48.6757 L1729.14 72.576 L1721.65 72.576 L1721.65 27.2059 L1729.14 27.2059 L1729.14 34.2544 Q1731.49 30.1225 1735.26 28.1376 Q1739.02 26.1121 1744.41 26.1121 Q1745.18 26.1121 1746.11 26.2337 Q1747.04 26.3147 1748.18 26.5172 L1748.22 34.1734 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1746.96 46.5287 L1768.8 46.5287 L1768.8 53.1722 L1746.96 53.1722 L1746.96 46.5287 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1789.17 18.8205 L1789.17 41.5461 L1799.46 41.5461 Q1805.18 41.5461 1808.29 38.5889 Q1811.41 35.6318 1811.41 30.163 Q1811.41 24.7348 1808.29 21.7777 Q1805.18 18.8205 1799.46 18.8205 L1789.17 18.8205 M1780.99 12.096 L1799.46 12.096 Q1809.63 12.096 1814.82 16.714 Q1820.04 21.2916 1820.04 30.163 Q1820.04 39.1155 1814.82 43.6931 Q1809.63 48.2706 1799.46 48.2706 L1789.17 48.2706 L1789.17 72.576 L1780.99 72.576 L1780.99 12.096 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1855.53 34.1734 Q1854.27 33.4443 1852.77 33.1202 Q1851.31 32.7556 1849.53 32.7556 Q1843.21 32.7556 1839.81 36.8875 Q1836.45 40.9789 1836.45 48.6757 L1836.45 72.576 L1828.95 72.576 L1828.95 27.2059 L1836.45 27.2059 L1836.45 34.2544 Q1838.8 30.1225 1842.56 28.1376 Q1846.33 26.1121 1851.72 26.1121 Q1852.49 26.1121 1853.42 26.2337 Q1854.35 26.3147 1855.49 26.5172 L1855.53 34.1734 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1900.33 48.0275 L1900.33 51.6733 L1866.06 51.6733 Q1866.55 59.3701 1870.68 63.421 Q1874.85 67.4314 1882.26 67.4314 Q1886.56 67.4314 1890.57 66.3781 Q1894.62 65.3249 1898.59 63.2184 L1898.59 70.267 Q1894.58 71.9684 1890.37 72.8596 Q1886.15 73.7508 1881.82 73.7508 Q1870.96 73.7508 1864.6 67.4314 Q1858.28 61.1119 1858.28 50.3365 Q1858.28 39.1965 1864.28 32.6746 Q1870.31 26.1121 1880.52 26.1121 Q1889.68 26.1121 1894.98 32.0264 Q1900.33 37.9003 1900.33 48.0275 M1892.88 45.84 Q1892.8 39.7232 1889.43 36.0774 Q1886.11 32.4315 1880.6 32.4315 Q1874.36 32.4315 1870.6 35.9558 Q1866.87 39.4801 1866.3 45.8805 L1892.88 45.84 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1931.44 76.7889 Q1928.28 84.8907 1925.28 87.3618 Q1922.29 89.8329 1917.26 89.8329 L1911.31 89.8329 L1911.31 83.5945 L1915.68 83.5945 Q1918.76 83.5945 1920.46 82.1361 Q1922.17 80.6778 1924.23 75.2496 L1925.57 71.8468 L1907.22 27.2059 L1915.12 27.2059 L1929.29 62.6918 L1943.47 27.2059 L1951.37 27.2059 L1931.44 76.7889 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M1988.36 12.096 L2000.55 12.096 L2015.98 53.2532 L2031.5 12.096 L2043.69 12.096 L2043.69 72.576 L2035.71 72.576 L2035.71 19.4686 L2020.12 60.9499 L2011.89 60.9499 L1996.3 19.4686 L1996.3 72.576 L1988.36 72.576 L1988.36 12.096 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M2077.19 32.4315 Q2071.2 32.4315 2067.71 37.1306 Q2064.23 41.7891 2064.23 49.9314 Q2064.23 58.0738 2067.67 62.7728 Q2071.16 67.4314 2077.19 67.4314 Q2083.15 67.4314 2086.63 62.7323 Q2090.12 58.0333 2090.12 49.9314 Q2090.12 41.8701 2086.63 37.1711 Q2083.15 32.4315 2077.19 32.4315 M2077.19 26.1121 Q2086.92 26.1121 2092.47 32.4315 Q2098.01 38.7509 2098.01 49.9314 Q2098.01 61.0714 2092.47 67.4314 Q2086.92 73.7508 2077.19 73.7508 Q2067.43 73.7508 2061.88 67.4314 Q2056.37 61.0714 2056.37 49.9314 Q2056.37 38.7509 2061.88 32.4315 Q2067.43 26.1121 2077.19 26.1121 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M2140.23 34.0924 L2140.23 9.54393 L2147.68 9.54393 L2147.68 72.576 L2140.23 72.576 L2140.23 65.7705 Q2137.88 69.8214 2134.27 71.8063 Q2130.71 73.7508 2125.68 73.7508 Q2117.46 73.7508 2112.27 67.1883 Q2107.13 60.6258 2107.13 49.9314 Q2107.13 39.2371 2112.27 32.6746 Q2117.46 26.1121 2125.68 26.1121 Q2130.71 26.1121 2134.27 28.0971 Q2137.88 30.0415 2140.23 34.0924 M2114.83 49.9314 Q2114.83 58.1548 2118.19 62.8538 Q2121.59 67.5124 2127.51 67.5124 Q2133.42 67.5124 2136.82 62.8538 Q2140.23 58.1548 2140.23 49.9314 Q2140.23 41.7081 2136.82 37.0496 Q2133.42 32.3505 2127.51 32.3505 Q2121.59 32.3505 2118.19 37.0496 Q2114.83 41.7081 2114.83 49.9314 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M2201.84 48.0275 L2201.84 51.6733 L2167.57 51.6733 Q2168.06 59.3701 2172.19 63.421 Q2176.36 67.4314 2183.77 67.4314 Q2188.07 67.4314 2192.08 66.3781 Q2196.13 65.3249 2200.1 63.2184 L2200.1 70.267 Q2196.09 71.9684 2191.87 72.8596 Q2187.66 73.7508 2183.33 73.7508 Q2172.47 73.7508 2166.11 67.4314 Q2159.79 61.1119 2159.79 50.3365 Q2159.79 39.1965 2165.79 32.6746 Q2171.82 26.1121 2182.03 26.1121 Q2191.19 26.1121 2196.49 32.0264 Q2201.84 37.9003 2201.84 48.0275 M2194.39 45.84 Q2194.3 39.7232 2190.94 36.0774 Q2187.62 32.4315 2182.11 32.4315 Q2175.87 32.4315 2172.11 35.9558 Q2168.38 39.4801 2167.81 45.8805 L2194.39 45.84 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M2214.07 9.54393 L2221.53 9.54393 L2221.53 72.576 L2214.07 72.576 L2214.07 9.54393 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><polyline clip-path="url(#clip172)" style="stroke:#009af9; stroke-linecap:round; stroke-linejoin:round; stroke-width:8; stroke-opacity:1; fill:none" points="382.132,1481.53 384.393,1489.23 386.654,1495.63 388.915,1500.98 391.176,1505.47 393.436,1509.27 395.697,1512.48 397.958,1515.22 400.219,1517.55 402.48,1519.55 404.741,1521.26 407.002,1522.73 409.263,1524 411.524,1525.08 413.784,1526.01 416.045,1526.81 418.306,1527.49 420.567,1528.06 422.828,1528.55 425.089,1528.95 427.35,1529.27 429.611,1529.53 431.871,1529.73 434.132,1529.87 436.393,1529.96 438.654,1530.01 440.915,1530.01 443.176,1529.96 445.437,1529.88 447.698,1529.77 449.959,1529.61 452.219,1529.43 454.48,1529.21 456.741,1528.96 459.002,1528.68 461.263,1528.37 463.524,1528.03 465.785,1527.66 468.046,1527.26 470.307,1526.84 472.567,1526.39 474.828,1525.91 477.089,1525.4 479.35,1524.86 481.611,1524.3 483.872,1523.71 486.133,1523.09 488.394,1522.44 490.654,1521.77 492.915,1521.06 495.176,1520.33 497.437,1519.56 499.698,1518.76 501.959,1517.94 504.22,1517.08 506.481,1516.19 508.742,1515.26 511.002,1514.3 513.263,1513.31 515.524,1512.28 517.785,1511.21 520.046,1510.11 522.307,1508.97 524.568,1507.79 526.829,1506.57 529.09,1505.31 531.35,1504.01 533.611,1502.66 535.872,1501.27 538.133,1499.83 540.394,1498.35 542.655,1496.82 544.916,1495.24 547.177,1493.6 549.437,1491.92 551.698,1490.18 553.959,1488.39 556.22,1486.54 558.481,1484.63 560.742,1482.66 563.003,1480.63 565.264,1478.53 567.525,1476.37 569.785,1474.14 572.046,1471.84 574.307,1469.47 576.568,1467.03 578.829,1464.51 581.09,1461.91 583.351,1459.24 585.612,1456.47 587.873,1453.63 590.133,1450.69 592.394,1447.67 594.655,1444.55 596.916,1441.34 599.177,1438.02 601.438,1434.61 603.699,1431.09 605.96,1427.46 608.22,1423.72 610.481,1419.87 612.742,1415.89 615.003,1411.8 617.264,1407.58 619.525,1403.23 621.786,1398.75 624.047,1394.13 626.308,1389.38 628.568,1384.47 630.829,1379.42 633.09,1374.21 635.351,1368.84 637.612,1363.31 639.873,1357.61 642.134,1351.74 644.395,1345.69 646.656,1339.45 648.916,1333.03 651.177,1326.4 653.438,1319.58 655.699,1312.55 657.96,1305.3 660.221,1297.84 662.482,1290.15 664.743,1282.22 667.003,1274.06 669.264,1265.64 671.525,1256.97 673.786,1248.04 676.047,1238.84 678.308,1229.35 680.569,1219.58 682.83,1209.52 685.091,1199.14 687.351,1188.46 689.612,1177.45 691.873,1166.11 694.134,1154.43 696.395,1142.39 698.656,1129.99 700.917,1117.22 703.178,1104.06 705.439,1090.51 707.699,1076.54 709.96,1062.16 712.221,1047.35 714.482,1032.09 716.743,1016.37 719.004,1000.19 721.265,983.521 723.526,966.36 725.787,948.691 728.047,930.499 730.308,911.773 732.569,892.496 734.83,872.658 737.091,852.253 739.352,831.261 741.613,809.662 743.874,787.442 746.134,764.587 748.395,741.091 750.656,716.947 752.917,692.154 755.178,666.714 757.439,640.633 759.7,613.919 761.961,586.585 764.222,558.646 766.482,530.123 768.743,501.087 771.004,471.625 773.265,441.729 775.526,411.473 777.787,381.017 780.048,350.61 782.309,320.588 784.57,291.375 786.83,263.482 789.091,237.509 791.352,214.141 793.613,194.128 795.874,178.751 798.135,169.967 800.396,169.746 802.657,180.035 804.917,202.761 807.178,239.835 809.439,293.174 811.7,363.662 813.961,449.48 816.222,547.673 818.483,654.341 820.744,764.639 823.005,872.867 825.265,974.342 827.526,1065.98 829.787,1145.92 832.048,1213.64 834.309,1269.91 836.57,1316.58 838.831,1354.83 841.092,1385.95 843.353,1411.18 845.613,1431.62 847.874,1448.24 850.135,1461.82 852.396,1472.95 854.657,1482.12 856.918,1489.72 859.179,1496.04 861.44,1501.33 863.7,1505.78 865.961,1509.52 868.222,1512.7 870.483,1515.41 872.744,1517.72 875.005,1519.7 877.266,1521.39 879.527,1522.85 881.788,1524.1 884.048,1525.17 886.309,1526.09 888.57,1526.88 890.831,1527.55 893.092,1528.12 895.353,1528.59 897.614,1528.99 899.875,1529.31 902.136,1529.56 904.396,1529.76 906.657,1529.89 908.918,1529.98 911.179,1530.02 913.44,1530.02 915.701,1529.98 917.962,1529.89 920.223,1529.77 922.483,1529.62 924.744,1529.43 927.005,1529.21 929.266,1528.96 931.527,1528.67 933.788,1528.36 936.049,1528.02 938.31,1527.65 940.571,1527.25 942.831,1526.83 945.092,1526.37 947.353,1525.89 949.614,1525.38 951.875,1524.85 954.136,1524.28 956.397,1523.69 958.658,1523.07 960.919,1522.42 963.179,1521.74 965.44,1521.03 967.701,1520.3 969.962,1519.53 972.223,1518.73 974.484,1517.9 976.745,1517.04 979.006,1516.15 981.266,1515.22 983.527,1514.26 985.788,1513.27 988.049,1512.23 990.31,1511.17 992.571,1510.06 994.832,1508.92 997.093,1507.74 999.354,1506.52 1001.61,1505.25 1003.88,1503.95 1006.14,1502.6 1008.4,1501.21 1010.66,1499.77 1012.92,1498.28 1015.18,1496.75 1017.44,1495.17 1019.7,1493.53 1021.96,1491.84 1024.22,1490.1 1026.48,1488.31 1028.75,1486.45 1031.01,1484.54 1033.27,1482.57 1035.53,1480.54 1037.79,1478.44 1040.05,1476.27 1042.31,1474.04 1044.57,1471.74 1046.83,1469.37 1049.09,1466.92 1051.35,1464.4 1053.61,1461.8 1055.88,1459.11 1058.14,1456.35 1060.4,1453.5 1062.66,1450.56 1064.92,1447.53 1067.18,1444.41 1069.44,1441.19 1071.7,1437.87 1073.96,1434.45 1076.22,1430.93 1078.48,1427.29 1080.75,1423.55 1083.01,1419.69 1085.27,1415.71 1087.53,1411.61 1089.79,1407.39 1092.05,1403.03 1094.31,1398.55 1096.57,1393.92 1098.83,1389.16 1101.09,1384.25 1103.35,1379.19 1105.62,1373.97 1107.88,1368.6 1110.14,1363.06 1112.4,1357.35 1114.66,1351.47 1116.92,1345.41 1119.18,1339.17 1121.44,1332.73 1123.7,1326.1 1125.96,1319.27 1128.22,1312.23 1130.48,1304.97 1132.75,1297.5 1135.01,1289.79 1137.27,1281.86 1139.53,1273.68 1141.79,1265.25 1144.05,1256.57 1146.31,1247.63 1148.57,1238.41 1150.83,1228.92 1153.09,1219.13 1155.35,1209.05 1157.62,1198.67 1159.88,1187.97 1162.14,1176.94 1164.4,1165.59 1166.66,1153.89 1168.92,1141.84 1171.18,1129.43 1173.44,1116.64 1175.7,1103.46 1177.96,1089.89 1180.22,1075.91 1182.49,1061.5 1184.75,1046.67 1187.01,1031.39 1189.27,1015.65 1191.53,999.443 1193.79,982.753 1196.05,965.567 1198.31,947.873 1200.57,929.657 1202.83,910.905 1205.09,891.605 1207.35,871.741 1209.62,851.299 1211.88,830.268 1214.14,808.646 1216.4,786.415 1218.66,763.552 1220.92,740.044 1223.18,715.879 1225.44,691.056 1227.7,665.574 1229.96,639.442 1232.22,612.674 1234.49,585.287 1236.75,557.308 1239.01,528.766 1241.27,499.697 1243.53,470.146 1245.79,440.288 1248.05,410.169 1250.31,379.836 1252.57,349.468 1254.83,319.371 1257.09,289.987 1259.36,261.885 1261.62,235.767 1263.88,212.464 1266.14,192.94 1268.4,178.286 1270.66,169.793 1272.92,169.608 1275.18,180.128 1277.44,203.438 1279.7,241.305 1281.96,295.177 1284.23,366.136 1286.49,452.721 1288.75,551.519 1291.01,658.443 1293.27,768.734 1295.53,876.962 1297.79,978.013 1300.05,1069.18 1302.31,1148.84 1304.57,1216.41 1306.83,1272.34 1309.09,1318.14 1311.36,1355.96 1313.62,1386.85 1315.88,1411.92 1318.14,1432.25 1320.4,1448.77 1322.66,1462.25 1324.92,1473.31 1327.18,1482.42 1329.44,1489.96 1331.7,1496.24 1333.96,1501.5 1336.23,1505.92 1338.49,1509.65 1340.75,1512.81 1343.01,1515.49 1345.27,1517.78 1347.53,1519.75 1349.79,1521.44 1352.05,1522.89 1354.31,1524.14 1356.57,1525.2 1358.83,1526.12 1361.1,1526.9 1363.36,1527.57 1365.62,1528.13 1367.88,1528.61 1370.14,1529 1372.4,1529.32 1374.66,1529.57 1376.92,1529.76 1379.18,1529.9 1381.44,1529.98 1383.7,1530.02 1385.96,1530.02 1388.23,1529.97 1390.49,1529.89 1392.75,1529.77 1395.01,1529.61 1397.27,1529.42 1399.53,1529.2 1401.79,1528.95 1404.05,1528.66 1406.31,1528.35 1408.57,1528.01 1410.83,1527.64 1413.1,1527.24 1415.36,1526.81 1417.62,1526.36 1419.88,1525.87 1422.14,1525.36 1424.4,1524.83 1426.66,1524.26 1428.92,1523.67 1431.18,1523.05 1433.44,1522.4 1435.7,1521.72 1437.97,1521.01 1440.23,1520.27 1442.49,1519.5 1444.75,1518.7 1447.01,1517.87 1449.27,1517.01 1451.53,1516.12 1453.79,1515.19 1456.05,1514.23 1458.31,1513.23 1460.57,1512.2 1462.83,1511.13 1465.1,1510.02 1467.36,1508.88 1469.62,1507.7 1471.88,1506.47 1474.14,1505.21 1476.4,1503.9 1478.66,1502.55 1480.92,1501.16 1483.18,1499.72 1485.44,1498.23 1487.7,1496.69 1489.97,1495.11 1492.23,1493.47 1494.49,1491.78 1496.75,1490.04 1499.01,1488.24 1501.27,1486.39 1503.53,1484.47 1505.79,1482.5 1508.05,1480.46 1510.31,1478.36 1512.57,1476.2 1514.84,1473.96 1517.1,1471.66 1519.36,1469.28 1521.62,1466.83 1523.88,1464.31 1526.14,1461.7 1528.4,1459.02 1530.66,1456.25 1532.92,1453.39 1535.18,1450.45 1537.44,1447.42 1539.71,1444.29 1541.97,1441.07 1544.23,1437.75 1546.49,1434.33 1548.75,1430.8 1551.01,1427.16 1553.27,1423.41 1555.53,1419.55 1557.79,1415.57 1560.05,1411.47 1562.31,1407.24 1564.57,1402.88 1566.84,1398.39 1569.1,1393.76 1571.36,1388.99 1573.62,1384.07 1575.88,1379 1578.14,1373.78 1580.4,1368.4 1582.66,1362.86 1584.92,1357.14 1587.18,1351.26 1589.44,1345.19 1591.71,1338.94 1593.97,1332.5 1596.23,1325.86 1598.49,1319.02 1600.75,1311.97 1603.01,1304.71 1605.27,1297.23 1607.53,1289.51 1609.79,1281.57 1612.05,1273.38 1614.31,1264.95 1616.58,1256.26 1618.84,1247.3 1621.1,1238.08 1623.36,1228.57 1625.62,1218.78 1627.88,1208.69 1630.14,1198.29 1632.4,1187.58 1634.66,1176.54 1636.92,1165.17 1639.18,1153.46 1641.44,1141.4 1643.71,1128.97 1645.97,1116.16 1648.23,1102.97 1650.49,1089.39 1652.75,1075.39 1655.01,1060.98 1657.27,1046.13 1659.53,1030.83 1661.79,1015.08 1664.05,998.855 1666.31,982.147 1668.58,964.943 1670.84,947.229 1673.1,928.992 1675.36,910.22 1677.62,890.898 1679.88,871.012 1682.14,850.55 1684.4,829.497 1686.66,807.841 1688.92,785.582 1691.18,762.699 1693.45,739.174 1695.71,714.994 1697.97,690.154 1700.23,664.653 1702.49,638.499 1704.75,611.706 1707.01,584.292 1709.27,556.283 1711.53,527.713 1713.79,498.62 1716.05,469.049 1718.31,439.15 1720.58,408.997 1722.84,378.658 1725.1,348.32 1727.36,318.297 1729.62,289.026 1731.88,261.066 1734.14,235.103 1736.4,211.943 1738.66,192.517 1740.92,177.867 1743.18,169.505 1745.45,169.755 1747.71,180.816 1749.97,204.666 1752.23,243.058 1754.49,297.525 1756.75,369.222 1759.01,456.354 1761.27,555.485 1763.53,662.531 1765.79,772.766 1768.05,880.822 1770.32,981.507 1772.58,1072.18 1774.84,1151.36 1777.1,1218.53 1779.36,1274.15 1781.62,1319.66 1783.88,1357.19 1786.14,1387.83 1788.4,1412.72 1790.66,1432.9 1792.92,1449.29 1795.19,1462.68 1797.45,1473.66 1799.71,1482.7 1801.97,1490.2 1804.23,1496.44 1806.49,1501.67 1808.75,1506.06 1811.01,1509.77 1813.27,1512.91 1815.53,1515.57 1817.79,1517.85 1820.05,1519.81 1822.32,1521.49 1824.58,1522.94 1826.84,1524.17 1829.1,1525.24 1831.36,1526.15 1833.62,1526.92 1835.88,1527.59 1838.14,1528.15 1840.4,1528.62 1842.66,1529.01 1844.92,1529.32 1847.19,1529.57 1849.45,1529.76 1851.71,1529.9 1853.97,1529.98 1856.23,1530.02 1858.49,1530.01 1860.75,1529.97 1863.01,1529.88 1865.27,1529.76 1867.53,1529.6 1869.79,1529.41 1872.06,1529.19 1874.32,1528.93 1876.58,1528.65 1878.84,1528.33 1881.1,1527.99 1883.36,1527.62 1885.62,1527.22 1887.88,1526.79 1890.14,1526.33 1892.4,1525.85 1894.66,1525.34 1896.92,1524.8 1899.19,1524.23 1901.45,1523.64 1903.71,1523.02 1905.97,1522.37 1908.23,1521.69 1910.49,1520.98 1912.75,1520.24 1915.01,1519.47 1917.27,1518.67 1919.53,1517.84 1921.79,1516.97 1924.06,1516.08 1926.32,1515.15 1928.58,1514.18 1930.84,1513.19 1933.1,1512.15 1935.36,1511.08 1937.62,1509.97 1939.88,1508.83 1942.14,1507.64 1944.4,1506.42 1946.66,1505.15 1948.93,1503.84 1951.19,1502.49 1953.45,1501.1 1955.71,1499.65 1957.97,1498.16 1960.23,1496.63 1962.49,1495.04 1964.75,1493.4 1967.01,1491.71 1969.27,1489.97 1971.53,1488.16 1973.79,1486.31 1976.06,1484.39 1978.32,1482.41 1980.58,1480.37 1982.84,1478.27 1985.1,1476.1 1987.36,1473.86 1989.62,1471.56 1991.88,1469.18 1994.14,1466.73 1996.4,1464.2 1998.66,1461.59 2000.93,1458.9 2003.19,1456.13 2005.45,1453.27 2007.71,1450.33 2009.97,1447.29 2012.23,1444.16 2014.49,1440.93 2016.75,1437.61 2019.01,1434.18 2021.27,1430.65 2023.53,1427 2025.8,1423.25 2028.06,1419.38 2030.32,1415.4 2032.58,1411.29 2034.84,1407.05 2037.1,1402.69 2039.36,1398.19 2041.62,1393.56 2043.88,1388.78 2046.14,1383.86 2048.4,1378.78 2050.66,1373.56 2052.93,1368.17 2055.19,1362.62 2057.45,1356.9 2059.71,1351 2061.97,1344.93 2064.23,1338.67 2066.49,1332.22 2068.75,1325.57 2071.01,1318.72 2073.27,1311.67 2075.53,1304.39 2077.8,1296.9 2080.06,1289.18 2082.32,1281.23 2084.58,1273.03 2086.84,1264.58 2089.1,1255.88 2091.36,1246.92 2093.62,1237.68 2095.88,1228.16 2098.14,1218.35 2100.4,1208.25 2102.67,1197.84 2104.93,1187.12 2107.19,1176.07 2109.45,1164.68 2111.71,1152.96 2113.97,1140.87 2116.23,1128.43 2118.49,1115.61 2120.75,1102.41 2123.01,1088.81 2125.27,1074.8 2127.54,1060.36 2129.8,1045.49 2132.06,1030.18 2134.32,1014.41 2136.58,998.161 2138.84,981.431 2141.1,964.203 2143.36,946.466 2145.62,928.205 2147.88,909.407 2150.14,890.06 2152.4,870.151 2154.67,849.665 2156.93,828.589 2159.19,806.91 2161.45,784.615 2163.71,761.696 2165.97,738.152 2168.23,713.96 2170.49,689.109 2172.75,663.595 2175.01,637.421 2177.27,610.601 2179.54,583.154 2181.8,555.11 2184.06,526.507 2186.32,497.39 2188.58,467.815 2190.84,437.874 2193.1,407.772 2195.36,377.517 2197.62,347.226 2199.88,317.169 2202.14,287.778 2204.41,259.639 2206.67,233.495 2208.93,210.247 2211.19,190.953 2213.45,176.828 2215.71,169.243 2217.97,169.811 2220.23,180.976 2222.49,205.183 2224.75,244.262 2227.01,299.433 2229.27,371.33 2231.54,459.005 2233.8,558.772 2236.06,666.255 2238.32,776.613 2240.58,884.534 2242.84,984.994 2245.1,1075.46 2247.36,1154.5 2249.62,1221.53 2251.88,1276.85 2254.14,1321.62 2256.41,1357.85 2258.67,1388.07 2260.93,1412.85 2263.19,1432.98 2265.45,1449.35 2267.71,1462.71 2269.97,1473.67 2272.23,1482.7 2274.49,1490.18 2276.75,1496.4 2279.01,1501.61 2281.28,1506 2283.54,1509.7 2285.8,1512.85 2288.06,1515.52 2290.32,1517.8 2292.58,1519.74 2294.84,1521.42 2297.1,1522.85 2299.36,1524.09 2301.62,1525.16 2303.88,1526.07 2306.14,1526.85 2308.41,1527.51 2310.67,1528.07 2312.93,1528.54 2315.19,1528.93 2317.45,1529.24 2319.71,1529.49 2321.97,1529.68 2324.23,1529.82 2326.49,1529.9 2328.75,1529.94 2331.01,1529.93 2333.28,1529.88 2335.54,1529.79 2337.8,1529.67 2340.06,1529.51 2342.32,1529.32 2344.58,1529.09 2346.84,1528.84 2349.1,1528.55 2351.36,1528.23 2353.62,1527.89 2355.88,1527.51 2358.15,1527.11 2360.41,1526.68 2362.67,1526.22 2364.93,1525.74 2367.19,1525.22 2369.45,1524.68 2371.71,1524.11 2373.97,1523.52 2376.23,1522.89 2378.49,1522.24 2380.75,1521.55 2383.02,1520.84 2385.28,1520.1 2387.54,1519.32 2389.8,1518.52 2392.06,1517.68 2394.32,1516.82 2396.58,1515.92 2398.84,1514.98 2401.1,1514.02 2403.36,1513.01 2405.62,1511.97 2407.88,1510.9 2410.15,1509.79 2412.41,1508.64 2414.67,1507.45 2416.93,1506.22 2419.19,1504.94 2421.45,1503.63 2423.71,1502.27 2425.97,1500.87 2428.23,1499.42 2430.49,1497.92 2432.75,1496.38 2435.02,1494.78 2437.28,1493.14 2439.54,1491.44 2441.8,1489.69 2444.06,1487.88 2446.32,1486.01 2448.58,1484.09 2450.84,1482.1 2453.1,1480.05 2455.36,1477.94 2457.62,1475.76 2459.89,1473.51 2462.15,1471.2 2464.41,1468.81 2466.67,1466.34 2468.93,1463.8 2471.19,1461.18 2473.45,1458.48 2475.71,1455.7 2477.97,1452.83 2480.23,1449.87 2482.49,1446.82 2484.75,1443.68 2487.02,1440.44 2489.28,1437.1 2491.54,1433.65 2493.8,1430.1 2496.06,1426.45 2498.32,1422.68 2500.58,1418.79 2502.84,1414.78 2505.1,1410.66 2507.36,1406.4 2509.62,1402.02 2511.89,1397.5 2514.15,1392.85 2516.41,1388.05 2518.67,1383.11 2520.93,1378.01 2523.19,1372.76 2525.45,1367.35 2527.71,1361.77 2529.97,1356.03 2532.23,1350.11 2534.49,1344.01 2536.76,1337.72 2539.02,1331.24 2541.28,1324.56 2543.54,1317.68 2545.8,1310.6 2548.06,1303.29 2550.32,1295.77 2552.58,1288.01 2554.84,1280.02 2557.1,1271.79 2559.36,1263.31 2561.62,1254.57 2563.89,1245.56 2566.15,1236.28 2568.41,1226.72 2570.67,1216.87 2572.93,1206.72 2575.19,1196.27 2577.45,1185.5 2579.71,1174.4 2581.97,1162.97 2584.23,1151.19 2586.49,1139.06 2588.76,1126.56 2591.02,1113.68 2593.28,1100.42 2595.54,1086.75 2597.8,1072.68 2600.06,1058.18 2602.32,1043.25 2604.58,1027.87 2606.84,1012.03 2609.1,995.714 2611.36,978.917 2613.63,961.621 2615.89,943.813 2618.15,925.479 2620.41,906.606 2622.67,887.18 2624.93,867.187 2627.19,846.613 2629.45,825.446 2631.71,803.675 2633.97,781.287 2636.23,758.273 2638.5,734.624 2640.76,710.331 "></polyline>
<polyline clip-path="url(#clip172)" style="stroke:#e26f46; stroke-linecap:round; stroke-linejoin:round; stroke-width:8; stroke-opacity:1; fill:none" points="382.132,849.584 384.393,887.76 386.654,924.803 388.915,960.52 391.176,994.788 393.436,1027.53 395.697,1058.72 397.958,1088.35 400.219,1116.43 402.48,1143 404.741,1168.1 407.002,1191.78 409.263,1214.1 411.524,1235.11 413.784,1254.88 416.045,1273.47 418.306,1290.93 420.567,1307.33 422.828,1322.73 425.089,1337.17 427.35,1350.72 429.611,1363.43 431.871,1375.34 434.132,1386.51 436.393,1396.97 438.654,1406.77 440.915,1415.95 443.176,1424.55 445.437,1432.6 447.698,1440.14 449.959,1447.21 452.219,1453.82 454.48,1460 456.741,1465.8 459.002,1471.22 461.263,1476.29 463.524,1481.05 465.785,1485.49 468.046,1489.66 470.307,1493.55 472.567,1497.2 474.828,1500.61 477.089,1503.8 479.35,1506.79 481.611,1509.59 483.872,1512.21 486.133,1514.66 488.394,1516.96 490.654,1519.11 492.915,1521.12 495.176,1523 497.437,1524.76 499.698,1526.41 501.959,1527.96 504.22,1529.4 506.481,1530.76 508.742,1532.03 511.002,1533.22 513.263,1534.33 515.524,1535.37 517.785,1536.35 520.046,1537.27 522.307,1538.12 524.568,1538.93 526.829,1539.68 529.09,1540.39 531.35,1541.05 533.611,1541.67 535.872,1542.25 538.133,1542.8 540.394,1543.31 542.655,1543.79 544.916,1544.24 547.177,1544.66 549.437,1545.06 551.698,1545.43 553.959,1545.78 556.22,1546.1 558.481,1546.41 560.742,1546.7 563.003,1546.97 565.264,1547.22 567.525,1547.46 569.785,1547.69 572.046,1547.9 574.307,1548.1 576.568,1548.28 578.829,1548.46 581.09,1548.62 583.351,1548.77 585.612,1548.92 587.873,1549.06 590.133,1549.18 592.394,1549.31 594.655,1549.42 596.916,1549.53 599.177,1549.63 601.438,1549.72 603.699,1549.81 605.96,1549.89 608.22,1549.97 610.481,1550.04 612.742,1550.11 615.003,1550.18 617.264,1550.24 619.525,1550.3 621.786,1550.35 624.047,1550.4 626.308,1550.45 628.568,1550.49 630.829,1550.53 633.09,1550.57 635.351,1550.61 637.612,1550.64 639.873,1550.68 642.134,1550.71 644.395,1550.73 646.656,1550.76 648.916,1550.78 651.177,1550.8 653.438,1550.82 655.699,1550.84 657.96,1550.86 660.221,1550.87 662.482,1550.89 664.743,1550.9 667.003,1550.91 669.264,1550.92 671.525,1550.92 673.786,1550.93 676.047,1550.93 678.308,1550.93 680.569,1550.93 682.83,1550.93 685.091,1550.93 687.351,1550.92 689.612,1550.91 691.873,1550.9 694.134,1550.89 696.395,1550.88 698.656,1550.86 700.917,1550.84 703.178,1550.82 705.439,1550.79 707.699,1550.76 709.96,1550.73 712.221,1550.69 714.482,1550.65 716.743,1550.61 719.004,1550.55 721.265,1550.49 723.526,1550.42 725.787,1550.35 728.047,1550.26 730.308,1550.16 732.569,1550.04 734.83,1549.91 737.091,1549.75 739.352,1549.57 741.613,1549.37 743.874,1549.14 746.134,1548.89 748.395,1548.6 750.656,1548.26 752.917,1547.87 755.178,1547.4 757.439,1546.84 759.7,1546.17 761.961,1545.36 764.222,1544.38 766.482,1543.22 768.743,1541.79 771.004,1540.03 773.265,1537.93 775.526,1535.41 777.787,1532.35 780.048,1528.57 782.309,1523.82 784.57,1517.78 786.83,1510.09 789.091,1500.3 791.352,1487.93 793.613,1472.44 795.874,1452.93 798.135,1428.03 800.396,1396.45 802.657,1357.04 804.917,1308.78 807.178,1250.77 809.439,1182.2 811.7,1103.37 813.961,1017.41 816.222,928.157 818.483,839.859 820.744,757.218 823.005,685.3 825.265,627.847 827.526,586.531 829.787,561.757 832.048,552.651 834.309,557.064 836.57,571.877 838.831,594.987 841.092,624.448 843.353,658.473 845.613,695.5 847.874,734.201 850.135,773.625 852.396,813.104 854.657,852.098 856.918,890.21 859.179,927.172 861.44,962.794 863.7,996.969 865.961,1029.62 868.222,1060.72 870.483,1090.24 872.744,1118.22 875.005,1144.69 877.266,1169.7 879.527,1193.29 881.788,1215.53 884.048,1236.46 886.309,1256.15 888.57,1274.66 890.831,1292.05 893.092,1308.39 895.353,1323.72 897.614,1338.1 899.875,1351.6 902.136,1364.25 904.396,1376.11 906.657,1387.22 908.918,1397.64 911.179,1407.4 913.44,1416.55 915.701,1425.11 917.962,1433.13 920.223,1440.63 922.483,1447.66 924.744,1454.24 927.005,1460.4 929.266,1466.17 931.527,1471.57 933.788,1476.63 936.049,1481.36 938.31,1485.78 940.571,1489.93 942.831,1493.8 945.092,1497.43 947.353,1500.83 949.614,1504.01 951.875,1506.99 954.136,1509.77 956.397,1512.38 958.658,1514.82 960.919,1517.11 963.179,1519.25 965.44,1521.25 967.701,1523.12 969.962,1524.88 972.223,1526.52 974.484,1528.06 976.745,1529.5 979.006,1530.85 981.266,1532.11 983.527,1533.3 985.788,1534.41 988.049,1535.44 990.31,1536.42 992.571,1537.33 994.832,1538.18 997.093,1538.98 999.354,1539.73 1001.61,1540.43 1003.88,1541.09 1006.14,1541.71 1008.4,1542.29 1010.66,1542.83 1012.92,1543.34 1015.18,1543.82 1017.44,1544.27 1019.7,1544.69 1021.96,1545.08 1024.22,1545.45 1026.48,1545.8 1028.75,1546.13 1031.01,1546.43 1033.27,1546.72 1035.53,1546.99 1037.79,1547.24 1040.05,1547.48 1042.31,1547.7 1044.57,1547.91 1046.83,1548.11 1049.09,1548.29 1051.35,1548.47 1053.61,1548.63 1055.88,1548.79 1058.14,1548.93 1060.4,1549.07 1062.66,1549.19 1064.92,1549.31 1067.18,1549.43 1069.44,1549.53 1071.7,1549.63 1073.96,1549.73 1076.22,1549.82 1078.48,1549.9 1080.75,1549.98 1083.01,1550.05 1085.27,1550.12 1087.53,1550.18 1089.79,1550.24 1092.05,1550.3 1094.31,1550.36 1096.57,1550.41 1098.83,1550.45 1101.09,1550.5 1103.35,1550.54 1105.62,1550.58 1107.88,1550.61 1110.14,1550.65 1112.4,1550.68 1114.66,1550.71 1116.92,1550.74 1119.18,1550.76 1121.44,1550.78 1123.7,1550.81 1125.96,1550.83 1128.22,1550.84 1130.48,1550.86 1132.75,1550.88 1135.01,1550.89 1137.27,1550.9 1139.53,1550.91 1141.79,1550.92 1144.05,1550.92 1146.31,1550.93 1148.57,1550.93 1150.83,1550.93 1153.09,1550.93 1155.35,1550.93 1157.62,1550.93 1159.88,1550.92 1162.14,1550.92 1164.4,1550.9 1166.66,1550.89 1168.92,1550.87 1171.18,1550.86 1173.44,1550.83 1175.7,1550.81 1177.96,1550.79 1180.22,1550.76 1182.49,1550.73 1184.75,1550.69 1187.01,1550.65 1189.27,1550.6 1191.53,1550.55 1193.79,1550.49 1196.05,1550.42 1198.31,1550.35 1200.57,1550.26 1202.83,1550.16 1205.09,1550.04 1207.35,1549.91 1209.62,1549.76 1211.88,1549.59 1214.14,1549.38 1216.4,1549.14 1218.66,1548.87 1220.92,1548.56 1223.18,1548.22 1225.44,1547.82 1227.7,1547.35 1229.96,1546.8 1232.22,1546.14 1234.49,1545.34 1236.75,1544.37 1239.01,1543.19 1241.27,1541.77 1243.53,1540.04 1245.79,1537.89 1248.05,1535.25 1250.31,1532.08 1252.57,1528.23 1254.83,1523.48 1257.09,1517.51 1259.36,1509.9 1261.62,1500.17 1263.88,1487.71 1266.14,1471.85 1268.4,1451.82 1270.66,1426.74 1272.92,1395.16 1275.18,1355.55 1277.44,1306.81 1279.7,1248.19 1281.96,1179.38 1284.23,1100.47 1286.49,1014.1 1288.75,924.548 1291.01,836.278 1293.27,753.933 1295.53,682.339 1297.79,625.614 1300.05,585.057 1302.31,560.761 1304.57,551.895 1306.83,556.705 1309.09,572.509 1311.36,596.072 1313.62,625.684 1315.88,659.74 1318.14,696.772 1320.4,735.536 1322.66,775.01 1324.92,814.473 1327.18,853.44 1329.44,891.525 1331.7,928.445 1333.96,964.023 1336.23,998.135 1338.49,1030.72 1340.75,1061.77 1343.01,1091.25 1345.27,1119.19 1347.53,1145.6 1349.79,1170.55 1352.05,1194.09 1354.31,1216.28 1356.57,1237.17 1358.83,1256.81 1361.1,1275.29 1363.36,1292.64 1365.62,1308.94 1367.88,1324.24 1370.14,1338.59 1372.4,1352.05 1374.66,1364.68 1376.92,1376.51 1379.18,1387.6 1381.44,1397.99 1383.7,1407.73 1385.96,1416.85 1388.23,1425.4 1390.49,1433.4 1392.75,1440.89 1395.01,1447.9 1397.27,1454.47 1399.53,1460.61 1401.79,1466.37 1404.05,1471.75 1406.31,1476.79 1408.57,1481.51 1410.83,1485.93 1413.1,1490.07 1415.36,1493.94 1417.62,1497.56 1419.88,1500.95 1422.14,1504.12 1424.4,1507.09 1426.66,1509.87 1428.92,1512.47 1431.18,1514.9 1433.44,1517.18 1435.7,1519.32 1437.97,1521.32 1440.23,1523.19 1442.49,1524.94 1444.75,1526.58 1447.01,1528.11 1449.27,1529.55 1451.53,1530.89 1453.79,1532.15 1456.05,1533.34 1458.31,1534.44 1460.57,1535.48 1462.83,1536.45 1465.1,1537.36 1467.36,1538.21 1469.62,1539.01 1471.88,1539.76 1474.14,1540.46 1476.4,1541.12 1478.66,1541.73 1480.92,1542.31 1483.18,1542.85 1485.44,1543.36 1487.7,1543.84 1489.97,1544.28 1492.23,1544.7 1494.49,1545.1 1496.75,1545.46 1499.01,1545.81 1501.27,1546.14 1503.53,1546.44 1505.79,1546.73 1508.05,1547 1510.31,1547.25 1512.57,1547.49 1514.84,1547.71 1517.1,1547.92 1519.36,1548.12 1521.62,1548.3 1523.88,1548.47 1526.14,1548.64 1528.4,1548.79 1530.66,1548.93 1532.92,1549.07 1535.18,1549.2 1537.44,1549.32 1539.71,1549.43 1541.97,1549.54 1544.23,1549.64 1546.49,1549.73 1548.75,1549.82 1551.01,1549.9 1553.27,1549.98 1555.53,1550.05 1557.79,1550.12 1560.05,1550.19 1562.31,1550.25 1564.57,1550.3 1566.84,1550.36 1569.1,1550.41 1571.36,1550.45 1573.62,1550.5 1575.88,1550.54 1578.14,1550.58 1580.4,1550.62 1582.66,1550.65 1584.92,1550.68 1587.18,1550.71 1589.44,1550.74 1591.71,1550.76 1593.97,1550.79 1596.23,1550.81 1598.49,1550.83 1600.75,1550.85 1603.01,1550.86 1605.27,1550.88 1607.53,1550.89 1609.79,1550.9 1612.05,1550.91 1614.31,1550.92 1616.58,1550.92 1618.84,1550.93 1621.1,1550.93 1623.36,1550.93 1625.62,1550.93 1627.88,1550.93 1630.14,1550.93 1632.4,1550.92 1634.66,1550.92 1636.92,1550.91 1639.18,1550.89 1641.44,1550.88 1643.71,1550.86 1645.97,1550.84 1648.23,1550.82 1650.49,1550.79 1652.75,1550.76 1655.01,1550.73 1657.27,1550.69 1659.53,1550.65 1661.79,1550.6 1664.05,1550.55 1666.31,1550.49 1668.58,1550.42 1670.84,1550.34 1673.1,1550.25 1675.36,1550.15 1677.62,1550.04 1679.88,1549.91 1682.14,1549.76 1684.4,1549.58 1686.66,1549.39 1688.92,1549.15 1691.18,1548.87 1693.45,1548.56 1695.71,1548.21 1697.97,1547.8 1700.23,1547.33 1702.49,1546.77 1704.75,1546.11 1707.01,1545.31 1709.27,1544.34 1711.53,1543.15 1713.79,1541.72 1716.05,1539.99 1718.31,1537.84 1720.58,1535.2 1722.84,1532.01 1725.1,1528.12 1727.36,1523.29 1729.62,1517.22 1731.88,1509.5 1734.14,1499.64 1736.4,1487.06 1738.66,1471.1 1740.92,1451.03 1743.18,1425.82 1745.45,1393.88 1747.71,1353.88 1749.97,1304.77 1752.23,1245.83 1754.49,1176.66 1756.75,1097.28 1759.01,1010.67 1761.27,921.137 1763.53,833.11 1765.79,751.177 1768.05,680.073 1770.32,623.961 1772.58,584.097 1774.84,560.424 1777.1,552.037 1779.36,557.185 1781.62,573.264 1783.88,597.107 1786.14,626.913 1788.4,661.096 1790.66,698.2 1792.92,736.996 1795.19,776.477 1797.45,815.927 1799.71,854.865 1801.97,892.909 1804.23,929.781 1806.49,965.305 1808.75,999.36 1811.01,1031.89 1813.27,1062.87 1815.53,1092.3 1817.79,1120.18 1820.05,1146.54 1822.32,1171.44 1824.58,1194.93 1826.84,1217.06 1829.1,1237.91 1831.36,1257.51 1833.62,1275.94 1835.88,1293.25 1838.14,1309.51 1840.4,1324.77 1842.66,1339.1 1844.92,1352.53 1847.19,1365.12 1849.45,1376.93 1851.71,1387.99 1853.97,1398.36 1856.23,1408.07 1858.49,1417.17 1860.75,1425.7 1863.01,1433.68 1865.27,1441.15 1867.53,1448.15 1869.79,1454.7 1872.06,1460.83 1874.32,1466.57 1876.58,1471.94 1878.84,1476.97 1881.1,1481.68 1883.36,1486.09 1885.62,1490.21 1887.88,1494.07 1890.14,1497.69 1892.4,1501.07 1894.66,1504.23 1896.92,1507.19 1899.19,1509.96 1901.45,1512.56 1903.71,1514.99 1905.97,1517.26 1908.23,1519.39 1910.49,1521.39 1912.75,1523.25 1915.01,1525 1917.27,1526.63 1919.53,1528.16 1921.79,1529.6 1924.06,1530.94 1926.32,1532.2 1928.58,1533.38 1930.84,1534.48 1933.1,1535.51 1935.36,1536.48 1937.62,1537.39 1939.88,1538.24 1942.14,1539.04 1944.4,1539.78 1946.66,1540.48 1948.93,1541.14 1951.19,1541.75 1953.45,1542.33 1955.71,1542.87 1957.97,1543.38 1960.23,1543.85 1962.49,1544.3 1964.75,1544.72 1967.01,1545.11 1969.27,1545.48 1971.53,1545.82 1973.79,1546.15 1976.06,1546.45 1978.32,1546.74 1980.58,1547.01 1982.84,1547.26 1985.1,1547.49 1987.36,1547.72 1989.62,1547.93 1991.88,1548.12 1994.14,1548.31 1996.4,1548.48 1998.66,1548.64 2000.93,1548.8 2003.19,1548.94 2005.45,1549.08 2007.71,1549.2 2009.97,1549.32 2012.23,1549.43 2014.49,1549.54 2016.75,1549.64 2019.01,1549.73 2021.27,1549.82 2023.53,1549.9 2025.8,1549.98 2028.06,1550.05 2030.32,1550.12 2032.58,1550.19 2034.84,1550.25 2037.1,1550.31 2039.36,1550.36 2041.62,1550.41 2043.88,1550.46 2046.14,1550.5 2048.4,1550.54 2050.66,1550.58 2052.93,1550.62 2055.19,1550.65 2057.45,1550.68 2059.71,1550.71 2061.97,1550.74 2064.23,1550.76 2066.49,1550.79 2068.75,1550.81 2071.01,1550.83 2073.27,1550.85 2075.53,1550.86 2077.8,1550.88 2080.06,1550.89 2082.32,1550.9 2084.58,1550.91 2086.84,1550.92 2089.1,1550.92 2091.36,1550.93 2093.62,1550.93 2095.88,1550.93 2098.14,1550.93 2100.4,1550.93 2102.67,1550.93 2104.93,1550.92 2107.19,1550.91 2109.45,1550.91 2111.71,1550.89 2113.97,1550.88 2116.23,1550.86 2118.49,1550.84 2120.75,1550.81 2123.01,1550.78 2125.27,1550.75 2127.54,1550.72 2129.8,1550.68 2132.06,1550.64 2134.32,1550.59 2136.58,1550.54 2138.84,1550.48 2141.1,1550.41 2143.36,1550.34 2145.62,1550.25 2147.88,1550.15 2150.14,1550.04 2152.4,1549.9 2154.67,1549.75 2156.93,1549.58 2159.19,1549.38 2161.45,1549.15 2163.71,1548.88 2165.97,1548.56 2168.23,1548.19 2170.49,1547.77 2172.75,1547.29 2175.01,1546.72 2177.27,1546.05 2179.54,1545.25 2181.8,1544.27 2184.06,1543.09 2186.32,1541.65 2188.58,1539.9 2190.84,1537.75 2193.1,1535.06 2195.36,1531.79 2197.62,1527.83 2199.88,1522.99 2202.14,1516.95 2204.41,1509.29 2206.67,1499.49 2208.93,1486.9 2211.19,1470.81 2213.45,1450.36 2215.71,1424.62 2217.97,1392.49 2220.23,1352.42 2222.49,1303.02 2224.75,1243.55 2227.01,1173.91 2229.27,1094.64 2231.54,1007.84 2233.8,917.99 2236.06,829.814 2238.32,748.022 2240.58,677.324 2242.84,621.719 2245.1,582.298 2247.36,558.952 2249.62,550.841 2251.88,556.397 2254.14,573.316 2256.41,598.566 2258.67,628.757 2260.93,662.896 2263.19,699.878 2265.45,738.553 2267.71,777.97 2269.97,817.378 2272.23,856.233 2274.49,894.192 2276.75,930.994 2279.01,966.45 2281.28,1000.44 2283.54,1032.9 2285.8,1063.81 2288.06,1093.16 2290.32,1120.98 2292.58,1147.3 2294.84,1172.16 2297.1,1195.6 2299.36,1217.68 2301.62,1238.47 2303.88,1258.04 2306.14,1276.43 2308.41,1293.71 2310.67,1309.94 2312.93,1325.17 2315.19,1339.46 2317.45,1352.86 2319.71,1365.43 2321.97,1377.22 2324.23,1388.26 2326.49,1398.61 2328.75,1408.31 2331.01,1417.39 2333.28,1425.89 2335.54,1433.86 2337.8,1441.32 2340.06,1448.3 2342.32,1454.84 2344.58,1460.96 2346.84,1466.7 2349.1,1472.06 2351.36,1477.08 2353.62,1481.78 2355.88,1486.18 2358.15,1490.29 2360.41,1494.15 2362.67,1497.75 2364.93,1501.13 2367.19,1504.29 2369.45,1507.25 2371.71,1510.02 2373.97,1512.61 2376.23,1515.03 2378.49,1517.3 2380.75,1519.43 2383.02,1521.42 2385.28,1523.28 2387.54,1525.02 2389.8,1526.66 2392.06,1528.19 2394.32,1529.62 2396.58,1530.96 2398.84,1532.22 2401.1,1533.39 2403.36,1534.49 2405.62,1535.53 2407.88,1536.49 2410.15,1537.4 2412.41,1538.25 2414.67,1539.04 2416.93,1539.79 2419.19,1540.49 2421.45,1541.14 2423.71,1541.76 2425.97,1542.33 2428.23,1542.87 2430.49,1543.38 2432.75,1543.85 2435.02,1544.3 2437.28,1544.72 2439.54,1545.11 2441.8,1545.48 2444.06,1545.82 2446.32,1546.15 2448.58,1546.45 2450.84,1546.74 2453.1,1547 2455.36,1547.26 2457.62,1547.49 2459.89,1547.71 2462.15,1547.92 2464.41,1548.12 2466.67,1548.3 2468.93,1548.48 2471.19,1548.64 2473.45,1548.79 2475.71,1548.94 2477.97,1549.07 2480.23,1549.2 2482.49,1549.32 2484.75,1549.43 2487.02,1549.54 2489.28,1549.64 2491.54,1549.73 2493.8,1549.82 2496.06,1549.9 2498.32,1549.98 2500.58,1550.05 2502.84,1550.12 2505.1,1550.18 2507.36,1550.24 2509.62,1550.3 2511.89,1550.35 2514.15,1550.4 2516.41,1550.45 2518.67,1550.49 2520.93,1550.54 2523.19,1550.57 2525.45,1550.61 2527.71,1550.64 2529.97,1550.68 2532.23,1550.71 2534.49,1550.73 2536.76,1550.76 2539.02,1550.78 2541.28,1550.8 2543.54,1550.82 2545.8,1550.84 2548.06,1550.86 2550.32,1550.87 2552.58,1550.88 2554.84,1550.89 2557.1,1550.9 2559.36,1550.91 2561.62,1550.92 2563.89,1550.92 2566.15,1550.93 2568.41,1550.93 2570.67,1550.93 2572.93,1550.92 2575.19,1550.92 2577.45,1550.91 2579.71,1550.9 2581.97,1550.89 2584.23,1550.88 2586.49,1550.87 2588.76,1550.85 2591.02,1550.83 2593.28,1550.81 2595.54,1550.78 2597.8,1550.75 2600.06,1550.72 2602.32,1550.68 2604.58,1550.63 2606.84,1550.58 2609.1,1550.53 2611.36,1550.46 2613.63,1550.39 2615.89,1550.31 2618.15,1550.22 2620.41,1550.11 2622.67,1549.99 2624.93,1549.86 2627.19,1549.7 2629.45,1549.53 2631.71,1549.33 2633.97,1549.09 2636.23,1548.82 2638.5,1548.51 2640.76,1548.14 "></polyline>
<path clip-path="url(#clip170)" d="M2181.04 332.132 L2565.47 332.132 L2565.47 176.612 L2181.04 176.612  Z" fill="#ffffff" fill-rule="evenodd" fill-opacity="1"></path>
<polyline clip-path="url(#clip170)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="2181.04,332.132 2565.47,332.132 2565.47,176.612 2181.04,176.612 2181.04,332.132 "></polyline>
<polyline clip-path="url(#clip170)" style="stroke:#009af9; stroke-linecap:round; stroke-linejoin:round; stroke-width:8; stroke-opacity:1; fill:none" points="2206.14,228.452 2356.71,228.452 "></polyline>
<path clip-path="url(#clip170)" d="M2396.99 223.788 Q2396.28 223.371 2395.42 223.186 Q2394.59 222.977 2393.57 222.977 Q2389.96 222.977 2388.01 225.338 Q2386.09 227.676 2386.09 232.075 L2386.09 245.732 L2381.81 245.732 L2381.81 219.806 L2386.09 219.806 L2386.09 223.834 Q2387.43 221.473 2389.59 220.338 Q2391.74 219.181 2394.82 219.181 Q2395.26 219.181 2395.79 219.251 Q2396.32 219.297 2396.97 219.413 L2396.99 223.788 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M2413.24 232.7 Q2408.08 232.7 2406.09 233.88 Q2404.1 235.061 2404.1 237.908 Q2404.1 240.176 2405.58 241.519 Q2407.09 242.838 2409.66 242.838 Q2413.2 242.838 2415.33 240.338 Q2417.48 237.815 2417.48 233.649 L2417.48 232.7 L2413.24 232.7 M2421.74 230.94 L2421.74 245.732 L2417.48 245.732 L2417.48 241.797 Q2416.02 244.158 2413.85 245.292 Q2411.67 246.403 2408.52 246.403 Q2404.54 246.403 2402.18 244.181 Q2399.84 241.936 2399.84 238.186 Q2399.84 233.811 2402.76 231.588 Q2405.7 229.366 2411.51 229.366 L2417.48 229.366 L2417.48 228.95 Q2417.48 226.01 2415.54 224.413 Q2413.61 222.792 2410.12 222.792 Q2407.9 222.792 2405.79 223.325 Q2403.68 223.857 2401.74 224.922 L2401.74 220.987 Q2404.08 220.084 2406.28 219.644 Q2408.48 219.181 2410.56 219.181 Q2416.18 219.181 2418.96 222.098 Q2421.74 225.014 2421.74 230.94 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M2449.12 232.792 Q2449.12 228.093 2447.18 225.431 Q2445.26 222.746 2441.88 222.746 Q2438.5 222.746 2436.55 225.431 Q2434.63 228.093 2434.63 232.792 Q2434.63 237.491 2436.55 240.176 Q2438.5 242.838 2441.88 242.838 Q2445.26 242.838 2447.18 240.176 Q2449.12 237.491 2449.12 232.792 M2434.63 223.741 Q2435.98 221.426 2438.01 220.315 Q2440.07 219.181 2442.92 219.181 Q2447.64 219.181 2450.58 222.931 Q2453.54 226.681 2453.54 232.792 Q2453.54 238.903 2450.58 242.653 Q2447.64 246.403 2442.92 246.403 Q2440.07 246.403 2438.01 245.292 Q2435.98 244.158 2434.63 241.843 L2434.63 245.732 L2430.35 245.732 L2430.35 209.714 L2434.63 209.714 L2434.63 223.741 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M2479.22 232.792 Q2479.22 228.093 2477.27 225.431 Q2475.35 222.746 2471.97 222.746 Q2468.59 222.746 2466.65 225.431 Q2464.72 228.093 2464.72 232.792 Q2464.72 237.491 2466.65 240.176 Q2468.59 242.838 2471.97 242.838 Q2475.35 242.838 2477.27 240.176 Q2479.22 237.491 2479.22 232.792 M2464.72 223.741 Q2466.07 221.426 2468.1 220.315 Q2470.16 219.181 2473.01 219.181 Q2477.73 219.181 2480.67 222.931 Q2483.64 226.681 2483.64 232.792 Q2483.64 238.903 2480.67 242.653 Q2477.73 246.403 2473.01 246.403 Q2470.16 246.403 2468.1 245.292 Q2466.07 244.158 2464.72 241.843 L2464.72 245.732 L2460.44 245.732 L2460.44 209.714 L2464.72 209.714 L2464.72 223.741 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M2490.7 219.806 L2494.96 219.806 L2494.96 245.732 L2490.7 245.732 L2490.7 219.806 M2490.7 209.714 L2494.96 209.714 L2494.96 215.107 L2490.7 215.107 L2490.7 209.714 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M2508.08 212.445 L2508.08 219.806 L2516.85 219.806 L2516.85 223.116 L2508.08 223.116 L2508.08 237.19 Q2508.08 240.362 2508.94 241.264 Q2509.82 242.167 2512.48 242.167 L2516.85 242.167 L2516.85 245.732 L2512.48 245.732 Q2507.55 245.732 2505.67 243.903 Q2503.8 242.051 2503.8 237.19 L2503.8 223.116 L2500.67 223.116 L2500.67 219.806 L2503.8 219.806 L2503.8 212.445 L2508.08 212.445 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M2538.98 220.57 L2538.98 224.598 Q2537.18 223.672 2535.23 223.209 Q2533.29 222.746 2531.21 222.746 Q2528.03 222.746 2526.44 223.718 Q2524.86 224.69 2524.86 226.635 Q2524.86 228.116 2526 228.973 Q2527.13 229.806 2530.56 230.57 L2532.02 230.894 Q2536.55 231.866 2538.45 233.649 Q2540.37 235.408 2540.37 238.579 Q2540.37 242.19 2537.5 244.297 Q2534.66 246.403 2529.66 246.403 Q2527.57 246.403 2525.3 245.987 Q2523.06 245.593 2520.56 244.783 L2520.56 240.385 Q2522.92 241.612 2525.21 242.237 Q2527.5 242.838 2529.75 242.838 Q2532.76 242.838 2534.38 241.82 Q2536 240.778 2536 238.903 Q2536 237.167 2534.82 236.241 Q2533.66 235.315 2529.7 234.459 L2528.22 234.112 Q2524.26 233.278 2522.5 231.565 Q2520.74 229.829 2520.74 226.82 Q2520.74 223.163 2523.34 221.172 Q2525.93 219.181 2530.7 219.181 Q2533.06 219.181 2535.14 219.528 Q2537.22 219.876 2538.98 220.57 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><polyline clip-path="url(#clip170)" style="stroke:#e26f46; stroke-linecap:round; stroke-linejoin:round; stroke-width:8; stroke-opacity:1; fill:none" points="2206.14,280.292 2356.71,280.292 "></polyline>
<path clip-path="url(#clip170)" d="M2398.31 261.554 L2398.31 265.095 L2394.24 265.095 Q2391.95 265.095 2391.04 266.021 Q2390.17 266.947 2390.17 269.354 L2390.17 271.646 L2397.18 271.646 L2397.18 274.956 L2390.17 274.956 L2390.17 297.572 L2385.88 297.572 L2385.88 274.956 L2381.81 274.956 L2381.81 271.646 L2385.88 271.646 L2385.88 269.841 Q2385.88 265.512 2387.9 263.544 Q2389.91 261.554 2394.29 261.554 L2398.31 261.554 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M2411.92 274.632 Q2408.5 274.632 2406.51 277.317 Q2404.52 279.979 2404.52 284.632 Q2404.52 289.285 2406.48 291.97 Q2408.48 294.632 2411.92 294.632 Q2415.33 294.632 2417.32 291.947 Q2419.31 289.262 2419.31 284.632 Q2419.31 280.026 2417.32 277.341 Q2415.33 274.632 2411.92 274.632 M2411.92 271.021 Q2417.48 271.021 2420.65 274.632 Q2423.82 278.243 2423.82 284.632 Q2423.82 290.998 2420.65 294.632 Q2417.48 298.243 2411.92 298.243 Q2406.35 298.243 2403.17 294.632 Q2400.03 290.998 2400.03 284.632 Q2400.03 278.243 2403.17 274.632 Q2406.35 271.021 2411.92 271.021 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M2450.97 271.646 L2441.6 284.262 L2451.46 297.572 L2446.44 297.572 L2438.89 287.387 L2431.35 297.572 L2426.32 297.572 L2436.39 284.007 L2427.18 271.646 L2432.2 271.646 L2439.08 280.882 L2445.95 271.646 L2450.97 271.646 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M2478.2 283.544 L2478.2 285.627 L2458.61 285.627 Q2458.89 290.026 2461.25 292.34 Q2463.64 294.632 2467.87 294.632 Q2470.33 294.632 2472.62 294.03 Q2474.93 293.428 2477.2 292.225 L2477.2 296.252 Q2474.91 297.225 2472.5 297.734 Q2470.1 298.243 2467.62 298.243 Q2461.41 298.243 2457.78 294.632 Q2454.17 291.021 2454.17 284.864 Q2454.17 278.498 2457.6 274.771 Q2461.04 271.021 2466.88 271.021 Q2472.11 271.021 2475.14 274.401 Q2478.2 277.757 2478.2 283.544 M2473.94 282.294 Q2473.89 278.799 2471.97 276.716 Q2470.07 274.632 2466.92 274.632 Q2463.36 274.632 2461.21 276.646 Q2459.08 278.66 2458.75 282.317 L2473.94 282.294 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip170)" d="M2501.72 272.41 L2501.72 276.438 Q2499.91 275.512 2497.97 275.049 Q2496.02 274.586 2493.94 274.586 Q2490.77 274.586 2489.17 275.558 Q2487.6 276.53 2487.6 278.475 Q2487.6 279.956 2488.73 280.813 Q2489.86 281.646 2493.29 282.41 L2494.75 282.734 Q2499.28 283.706 2501.18 285.489 Q2503.1 287.248 2503.1 290.419 Q2503.1 294.03 2500.23 296.137 Q2497.39 298.243 2492.39 298.243 Q2490.3 298.243 2488.03 297.827 Q2485.79 297.433 2483.29 296.623 L2483.29 292.225 Q2485.65 293.452 2487.94 294.077 Q2490.23 294.678 2492.48 294.678 Q2495.49 294.678 2497.11 293.66 Q2498.73 292.618 2498.73 290.743 Q2498.73 289.007 2497.55 288.081 Q2496.39 287.155 2492.43 286.299 L2490.95 285.952 Q2486.99 285.118 2485.23 283.405 Q2483.47 281.669 2483.47 278.66 Q2483.47 275.003 2486.07 273.012 Q2488.66 271.021 2493.43 271.021 Q2495.79 271.021 2497.87 271.368 Q2499.96 271.716 2501.72 272.41 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path></svg>
</div>
</div>
</section>
</section>
<section id="composition-patterns-from-graphs" class="level2">
<h2 class="anchored" data-anchor-id="composition-patterns-from-graphs">Composition patterns from graphs</h2>
<p>The innovation of composing dynamical systems as machines alleviates some of the bookkeeping endemic to implementing a complicated ODE. However, the mappings of ports can still be quite intricate in a composition of machines with many variables, boxes, and wires. In this section, we use directed graphs to present composition patterns more succinctly.<sup>4</sup></p>
<p>Recall the schema for graphs introduced in an <a href="../../../../post/2020/09/cset-graphs-1">earlier blog post</a>:</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2021/01/machines/_svgs/2ea02c30bc04e69fc815bd9800b3ee7198312c7b.svg" class="img-fluid">
</div>
<p>We can transform an instance of <code>Graph</code> into an instance of <code>SIPortGraph</code> via pullback functorial data migration (see Appendix) induced by the functor <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BTh(SIPortGraph)%7D%20%5Cto%20%5Cmathsf%7BTh(Graph)%7D"> defined on objects by - <img src="https://latex.codecogs.com/png.latex?P_%7B%5Ctextrm%7Bin%7D%7D%5Cmapsto%20E">, <img src="https://latex.codecogs.com/png.latex?P_%7B%5Ctextrm%7Bout%7D%7D%5Cmapsto%20E"> - <img src="https://latex.codecogs.com/png.latex?%5Ctextrm%7BBox%7D%5Cmapsto%20V"></p>
<p>and on morphisms by - <img src="https://latex.codecogs.com/png.latex?%5Coperatorname%7Bwire%7D%5Cmapsto%20%5Coperatorname%7Bid%7D(E)"> - <img src="https://latex.codecogs.com/png.latex?%5Coperatorname%7Bbox_%7Bin%7D%7D%5Cmapsto%20%5Coperatorname%7Btgt%7D"> - <img src="https://latex.codecogs.com/png.latex?%5Coperatorname%7Bbox_%7Bout%7D%7D%5Cmapsto%20%5Coperatorname%7Bsrc%7D"></p>
<p>Single-input port graphs induced by ordinary graphs are a restricted class of single-input port graphs. Generically, a single-input port graph allows out-port splitting, i.e.&nbsp;two distinct in-ports may be wired to a single out-port. This syntactic feature implements the copying of output data and is not available in the more restrictive composition syntax defined by the theory of graphs.</p>
<section id="example-three-species-ecosystem" class="level3">
<h3 class="anchored" data-anchor-id="example-three-species-ecosystem">Example: Three species ecosystem</h3>
<p>Consider a ocean ecosystem containing three species — little fish, big fish, and sharks — with two predation interactions — sharks eat big fish and big fish eat little fish.</p>
<p>In order to save ourselves the bookkeeping of ports, wires, and boxes, we can model the composition pattern as the graph <code>ocean_graph</code> and then migrate the data of <code>ocean_graph</code> to an instance of <code>SIPortGraph</code>.</p>
<div id="16" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb6-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab.Graphs</span>: SchGraph, Graph</span>
<span id="cb6-2"></span>
<span id="cb6-3">ocean_graph <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Graph</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb6-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">add_parts!</span>(ocean_graph, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>E, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, src<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>], tgt<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>])</span></code></pre></div>
</details>
</div>
<div id="18" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<figure class="figure">
<p><img src="https://blog.algebraicjulia.org/post/2021/01/machines/index_files/figure-html/cell-10-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="20" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb7-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Catlab.Theories</span>: id</span>
<span id="cb7-2">E <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> SchGraph[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>E]</span>
<span id="cb7-3"></span>
<span id="cb7-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define the composition pattern via data migration</span></span>
<span id="cb7-5">ocean_pattern <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">SIPortGraph</span>()</span>
<span id="cb7-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">migrate!</span>(ocean_pattern, ocean_graph, </span>
<span id="cb7-7">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Dict</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>InPort <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>E, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>OutPort <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>E, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>Box <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>V),</span>
<span id="cb7-8">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Dict</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>wire <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">id</span>(E), <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>in_port_box <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>tgt, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>out_port_box <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=&gt;</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>src))</span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="1">
<div class="c-set">
<span class="c-set-summary">Main.Notebook.SIPortGraph {Box:3, InPort:4, OutPort:4}</span>

<table class="caption-top table table-sm table-striped small" data-quarto-postprocess="true">
<thead>
<tr class="header headerLastRow">
<th class="rowLabel" data-quarto-table-cell-role="th" style="text-align: right; font-weight: bold;">InPort</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">in_port_box</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">wire</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">1</td>
<td style="text-align: right;">2</td>
<td style="text-align: right;">1</td>
</tr>
<tr class="even">
<td class="rowLabel" style="text-align: right; font-weight: bold;">2</td>
<td style="text-align: right;">1</td>
<td style="text-align: right;">2</td>
</tr>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">3</td>
<td style="text-align: right;">3</td>
<td style="text-align: right;">3</td>
</tr>
<tr class="even">
<td class="rowLabel" style="text-align: right; font-weight: bold;">4</td>
<td style="text-align: right;">2</td>
<td style="text-align: right;">4</td>
</tr>
</tbody>
</table>


<table class="caption-top table table-sm table-striped small" data-quarto-postprocess="true">
<thead>
<tr class="header headerLastRow">
<th class="rowLabel" data-quarto-table-cell-role="th" style="text-align: right; font-weight: bold;">OutPort</th>
<th style="text-align: right;" data-quarto-table-cell-role="th">out_port_box</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">1</td>
<td style="text-align: right;">1</td>
</tr>
<tr class="even">
<td class="rowLabel" style="text-align: right; font-weight: bold;">2</td>
<td style="text-align: right;">2</td>
</tr>
<tr class="odd">
<td class="rowLabel" style="text-align: right; font-weight: bold;">3</td>
<td style="text-align: right;">2</td>
</tr>
<tr class="even">
<td class="rowLabel" style="text-align: right; font-weight: bold;">4</td>
<td style="text-align: right;">3</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
<p>We can now construct a model of the total ocean ecosystem by applying the primitive machines corresponding to little fish, big fish, and shark evolution into the composition pattern. Again, using a standard ODE solver we can compute and graph a trajectory of this ecosystem.</p>
<div id="22" class="cell" data-execution_count="1">
<details open="" class="code-fold">
<summary>Code</summary>
<div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb8-1">α, β, γ, δ, β′, γ′, δ′ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.015</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.015</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.017</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.017</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.35</span></span>
<span id="cb8-2"></span>
<span id="cb8-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dotfish</span>(f, p, t) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [α<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>f[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> β<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>p[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>f[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]</span>
<span id="cb8-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dotFISH</span>(F, p, t) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [γ<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>p[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>F[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> δ<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>F[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> β′<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>p[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>F[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]</span>
<span id="cb8-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dotsharks</span>(s, p, t) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>δ′<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>s[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> γ′<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>s[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>p[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]</span>
<span id="cb8-6"></span>
<span id="cb8-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Define the primitive systems</span></span>
<span id="cb8-8">fish   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Machine</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{Float64}</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, dotfish,   f<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span>f)</span>
<span id="cb8-9">FISH   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Machine</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{Float64}</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, dotFISH,   F<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span>[F[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], F[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]])</span>
<span id="cb8-10">sharks <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Machine</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">{Float64}</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, dotsharks, s<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span>s)</span>
<span id="cb8-11"></span>
<span id="cb8-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Compose</span></span>
<span id="cb8-13">ocean_sys <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">oapply</span>(ocean_pattern, [fish, FISH, sharks])</span></code></pre></div>
</details>
</div>
<div id="24" class="cell" data-execution_count="1">
<div class="cell-output cell-output-display" data-execution_count="1">
<!--?xml version="1.0" encoding="utf-8"?-->
<svg xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" width="672" height="480" viewbox="0 0 2688 1920">
<defs>
  <clippath id="clip230">
    <rect x="0" y="0" width="2688" height="1920"></rect>
  </clippath>
</defs>
<path clip-path="url(#clip230)" d="M0 1920 L2688 1920 L2688 0 L0 0  Z" fill="#ffffff" fill-rule="evenodd" fill-opacity="1"></path>
<defs>
  <clippath id="clip231">
    <rect x="537" y="0" width="1883" height="1883"></rect>
  </clippath>
</defs>
<path clip-path="url(#clip230)" d="M380.396 1592.38 L2640.76 1592.38 L2640.76 127.792 L380.396 127.792  Z" fill="#ffffff" fill-rule="evenodd" fill-opacity="1"></path>
<defs>
  <clippath id="clip232">
    <rect x="380" y="127" width="2261" height="1466"></rect>
  </clippath>
</defs>
<polyline clip-path="url(#clip232)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="380.396,1592.38 380.396,127.792 "></polyline>
<polyline clip-path="url(#clip232)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="832.468,1592.38 832.468,127.792 "></polyline>
<polyline clip-path="url(#clip232)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="1284.54,1592.38 1284.54,127.792 "></polyline>
<polyline clip-path="url(#clip232)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="1736.61,1592.38 1736.61,127.792 "></polyline>
<polyline clip-path="url(#clip232)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="2188.68,1592.38 2188.68,127.792 "></polyline>
<polyline clip-path="url(#clip232)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="2640.76,1592.38 2640.76,127.792 "></polyline>
<polyline clip-path="url(#clip232)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="380.396,1560.47 2640.76,1560.47 "></polyline>
<polyline clip-path="url(#clip232)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="380.396,1236.32 2640.76,1236.32 "></polyline>
<polyline clip-path="url(#clip232)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="380.396,912.167 2640.76,912.167 "></polyline>
<polyline clip-path="url(#clip232)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="380.396,588.015 2640.76,588.015 "></polyline>
<polyline clip-path="url(#clip232)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; stroke-opacity:0.1; fill:none" points="380.396,263.864 2640.76,263.864 "></polyline>
<polyline clip-path="url(#clip230)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="380.396,1592.38 2640.76,1592.38 "></polyline>
<polyline clip-path="url(#clip230)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="380.396,1592.38 380.396,1573.49 "></polyline>
<polyline clip-path="url(#clip230)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="832.468,1592.38 832.468,1573.49 "></polyline>
<polyline clip-path="url(#clip230)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="1284.54,1592.38 1284.54,1573.49 "></polyline>
<polyline clip-path="url(#clip230)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="1736.61,1592.38 1736.61,1573.49 "></polyline>
<polyline clip-path="url(#clip230)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="2188.68,1592.38 2188.68,1573.49 "></polyline>
<polyline clip-path="url(#clip230)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="2640.76,1592.38 2640.76,1573.49 "></polyline>
<path clip-path="url(#clip230)" d="M380.396 1625.61 Q376.785 1625.61 374.956 1629.17 Q373.151 1632.71 373.151 1639.84 Q373.151 1646.95 374.956 1650.51 Q376.785 1654.06 380.396 1654.06 Q384.03 1654.06 385.836 1650.51 Q387.664 1646.95 387.664 1639.84 Q387.664 1632.71 385.836 1629.17 Q384.03 1625.61 380.396 1625.61 M380.396 1621.9 Q386.206 1621.9 389.262 1626.51 Q392.34 1631.09 392.34 1639.84 Q392.34 1648.57 389.262 1653.18 Q386.206 1657.76 380.396 1657.76 Q374.586 1657.76 371.507 1653.18 Q368.452 1648.57 368.452 1639.84 Q368.452 1631.09 371.507 1626.51 Q374.586 1621.9 380.396 1621.9 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M811.241 1653.15 L827.561 1653.15 L827.561 1657.09 L805.616 1657.09 L805.616 1653.15 Q808.278 1650.4 812.862 1645.77 Q817.468 1641.12 818.649 1639.77 Q820.894 1637.25 821.774 1635.51 Q822.676 1633.76 822.676 1632.07 Q822.676 1629.31 820.732 1627.57 Q818.811 1625.84 815.709 1625.84 Q813.51 1625.84 811.056 1626.6 Q808.625 1627.37 805.848 1628.92 L805.848 1624.2 Q808.672 1623.06 811.125 1622.48 Q813.579 1621.9 815.616 1621.9 Q820.986 1621.9 824.181 1624.59 Q827.375 1627.27 827.375 1631.76 Q827.375 1633.89 826.565 1635.82 Q825.778 1637.71 823.672 1640.31 Q823.093 1640.98 819.991 1644.2 Q816.889 1647.39 811.241 1653.15 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M847.375 1625.61 Q843.764 1625.61 841.935 1629.17 Q840.13 1632.71 840.13 1639.84 Q840.13 1646.95 841.935 1650.51 Q843.764 1654.06 847.375 1654.06 Q851.009 1654.06 852.815 1650.51 Q854.644 1646.95 854.644 1639.84 Q854.644 1632.71 852.815 1629.17 Q851.009 1625.61 847.375 1625.61 M847.375 1621.9 Q853.185 1621.9 856.241 1626.51 Q859.32 1631.09 859.32 1639.84 Q859.32 1648.57 856.241 1653.18 Q853.185 1657.76 847.375 1657.76 Q841.565 1657.76 838.486 1653.18 Q835.431 1648.57 835.431 1639.84 Q835.431 1631.09 838.486 1626.51 Q841.565 1621.9 847.375 1621.9 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1272.71 1626.6 L1260.91 1645.05 L1272.71 1645.05 L1272.71 1626.6 M1271.48 1622.53 L1277.36 1622.53 L1277.36 1645.05 L1282.29 1645.05 L1282.29 1648.94 L1277.36 1648.94 L1277.36 1657.09 L1272.71 1657.09 L1272.71 1648.94 L1257.11 1648.94 L1257.11 1644.43 L1271.48 1622.53 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1300.03 1625.61 Q1296.41 1625.61 1294.59 1629.17 Q1292.78 1632.71 1292.78 1639.84 Q1292.78 1646.95 1294.59 1650.51 Q1296.41 1654.06 1300.03 1654.06 Q1303.66 1654.06 1305.47 1650.51 Q1307.29 1646.95 1307.29 1639.84 Q1307.29 1632.71 1305.47 1629.17 Q1303.66 1625.61 1300.03 1625.61 M1300.03 1621.9 Q1305.84 1621.9 1308.89 1626.51 Q1311.97 1631.09 1311.97 1639.84 Q1311.97 1648.57 1308.89 1653.18 Q1305.84 1657.76 1300.03 1657.76 Q1294.22 1657.76 1291.14 1653.18 Q1288.08 1648.57 1288.08 1639.84 Q1288.08 1631.09 1291.14 1626.51 Q1294.22 1621.9 1300.03 1621.9 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1722.02 1637.95 Q1718.87 1637.95 1717.02 1640.1 Q1715.19 1642.25 1715.19 1646 Q1715.19 1649.73 1717.02 1651.9 Q1718.87 1654.06 1722.02 1654.06 Q1725.17 1654.06 1726.99 1651.9 Q1728.85 1649.73 1728.85 1646 Q1728.85 1642.25 1726.99 1640.1 Q1725.17 1637.95 1722.02 1637.95 M1731.3 1623.29 L1731.3 1627.55 Q1729.54 1626.72 1727.73 1626.28 Q1725.95 1625.84 1724.19 1625.84 Q1719.56 1625.84 1717.11 1628.96 Q1714.68 1632.09 1714.33 1638.41 Q1715.7 1636.39 1717.76 1635.33 Q1719.82 1634.24 1722.29 1634.24 Q1727.5 1634.24 1730.51 1637.41 Q1733.54 1640.56 1733.54 1646 Q1733.54 1651.32 1730.4 1654.54 Q1727.25 1657.76 1722.02 1657.76 Q1716.02 1657.76 1712.85 1653.18 Q1709.68 1648.57 1709.68 1639.84 Q1709.68 1631.65 1713.57 1626.79 Q1717.46 1621.9 1724.01 1621.9 Q1725.77 1621.9 1727.55 1622.25 Q1729.36 1622.6 1731.3 1623.29 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1751.6 1625.61 Q1747.99 1625.61 1746.16 1629.17 Q1744.35 1632.71 1744.35 1639.84 Q1744.35 1646.95 1746.16 1650.51 Q1747.99 1654.06 1751.6 1654.06 Q1755.23 1654.06 1757.04 1650.51 Q1758.87 1646.95 1758.87 1639.84 Q1758.87 1632.71 1757.04 1629.17 Q1755.23 1625.61 1751.6 1625.61 M1751.6 1621.9 Q1757.41 1621.9 1760.47 1626.51 Q1763.54 1631.09 1763.54 1639.84 Q1763.54 1648.57 1760.47 1653.18 Q1757.41 1657.76 1751.6 1657.76 Q1745.79 1657.76 1742.71 1653.18 Q1739.66 1648.57 1739.66 1639.84 Q1739.66 1631.09 1742.71 1626.51 Q1745.79 1621.9 1751.6 1621.9 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2173.56 1640.68 Q2170.22 1640.68 2168.3 1642.46 Q2166.4 1644.24 2166.4 1647.37 Q2166.4 1650.49 2168.3 1652.27 Q2170.22 1654.06 2173.56 1654.06 Q2176.89 1654.06 2178.81 1652.27 Q2180.73 1650.47 2180.73 1647.37 Q2180.73 1644.24 2178.81 1642.46 Q2176.91 1640.68 2173.56 1640.68 M2168.88 1638.69 Q2165.87 1637.95 2164.18 1635.89 Q2162.52 1633.82 2162.52 1630.86 Q2162.52 1626.72 2165.45 1624.31 Q2168.42 1621.9 2173.56 1621.9 Q2178.72 1621.9 2181.66 1624.31 Q2184.6 1626.72 2184.6 1630.86 Q2184.6 1633.82 2182.91 1635.89 Q2181.24 1637.95 2178.26 1638.69 Q2181.64 1639.47 2183.51 1641.76 Q2185.41 1644.06 2185.41 1647.37 Q2185.41 1652.39 2182.33 1655.07 Q2179.27 1657.76 2173.56 1657.76 Q2167.84 1657.76 2164.76 1655.07 Q2161.7 1652.39 2161.7 1647.37 Q2161.7 1644.06 2163.6 1641.76 Q2165.5 1639.47 2168.88 1638.69 M2167.17 1631.3 Q2167.17 1633.99 2168.83 1635.49 Q2170.52 1637 2173.56 1637 Q2176.57 1637 2178.26 1635.49 Q2179.97 1633.99 2179.97 1631.3 Q2179.97 1628.62 2178.26 1627.11 Q2176.57 1625.61 2173.56 1625.61 Q2170.52 1625.61 2168.83 1627.11 Q2167.17 1628.62 2167.17 1631.3 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2203.72 1625.61 Q2200.11 1625.61 2198.28 1629.17 Q2196.47 1632.71 2196.47 1639.84 Q2196.47 1646.95 2198.28 1650.51 Q2200.11 1654.06 2203.72 1654.06 Q2207.35 1654.06 2209.16 1650.51 Q2210.99 1646.95 2210.99 1639.84 Q2210.99 1632.71 2209.16 1629.17 Q2207.35 1625.61 2203.72 1625.61 M2203.72 1621.9 Q2209.53 1621.9 2212.58 1626.51 Q2215.66 1631.09 2215.66 1639.84 Q2215.66 1648.57 2212.58 1653.18 Q2209.53 1657.76 2203.72 1657.76 Q2197.91 1657.76 2194.83 1653.18 Q2191.77 1648.57 2191.77 1639.84 Q2191.77 1631.09 2194.83 1626.51 Q2197.91 1621.9 2203.72 1621.9 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2600.36 1653.15 L2608 1653.15 L2608 1626.79 L2599.69 1628.45 L2599.69 1624.2 L2607.96 1622.53 L2612.63 1622.53 L2612.63 1653.15 L2620.27 1653.15 L2620.27 1657.09 L2600.36 1657.09 L2600.36 1653.15 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2639.71 1625.61 Q2636.1 1625.61 2634.27 1629.17 Q2632.47 1632.71 2632.47 1639.84 Q2632.47 1646.95 2634.27 1650.51 Q2636.1 1654.06 2639.71 1654.06 Q2643.35 1654.06 2645.15 1650.51 Q2646.98 1646.95 2646.98 1639.84 Q2646.98 1632.71 2645.15 1629.17 Q2643.35 1625.61 2639.71 1625.61 M2639.71 1621.9 Q2645.52 1621.9 2648.58 1626.51 Q2651.66 1631.09 2651.66 1639.84 Q2651.66 1648.57 2648.58 1653.18 Q2645.52 1657.76 2639.71 1657.76 Q2633.9 1657.76 2630.83 1653.18 Q2627.77 1648.57 2627.77 1639.84 Q2627.77 1631.09 2630.83 1626.51 Q2633.9 1621.9 2639.71 1621.9 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2669.88 1625.61 Q2666.27 1625.61 2664.44 1629.17 Q2662.63 1632.71 2662.63 1639.84 Q2662.63 1646.95 2664.44 1650.51 Q2666.27 1654.06 2669.88 1654.06 Q2673.51 1654.06 2675.32 1650.51 Q2677.14 1646.95 2677.14 1639.84 Q2677.14 1632.71 2675.32 1629.17 Q2673.51 1625.61 2669.88 1625.61 M2669.88 1621.9 Q2675.69 1621.9 2678.74 1626.51 Q2681.82 1631.09 2681.82 1639.84 Q2681.82 1648.57 2678.74 1653.18 Q2675.69 1657.76 2669.88 1657.76 Q2664.07 1657.76 2660.99 1653.18 Q2657.93 1648.57 2657.93 1639.84 Q2657.93 1631.09 2660.99 1626.51 Q2664.07 1621.9 2669.88 1621.9 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1432.45 1694.05 L1472.65 1694.05 L1472.65 1699.46 L1455.78 1699.46 L1455.78 1741.57 L1449.32 1741.57 L1449.32 1699.46 L1432.45 1699.46 L1432.45 1694.05 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1476.6 1705.92 L1482.46 1705.92 L1482.46 1741.57 L1476.6 1741.57 L1476.6 1705.92 M1476.6 1692.04 L1482.46 1692.04 L1482.46 1699.46 L1476.6 1699.46 L1476.6 1692.04 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1522.46 1712.76 Q1524.66 1708.82 1527.72 1706.94 Q1530.77 1705.06 1534.91 1705.06 Q1540.48 1705.06 1543.5 1708.98 Q1546.53 1712.86 1546.53 1720.05 L1546.53 1741.57 L1540.64 1741.57 L1540.64 1720.24 Q1540.64 1715.12 1538.82 1712.64 Q1537.01 1710.15 1533.29 1710.15 Q1528.73 1710.15 1526.09 1713.18 Q1523.45 1716.2 1523.45 1721.42 L1523.45 1741.57 L1517.56 1741.57 L1517.56 1720.24 Q1517.56 1715.09 1515.75 1712.64 Q1513.93 1710.15 1510.15 1710.15 Q1505.66 1710.15 1503.02 1713.21 Q1500.37 1716.23 1500.37 1721.42 L1500.37 1741.57 L1494.49 1741.57 L1494.49 1705.92 L1500.37 1705.92 L1500.37 1711.46 Q1502.38 1708.18 1505.18 1706.62 Q1507.98 1705.06 1511.83 1705.06 Q1515.72 1705.06 1518.42 1707.03 Q1521.16 1709.01 1522.46 1712.76 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1588.7 1722.28 L1588.7 1725.15 L1561.77 1725.15 Q1562.15 1731.19 1565.4 1734.38 Q1568.68 1737.53 1574.5 1737.53 Q1577.88 1737.53 1581.03 1736.7 Q1584.21 1735.87 1587.33 1734.22 L1587.33 1739.75 Q1584.18 1741.09 1580.87 1741.79 Q1577.56 1742.49 1574.15 1742.49 Q1565.62 1742.49 1560.63 1737.53 Q1555.66 1732.56 1555.66 1724.09 Q1555.66 1715.34 1560.37 1710.22 Q1565.11 1705.06 1573.13 1705.06 Q1580.33 1705.06 1584.5 1709.71 Q1588.7 1714.32 1588.7 1722.28 M1582.84 1720.56 Q1582.78 1715.76 1580.14 1712.89 Q1577.53 1710.03 1573.2 1710.03 Q1568.3 1710.03 1565.34 1712.8 Q1562.41 1715.56 1561.96 1720.59 L1582.84 1720.56 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><polyline clip-path="url(#clip230)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="380.396,1592.38 380.396,127.792 "></polyline>
<polyline clip-path="url(#clip230)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="380.396,1560.47 399.294,1560.47 "></polyline>
<polyline clip-path="url(#clip230)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="380.396,1236.32 399.294,1236.32 "></polyline>
<polyline clip-path="url(#clip230)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="380.396,912.167 399.294,912.167 "></polyline>
<polyline clip-path="url(#clip230)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="380.396,588.015 399.294,588.015 "></polyline>
<polyline clip-path="url(#clip230)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="380.396,263.864 399.294,263.864 "></polyline>
<path clip-path="url(#clip230)" d="M328.132 1546.27 Q324.52 1546.27 322.692 1549.83 Q320.886 1553.37 320.886 1560.5 Q320.886 1567.61 322.692 1571.18 Q324.52 1574.72 328.132 1574.72 Q331.766 1574.72 333.571 1571.18 Q335.4 1567.61 335.4 1560.5 Q335.4 1553.37 333.571 1549.83 Q331.766 1546.27 328.132 1546.27 M328.132 1542.56 Q333.942 1542.56 336.997 1547.17 Q340.076 1551.75 340.076 1560.5 Q340.076 1569.23 336.997 1573.84 Q333.942 1578.42 328.132 1578.42 Q322.321 1578.42 319.243 1573.84 Q316.187 1569.23 316.187 1560.5 Q316.187 1551.75 319.243 1547.17 Q322.321 1542.56 328.132 1542.56 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M292.993 1249.66 L309.312 1249.66 L309.312 1253.6 L287.368 1253.6 L287.368 1249.66 Q290.03 1246.91 294.613 1242.28 Q299.22 1237.63 300.4 1236.28 Q302.646 1233.76 303.525 1232.02 Q304.428 1230.26 304.428 1228.57 Q304.428 1225.82 302.484 1224.08 Q300.562 1222.35 297.46 1222.35 Q295.261 1222.35 292.808 1223.11 Q290.377 1223.88 287.599 1225.43 L287.599 1220.7 Q290.423 1219.57 292.877 1218.99 Q295.331 1218.41 297.368 1218.41 Q302.738 1218.41 305.933 1221.1 Q309.127 1223.78 309.127 1228.27 Q309.127 1230.4 308.317 1232.32 Q307.53 1234.22 305.423 1236.82 Q304.845 1237.49 301.743 1240.7 Q298.641 1243.9 292.993 1249.66 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M319.173 1219.04 L337.53 1219.04 L337.53 1222.97 L323.456 1222.97 L323.456 1231.45 Q324.474 1231.1 325.493 1230.94 Q326.511 1230.75 327.53 1230.75 Q333.317 1230.75 336.696 1233.92 Q340.076 1237.09 340.076 1242.51 Q340.076 1248.09 336.604 1251.19 Q333.132 1254.27 326.812 1254.27 Q324.636 1254.27 322.368 1253.9 Q320.122 1253.53 317.715 1252.79 L317.715 1248.09 Q319.798 1249.22 322.02 1249.78 Q324.243 1250.33 326.72 1250.33 Q330.724 1250.33 333.062 1248.23 Q335.4 1246.12 335.4 1242.51 Q335.4 1238.9 333.062 1236.79 Q330.724 1234.69 326.72 1234.69 Q324.845 1234.69 322.97 1235.1 Q321.118 1235.52 319.173 1236.4 L319.173 1219.04 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M288.016 894.887 L306.372 894.887 L306.372 898.822 L292.298 898.822 L292.298 907.294 Q293.317 906.947 294.335 906.785 Q295.354 906.6 296.372 906.6 Q302.159 906.6 305.539 909.771 Q308.919 912.942 308.919 918.359 Q308.919 923.937 305.446 927.039 Q301.974 930.118 295.655 930.118 Q293.479 930.118 291.21 929.748 Q288.965 929.377 286.558 928.636 L286.558 923.937 Q288.641 925.072 290.863 925.627 Q293.085 926.183 295.562 926.183 Q299.567 926.183 301.905 924.076 Q304.243 921.97 304.243 918.359 Q304.243 914.748 301.905 912.641 Q299.567 910.535 295.562 910.535 Q293.687 910.535 291.812 910.951 Q289.96 911.368 288.016 912.248 L288.016 894.887 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M328.132 897.965 Q324.52 897.965 322.692 901.53 Q320.886 905.072 320.886 912.201 Q320.886 919.308 322.692 922.873 Q324.52 926.414 328.132 926.414 Q331.766 926.414 333.571 922.873 Q335.4 919.308 335.4 912.201 Q335.4 905.072 333.571 901.53 Q331.766 897.965 328.132 897.965 M328.132 894.262 Q333.942 894.262 336.997 898.868 Q340.076 903.451 340.076 912.201 Q340.076 920.928 336.997 925.535 Q333.942 930.118 328.132 930.118 Q322.321 930.118 319.243 925.535 Q316.187 920.928 316.187 912.201 Q316.187 903.451 319.243 898.868 Q322.321 894.262 328.132 894.262 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M287.785 570.735 L310.007 570.735 L310.007 572.726 L297.46 605.295 L292.576 605.295 L304.382 574.67 L287.785 574.67 L287.785 570.735 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M319.173 570.735 L337.53 570.735 L337.53 574.67 L323.456 574.67 L323.456 583.143 Q324.474 582.795 325.493 582.633 Q326.511 582.448 327.53 582.448 Q333.317 582.448 336.696 585.619 Q340.076 588.791 340.076 594.207 Q340.076 599.786 336.604 602.888 Q333.132 605.967 326.812 605.967 Q324.636 605.967 322.368 605.596 Q320.122 605.226 317.715 604.485 L317.715 599.786 Q319.798 600.92 322.02 601.476 Q324.243 602.031 326.72 602.031 Q330.724 602.031 333.062 599.925 Q335.4 597.818 335.4 594.207 Q335.4 590.596 333.062 588.49 Q330.724 586.383 326.72 586.383 Q324.845 586.383 322.97 586.8 Q321.118 587.217 319.173 588.096 L319.173 570.735 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M258.618 277.209 L266.257 277.209 L266.257 250.843 L257.947 252.51 L257.947 248.251 L266.211 246.584 L270.886 246.584 L270.886 277.209 L278.525 277.209 L278.525 281.144 L258.618 281.144 L258.618 277.209 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M297.97 249.663 Q294.359 249.663 292.53 253.227 Q290.724 256.769 290.724 263.899 Q290.724 271.005 292.53 274.57 Q294.359 278.112 297.97 278.112 Q301.604 278.112 303.409 274.57 Q305.238 271.005 305.238 263.899 Q305.238 256.769 303.409 253.227 Q301.604 249.663 297.97 249.663 M297.97 245.959 Q303.78 245.959 306.835 250.565 Q309.914 255.149 309.914 263.899 Q309.914 272.626 306.835 277.232 Q303.78 281.815 297.97 281.815 Q292.16 281.815 289.081 277.232 Q286.025 272.626 286.025 263.899 Q286.025 255.149 289.081 250.565 Q292.16 245.959 297.97 245.959 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M328.132 249.663 Q324.52 249.663 322.692 253.227 Q320.886 256.769 320.886 263.899 Q320.886 271.005 322.692 274.57 Q324.52 278.112 328.132 278.112 Q331.766 278.112 333.571 274.57 Q335.4 271.005 335.4 263.899 Q335.4 256.769 333.571 253.227 Q331.766 249.663 328.132 249.663 M328.132 245.959 Q333.942 245.959 336.997 250.565 Q340.076 255.149 340.076 263.899 Q340.076 272.626 336.997 277.232 Q333.942 281.815 328.132 281.815 Q322.321 281.815 319.243 277.232 Q316.187 272.626 316.187 263.899 Q316.187 255.149 319.243 250.565 Q322.321 245.959 328.132 245.959 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M161.134 1093.52 L178.99 1093.52 L178.99 1085.43 Q178.99 1080.95 176.667 1078.5 Q174.343 1076.05 170.046 1076.05 Q165.781 1076.05 163.458 1078.5 Q161.134 1080.95 161.134 1085.43 L161.134 1093.52 M155.851 1099.95 L155.851 1085.43 Q155.851 1077.45 159.479 1073.37 Q163.076 1069.27 170.046 1069.27 Q177.08 1069.27 180.677 1073.37 Q184.274 1077.45 184.274 1085.43 L184.274 1093.52 L203.371 1093.52 L203.371 1099.95 L155.851 1099.95 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M171.829 1049.4 Q171.829 1054.12 175.521 1056.85 Q179.181 1059.59 185.579 1059.59 Q191.976 1059.59 195.668 1056.88 Q199.329 1054.15 199.329 1049.4 Q199.329 1044.73 195.636 1041.99 Q191.944 1039.25 185.579 1039.25 Q179.245 1039.25 175.553 1041.99 Q171.829 1044.73 171.829 1049.4 M166.863 1049.4 Q166.863 1041.77 171.829 1037.41 Q176.794 1033.04 185.579 1033.04 Q194.331 1033.04 199.329 1037.41 Q204.294 1041.77 204.294 1049.4 Q204.294 1057.08 199.329 1061.44 Q194.331 1065.76 185.579 1065.76 Q176.794 1065.76 171.829 1061.44 Q166.863 1057.08 166.863 1049.4 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M198.024 1017.67 L216.93 1017.67 L216.93 1023.56 L167.723 1023.56 L167.723 1017.67 L173.134 1017.67 Q169.951 1015.83 168.423 1013.02 Q166.863 1010.19 166.863 1006.28 Q166.863 999.784 172.02 995.742 Q177.176 991.668 185.579 991.668 Q193.981 991.668 199.138 995.742 Q204.294 999.784 204.294 1006.28 Q204.294 1010.19 202.766 1013.02 Q201.206 1015.83 198.024 1017.67 M185.579 997.747 Q179.117 997.747 175.457 1000.42 Q171.765 1003.06 171.765 1007.71 Q171.765 1012.36 175.457 1015.03 Q179.117 1017.67 185.579 1017.67 Q192.04 1017.67 195.732 1015.03 Q199.392 1012.36 199.392 1007.71 Q199.392 1003.06 195.732 1000.42 Q192.04 997.747 185.579 997.747 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M189.303 982.565 L167.723 982.565 L167.723 976.708 L189.08 976.708 Q194.14 976.708 196.687 974.735 Q199.201 972.761 199.201 968.815 Q199.201 964.072 196.177 961.335 Q193.154 958.566 187.934 958.566 L167.723 958.566 L167.723 952.709 L203.371 952.709 L203.371 958.566 L197.896 958.566 Q201.143 960.698 202.734 963.531 Q204.294 966.332 204.294 970.056 Q204.294 976.199 200.474 979.382 Q196.655 982.565 189.303 982.565 M166.863 967.828 L166.863 967.828 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M153.846 940.646 L153.846 934.79 L203.371 934.79 L203.371 940.646 L153.846 940.646 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M185.451 906.335 Q185.451 913.433 187.075 916.17 Q188.698 918.908 192.613 918.908 Q195.732 918.908 197.578 916.871 Q199.392 914.802 199.392 911.269 Q199.392 906.399 195.955 903.471 Q192.485 900.511 186.756 900.511 L185.451 900.511 L185.451 906.335 M183.032 894.654 L203.371 894.654 L203.371 900.511 L197.96 900.511 Q201.206 902.516 202.766 905.508 Q204.294 908.5 204.294 912.828 Q204.294 918.303 201.238 921.549 Q198.151 924.764 192.995 924.764 Q186.979 924.764 183.923 920.754 Q180.868 916.711 180.868 908.722 L180.868 900.511 L180.295 900.511 Q176.253 900.511 174.057 903.184 Q171.829 905.826 171.829 910.632 Q171.829 913.688 172.561 916.584 Q173.293 919.48 174.757 922.154 L169.346 922.154 Q168.105 918.939 167.5 915.916 Q166.863 912.892 166.863 910.027 Q166.863 902.293 170.874 898.474 Q174.884 894.654 183.032 894.654 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M157.601 876.798 L167.723 876.798 L167.723 864.735 L172.274 864.735 L172.274 876.798 L191.626 876.798 Q195.987 876.798 197.228 875.621 Q198.469 874.411 198.469 870.751 L198.469 864.735 L203.371 864.735 L203.371 870.751 Q203.371 877.53 200.856 880.109 Q198.31 882.687 191.626 882.687 L172.274 882.687 L172.274 886.984 L167.723 886.984 L167.723 882.687 L157.601 882.687 L157.601 876.798 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M167.723 857.033 L167.723 851.176 L203.371 851.176 L203.371 857.033 L167.723 857.033 M153.846 857.033 L153.846 851.176 L161.262 851.176 L161.262 857.033 L153.846 857.033 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M171.829 825.109 Q171.829 829.819 175.521 832.557 Q179.181 835.294 185.579 835.294 Q191.976 835.294 195.668 832.589 Q199.329 829.851 199.329 825.109 Q199.329 820.43 195.636 817.693 Q191.944 814.956 185.579 814.956 Q179.245 814.956 175.553 817.693 Q171.829 820.43 171.829 825.109 M166.863 825.109 Q166.863 817.47 171.829 813.109 Q176.794 808.749 185.579 808.749 Q194.331 808.749 199.329 813.109 Q204.294 817.47 204.294 825.109 Q204.294 832.78 199.329 837.14 Q194.331 841.469 185.579 841.469 Q176.794 841.469 171.829 837.14 Q166.863 832.78 166.863 825.109 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M181.855 769.409 L203.371 769.409 L203.371 775.265 L182.046 775.265 Q176.985 775.265 174.47 777.239 Q171.956 779.212 171.956 783.159 Q171.956 787.901 174.98 790.639 Q178.003 793.376 183.223 793.376 L203.371 793.376 L203.371 799.264 L167.723 799.264 L167.723 793.376 L173.261 793.376 Q170.046 791.275 168.455 788.442 Q166.863 785.578 166.863 781.854 Q166.863 775.711 170.683 772.56 Q174.47 769.409 181.855 769.409 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M168.773 714.282 L174.311 714.282 Q173.038 716.765 172.402 719.438 Q171.765 722.112 171.765 724.976 Q171.765 729.337 173.102 731.533 Q174.439 733.697 177.112 733.697 Q179.149 733.697 180.327 732.138 Q181.473 730.578 182.523 725.867 L182.969 723.862 Q184.305 717.624 186.756 715.014 Q189.175 712.372 193.536 712.372 Q198.501 712.372 201.397 716.319 Q204.294 720.234 204.294 727.109 Q204.294 729.973 203.721 733.093 Q203.18 736.18 202.066 739.617 L196.018 739.617 Q197.705 736.371 198.565 733.22 Q199.392 730.069 199.392 726.981 Q199.392 722.844 197.992 720.616 Q196.559 718.388 193.981 718.388 Q191.594 718.388 190.321 720.011 Q189.048 721.602 187.87 727.045 L187.393 729.082 Q186.247 734.525 183.892 736.944 Q181.505 739.363 177.367 739.363 Q172.338 739.363 169.601 735.798 Q166.863 732.233 166.863 725.677 Q166.863 722.43 167.341 719.565 Q167.818 716.701 168.773 714.282 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M167.723 703.046 L167.723 697.19 L203.371 697.19 L203.371 703.046 L167.723 703.046 M153.846 703.046 L153.846 697.19 L161.262 697.19 L161.262 703.046 L153.846 703.046 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M167.723 687.482 L167.723 659.664 L173.07 659.664 L198.692 681.689 L198.692 659.664 L203.371 659.664 L203.371 688.278 L198.024 688.278 L172.402 666.253 L172.402 687.482 L167.723 687.482 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M184.083 620.229 L186.947 620.229 L186.947 647.156 Q192.995 646.774 196.177 643.527 Q199.329 640.249 199.329 634.424 Q199.329 631.05 198.501 627.899 Q197.673 624.716 196.018 621.597 L201.557 621.597 Q202.893 624.748 203.594 628.058 Q204.294 631.369 204.294 634.774 Q204.294 643.304 199.329 648.301 Q194.363 653.267 185.897 653.267 Q177.144 653.267 172.02 648.556 Q166.863 643.814 166.863 635.793 Q166.863 628.599 171.51 624.43 Q176.126 620.229 184.083 620.229 M182.364 626.085 Q177.558 626.149 174.693 628.79 Q171.829 631.4 171.829 635.729 Q171.829 640.631 174.598 643.591 Q177.367 646.519 182.396 646.965 L182.364 626.085 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M880.478 12.096 L888.661 12.096 L888.661 65.6895 L918.111 65.6895 L918.111 72.576 L880.478 72.576 L880.478 12.096 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M942.497 32.4315 Q936.502 32.4315 933.018 37.1306 Q929.534 41.7891 929.534 49.9314 Q929.534 58.0738 932.978 62.7728 Q936.462 67.4314 942.497 67.4314 Q948.452 67.4314 951.936 62.7323 Q955.42 58.0333 955.42 49.9314 Q955.42 41.8701 951.936 37.1711 Q948.452 32.4315 942.497 32.4315 M942.497 26.1121 Q952.22 26.1121 957.769 32.4315 Q963.319 38.7509 963.319 49.9314 Q963.319 61.0714 957.769 67.4314 Q952.22 73.7508 942.497 73.7508 Q932.735 73.7508 927.185 67.4314 Q921.676 61.0714 921.676 49.9314 Q921.676 38.7509 927.185 32.4315 Q932.735 26.1121 942.497 26.1121 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M983.047 14.324 L983.047 27.2059 L998.4 27.2059 L998.4 32.9987 L983.047 32.9987 L983.047 57.6282 Q983.047 63.1779 984.546 64.7578 Q986.085 66.3376 990.744 66.3376 L998.4 66.3376 L998.4 72.576 L990.744 72.576 Q982.115 72.576 978.834 69.3758 Q975.553 66.1351 975.553 57.6282 L975.553 32.9987 L970.084 32.9987 L970.084 27.2059 L975.553 27.2059 L975.553 14.324 L983.047 14.324 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1007.92 9.54393 L1015.41 9.54393 L1015.41 46.7717 L1037.65 27.2059 L1047.17 27.2059 L1023.11 48.4326 L1048.19 72.576 L1038.46 72.576 L1015.41 50.4176 L1015.41 72.576 L1007.92 72.576 L1007.92 9.54393 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1075.41 49.7694 Q1066.37 49.7694 1062.89 51.8354 Q1059.41 53.9013 1059.41 58.8839 Q1059.41 62.8538 1062 65.2034 Q1064.63 67.5124 1069.13 67.5124 Q1075.33 67.5124 1079.05 63.1374 Q1082.82 58.7219 1082.82 51.4303 L1082.82 49.7694 L1075.41 49.7694 M1090.27 46.6907 L1090.27 72.576 L1082.82 72.576 L1082.82 65.6895 Q1080.27 69.8214 1076.46 71.8063 Q1072.65 73.7508 1067.14 73.7508 Q1060.18 73.7508 1056.04 69.8619 Q1051.95 65.9325 1051.95 59.3701 Q1051.95 51.7138 1057.06 47.825 Q1062.2 43.9361 1072.37 43.9361 L1082.82 43.9361 L1082.82 43.2069 Q1082.82 38.0623 1079.42 35.2672 Q1076.06 32.4315 1069.94 32.4315 Q1066.05 32.4315 1062.36 33.3632 Q1058.68 34.295 1055.27 36.1584 L1055.27 29.2718 Q1059.37 27.692 1063.21 26.9223 Q1067.06 26.1121 1070.71 26.1121 Q1080.55 26.1121 1085.41 31.2163 Q1090.27 36.3204 1090.27 46.6907 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1101.86 46.5287 L1123.69 46.5287 L1123.69 53.1722 L1101.86 53.1722 L1101.86 46.5287 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1146.62 72.576 L1123.53 12.096 L1132.08 12.096 L1151.24 63.0159 L1170.44 12.096 L1178.95 12.096 L1155.9 72.576 L1146.62 72.576 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1198.6 32.4315 Q1192.6 32.4315 1189.12 37.1306 Q1185.63 41.7891 1185.63 49.9314 Q1185.63 58.0738 1189.08 62.7728 Q1192.56 67.4314 1198.6 67.4314 Q1204.55 67.4314 1208.03 62.7323 Q1211.52 58.0333 1211.52 49.9314 Q1211.52 41.8701 1208.03 37.1711 Q1204.55 32.4315 1198.6 32.4315 M1198.6 26.1121 Q1208.32 26.1121 1213.87 32.4315 Q1219.42 38.7509 1219.42 49.9314 Q1219.42 61.0714 1213.87 67.4314 Q1208.32 73.7508 1198.6 73.7508 Q1188.83 73.7508 1183.28 67.4314 Q1177.77 61.0714 1177.77 49.9314 Q1177.77 38.7509 1183.28 32.4315 Q1188.83 26.1121 1198.6 26.1121 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1231.77 9.54393 L1239.23 9.54393 L1239.23 72.576 L1231.77 72.576 L1231.77 9.54393 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1262.19 14.324 L1262.19 27.2059 L1277.55 27.2059 L1277.55 32.9987 L1262.19 32.9987 L1262.19 57.6282 Q1262.19 63.1779 1263.69 64.7578 Q1265.23 66.3376 1269.89 66.3376 L1277.55 66.3376 L1277.55 72.576 L1269.89 72.576 Q1261.26 72.576 1257.98 69.3758 Q1254.7 66.1351 1254.7 57.6282 L1254.7 32.9987 L1249.23 32.9987 L1249.23 27.2059 L1254.7 27.2059 L1254.7 14.324 L1262.19 14.324 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1326.16 48.0275 L1326.16 51.6733 L1291.89 51.6733 Q1292.37 59.3701 1296.51 63.421 Q1300.68 67.4314 1308.09 67.4314 Q1312.39 67.4314 1316.4 66.3781 Q1320.45 65.3249 1324.42 63.2184 L1324.42 70.267 Q1320.41 71.9684 1316.19 72.8596 Q1311.98 73.7508 1307.65 73.7508 Q1296.79 73.7508 1290.43 67.4314 Q1284.11 61.1119 1284.11 50.3365 Q1284.11 39.1965 1290.11 32.6746 Q1296.14 26.1121 1306.35 26.1121 Q1315.5 26.1121 1320.81 32.0264 Q1326.16 37.9003 1326.16 48.0275 M1318.7 45.84 Q1318.62 39.7232 1315.26 36.0774 Q1311.94 32.4315 1306.43 32.4315 Q1300.19 32.4315 1296.42 35.9558 Q1292.7 39.4801 1292.13 45.8805 L1318.7 45.84 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1364.68 34.1734 Q1363.43 33.4443 1361.93 33.1202 Q1360.47 32.7556 1358.69 32.7556 Q1352.37 32.7556 1348.97 36.8875 Q1345.6 40.9789 1345.6 48.6757 L1345.6 72.576 L1338.11 72.576 L1338.11 27.2059 L1345.6 27.2059 L1345.6 34.2544 Q1347.95 30.1225 1351.72 28.1376 Q1355.49 26.1121 1360.87 26.1121 Q1361.64 26.1121 1362.58 26.2337 Q1363.51 26.3147 1364.64 26.5172 L1364.68 34.1734 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1397.33 34.1734 Q1396.08 33.4443 1394.58 33.1202 Q1393.12 32.7556 1391.34 32.7556 Q1385.02 32.7556 1381.62 36.8875 Q1378.25 40.9789 1378.25 48.6757 L1378.25 72.576 L1370.76 72.576 L1370.76 27.2059 L1378.25 27.2059 L1378.25 34.2544 Q1380.6 30.1225 1384.37 28.1376 Q1388.14 26.1121 1393.53 26.1121 Q1394.29 26.1121 1395.23 26.2337 Q1396.16 26.3147 1397.29 26.5172 L1397.33 34.1734 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1425.77 49.7694 Q1416.74 49.7694 1413.25 51.8354 Q1409.77 53.9013 1409.77 58.8839 Q1409.77 62.8538 1412.36 65.2034 Q1414.99 67.5124 1419.49 67.5124 Q1425.69 67.5124 1429.42 63.1374 Q1433.18 58.7219 1433.18 51.4303 L1433.18 49.7694 L1425.77 49.7694 M1440.64 46.6907 L1440.64 72.576 L1433.18 72.576 L1433.18 65.6895 Q1430.63 69.8214 1426.82 71.8063 Q1423.02 73.7508 1417.51 73.7508 Q1410.54 73.7508 1406.41 69.8619 Q1402.32 65.9325 1402.32 59.3701 Q1402.32 51.7138 1407.42 47.825 Q1412.56 43.9361 1422.73 43.9361 L1433.18 43.9361 L1433.18 43.2069 Q1433.18 38.0623 1429.78 35.2672 Q1426.42 32.4315 1420.3 32.4315 Q1416.41 32.4315 1412.73 33.3632 Q1409.04 34.295 1405.64 36.1584 L1405.64 29.2718 Q1409.73 27.692 1413.58 26.9223 Q1417.43 26.1121 1421.07 26.1121 Q1430.91 26.1121 1435.78 31.2163 Q1440.64 36.3204 1440.64 46.6907 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1508.21 39.9662 Q1514.08 41.222 1517.36 45.1919 Q1520.68 49.1618 1520.68 54.9951 Q1520.68 63.9476 1514.53 68.8492 Q1508.37 73.7508 1497.03 73.7508 Q1493.22 73.7508 1489.17 72.9811 Q1485.16 72.2519 1480.86 70.7531 L1480.86 62.8538 Q1484.27 64.8388 1488.32 65.8515 Q1492.37 66.8642 1496.78 66.8642 Q1504.48 66.8642 1508.49 63.826 Q1512.54 60.7879 1512.54 54.9951 Q1512.54 49.6479 1508.77 46.6502 Q1505.05 43.612 1498.36 43.612 L1491.31 43.612 L1491.31 36.8875 L1498.69 36.8875 Q1504.72 36.8875 1507.92 34.4975 Q1511.12 32.067 1511.12 27.5299 Q1511.12 22.8714 1507.8 20.4004 Q1504.52 17.8888 1498.36 17.8888 Q1495 17.8888 1491.15 18.618 Q1487.3 19.3471 1482.69 20.8865 L1482.69 13.5948 Q1487.34 12.2985 1491.39 11.6504 Q1495.49 11.0023 1499.09 11.0023 Q1508.41 11.0023 1513.84 15.2557 Q1519.27 19.4686 1519.27 26.6793 Q1519.27 31.7024 1516.39 35.1862 Q1513.51 38.6294 1508.21 39.9662 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1598.1 14.0809 L1598.1 22.0612 Q1593.44 19.8332 1589.31 18.7395 Q1585.17 17.6457 1581.32 17.6457 Q1574.64 17.6457 1571 20.2383 Q1567.39 22.8309 1567.39 27.611 Q1567.39 31.6214 1569.78 33.6873 Q1572.21 35.7128 1578.93 36.9686 L1583.88 37.9813 Q1593.03 39.7232 1597.37 44.1387 Q1601.74 48.5136 1601.74 55.8863 Q1601.74 64.6767 1595.83 69.2137 Q1589.95 73.7508 1578.57 73.7508 Q1574.28 73.7508 1569.42 72.7785 Q1564.59 71.8063 1559.41 69.9024 L1559.41 61.4765 Q1564.39 64.2716 1569.17 65.6895 Q1573.95 67.1073 1578.57 67.1073 Q1585.58 67.1073 1589.39 64.3527 Q1593.19 61.598 1593.19 56.4939 Q1593.19 52.0379 1590.44 49.5264 Q1587.73 47.0148 1581.49 45.759 L1576.5 44.7868 Q1567.35 42.9639 1563.26 39.075 Q1559.17 35.1862 1559.17 28.2591 Q1559.17 20.2383 1564.8 15.6203 Q1570.47 11.0023 1580.39 11.0023 Q1584.65 11.0023 1589.06 11.7719 Q1593.48 12.5416 1598.1 14.0809 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1621.39 65.7705 L1621.39 89.8329 L1613.89 89.8329 L1613.89 27.2059 L1621.39 27.2059 L1621.39 34.0924 Q1623.74 30.0415 1627.3 28.0971 Q1630.91 26.1121 1635.89 26.1121 Q1644.15 26.1121 1649.3 32.6746 Q1654.48 39.2371 1654.48 49.9314 Q1654.48 60.6258 1649.3 67.1883 Q1644.15 73.7508 1635.89 73.7508 Q1630.91 73.7508 1627.3 71.8063 Q1623.74 69.8214 1621.39 65.7705 M1646.75 49.9314 Q1646.75 41.7081 1643.34 37.0496 Q1639.98 32.3505 1634.07 32.3505 Q1628.15 32.3505 1624.75 37.0496 Q1621.39 41.7081 1621.39 49.9314 Q1621.39 58.1548 1624.75 62.8538 Q1628.15 67.5124 1634.07 67.5124 Q1639.98 67.5124 1643.34 62.8538 Q1646.75 58.1548 1646.75 49.9314 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1705.65 48.0275 L1705.65 51.6733 L1671.38 51.6733 Q1671.86 59.3701 1675.99 63.421 Q1680.17 67.4314 1687.58 67.4314 Q1691.87 67.4314 1695.88 66.3781 Q1699.94 65.3249 1703.91 63.2184 L1703.91 70.267 Q1699.89 71.9684 1695.68 72.8596 Q1691.47 73.7508 1687.13 73.7508 Q1676.28 73.7508 1669.92 67.4314 Q1663.6 61.1119 1663.6 50.3365 Q1663.6 39.1965 1669.59 32.6746 Q1675.63 26.1121 1685.84 26.1121 Q1694.99 26.1121 1700.3 32.0264 Q1705.65 37.9003 1705.65 48.0275 M1698.19 45.84 Q1698.11 39.7232 1694.75 36.0774 Q1691.43 32.4315 1685.92 32.4315 Q1679.68 32.4315 1675.91 35.9558 Q1672.19 39.4801 1671.62 45.8805 L1698.19 45.84 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1750.53 28.9478 L1750.53 35.9153 Q1747.37 34.1734 1744.17 33.3227 Q1741.01 32.4315 1737.77 32.4315 Q1730.52 32.4315 1726.51 37.0496 Q1722.5 41.6271 1722.5 49.9314 Q1722.5 58.2358 1726.51 62.8538 Q1730.52 67.4314 1737.77 67.4314 Q1741.01 67.4314 1744.17 66.5807 Q1747.37 65.6895 1750.53 63.9476 L1750.53 70.8341 Q1747.41 72.2924 1744.05 73.0216 Q1740.73 73.7508 1736.96 73.7508 Q1726.71 73.7508 1720.68 67.3098 Q1714.64 60.8689 1714.64 49.9314 Q1714.64 38.832 1720.72 32.472 Q1726.83 26.1121 1737.45 26.1121 Q1740.89 26.1121 1744.17 26.8413 Q1747.45 27.5299 1750.53 28.9478 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1763.49 27.2059 L1770.95 27.2059 L1770.95 72.576 L1763.49 72.576 L1763.49 27.2059 M1763.49 9.54393 L1770.95 9.54393 L1770.95 18.9825 L1763.49 18.9825 L1763.49 9.54393 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1825.35 48.0275 L1825.35 51.6733 L1791.08 51.6733 Q1791.57 59.3701 1795.7 63.421 Q1799.87 67.4314 1807.28 67.4314 Q1811.58 67.4314 1815.59 66.3781 Q1819.64 65.3249 1823.61 63.2184 L1823.61 70.267 Q1819.6 71.9684 1815.39 72.8596 Q1811.17 73.7508 1806.84 73.7508 Q1795.98 73.7508 1789.62 67.4314 Q1783.3 61.1119 1783.3 50.3365 Q1783.3 39.1965 1789.3 32.6746 Q1795.33 26.1121 1805.54 26.1121 Q1814.7 26.1121 1820 32.0264 Q1825.35 37.9003 1825.35 48.0275 M1817.9 45.84 Q1817.82 39.7232 1814.45 36.0774 Q1811.13 32.4315 1805.62 32.4315 Q1799.39 32.4315 1795.62 35.9558 Q1791.89 39.4801 1791.32 45.8805 L1817.9 45.84 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1866.51 28.5427 L1866.51 35.5912 Q1863.35 33.9709 1859.95 33.1607 Q1856.54 32.3505 1852.9 32.3505 Q1847.35 32.3505 1844.55 34.0519 Q1841.8 35.7533 1841.8 39.156 Q1841.8 41.7486 1843.78 43.2475 Q1845.77 44.7058 1851.76 46.0426 L1854.32 46.6097 Q1862.26 48.3111 1865.58 51.4303 Q1868.94 54.509 1868.94 60.0587 Q1868.94 66.3781 1863.92 70.0644 Q1858.93 73.7508 1850.18 73.7508 Q1846.54 73.7508 1842.57 73.0216 Q1838.64 72.3329 1834.26 70.9151 L1834.26 63.2184 Q1838.4 65.3654 1842.41 66.4591 Q1846.42 67.5124 1850.35 67.5124 Q1855.61 67.5124 1858.45 65.73 Q1861.28 63.9071 1861.28 60.6258 Q1861.28 57.5877 1859.22 55.9673 Q1857.19 54.3469 1850.26 52.8481 L1847.67 52.2405 Q1840.74 50.7821 1837.67 47.7845 Q1834.59 44.7463 1834.59 39.4801 Q1834.59 33.0797 1839.12 29.5959 Q1843.66 26.1121 1852.01 26.1121 Q1856.14 26.1121 1859.78 26.7198 Q1863.43 27.3274 1866.51 28.5427 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1907.5 12.096 L1919.7 12.096 L1935.13 53.2532 L1950.65 12.096 L1962.84 12.096 L1962.84 72.576 L1954.86 72.576 L1954.86 19.4686 L1939.26 60.9499 L1931.04 60.9499 L1915.44 19.4686 L1915.44 72.576 L1907.5 72.576 L1907.5 12.096 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M1996.34 32.4315 Q1990.34 32.4315 1986.86 37.1306 Q1983.38 41.7891 1983.38 49.9314 Q1983.38 58.0738 1986.82 62.7728 Q1990.3 67.4314 1996.34 67.4314 Q2002.29 67.4314 2005.78 62.7323 Q2009.26 58.0333 2009.26 49.9314 Q2009.26 41.8701 2005.78 37.1711 Q2002.29 32.4315 1996.34 32.4315 M1996.34 26.1121 Q2006.06 26.1121 2011.61 32.4315 Q2017.16 38.7509 2017.16 49.9314 Q2017.16 61.0714 2011.61 67.4314 Q2006.06 73.7508 1996.34 73.7508 Q1986.58 73.7508 1981.03 67.4314 Q1975.52 61.0714 1975.52 49.9314 Q1975.52 38.7509 1981.03 32.4315 Q1986.58 26.1121 1996.34 26.1121 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2059.37 34.0924 L2059.37 9.54393 L2066.83 9.54393 L2066.83 72.576 L2059.37 72.576 L2059.37 65.7705 Q2057.02 69.8214 2053.42 71.8063 Q2049.85 73.7508 2044.83 73.7508 Q2036.61 73.7508 2031.42 67.1883 Q2026.28 60.6258 2026.28 49.9314 Q2026.28 39.2371 2031.42 32.6746 Q2036.61 26.1121 2044.83 26.1121 Q2049.85 26.1121 2053.42 28.0971 Q2057.02 30.0415 2059.37 34.0924 M2033.97 49.9314 Q2033.97 58.1548 2037.34 62.8538 Q2040.74 67.5124 2046.65 67.5124 Q2052.57 67.5124 2055.97 62.8538 Q2059.37 58.1548 2059.37 49.9314 Q2059.37 41.7081 2055.97 37.0496 Q2052.57 32.3505 2046.65 32.3505 Q2040.74 32.3505 2037.34 37.0496 Q2033.97 41.7081 2033.97 49.9314 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2120.99 48.0275 L2120.99 51.6733 L2086.72 51.6733 Q2087.2 59.3701 2091.33 63.421 Q2095.51 67.4314 2102.92 67.4314 Q2107.21 67.4314 2111.22 66.3781 Q2115.27 65.3249 2119.24 63.2184 L2119.24 70.267 Q2115.23 71.9684 2111.02 72.8596 Q2106.81 73.7508 2102.47 73.7508 Q2091.62 73.7508 2085.26 67.4314 Q2078.94 61.1119 2078.94 50.3365 Q2078.94 39.1965 2084.93 32.6746 Q2090.97 26.1121 2101.18 26.1121 Q2110.33 26.1121 2115.64 32.0264 Q2120.99 37.9003 2120.99 48.0275 M2113.53 45.84 Q2113.45 39.7232 2110.09 36.0774 Q2106.77 32.4315 2101.26 32.4315 Q2095.02 32.4315 2091.25 35.9558 Q2087.53 39.4801 2086.96 45.8805 L2113.53 45.84 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2133.22 9.54393 L2140.67 9.54393 L2140.67 72.576 L2133.22 72.576 L2133.22 9.54393 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><polyline clip-path="url(#clip232)" style="stroke:#009af9; stroke-linecap:round; stroke-linejoin:round; stroke-width:8; stroke-opacity:1; fill:none" points="380.396,263.864 382.659,245.034 384.921,227.64 387.184,211.938 389.446,198.209 391.709,186.752 393.972,177.882 396.234,171.935 398.497,169.243 400.76,170.135 403.022,174.929 405.285,183.917 407.547,197.34 409.81,215.363 412.073,238.074 414.335,265.477 416.598,297.439 418.861,333.702 421.123,373.898 423.386,417.544 425.648,464.049 427.911,512.767 430.174,562.938 432.436,613.814 434.699,664.698 436.961,714.954 439.224,763.998 441.487,811.306 443.749,856.474 446.012,899.222 448.275,939.348 450.537,976.727 452.8,1011.31 455.062,1043.14 457.325,1072.27 459.588,1098.82 461.85,1122.93 464.113,1144.74 466.376,1164.4 468.638,1182.06 470.901,1197.87 473.163,1211.98 475.426,1224.53 477.689,1235.64 479.951,1245.45 482.214,1254.07 484.477,1261.58 486.739,1268.1 489.002,1273.69 491.264,1278.43 493.527,1282.4 495.79,1285.64 498.052,1288.21 500.315,1290.17 502.578,1291.55 504.84,1292.38 507.103,1292.72 509.365,1292.58 511.628,1291.99 513.891,1290.98 516.153,1289.57 518.416,1287.77 520.679,1285.6 522.941,1283.08 525.204,1280.21 527.466,1277 529.729,1273.47 531.992,1269.63 534.254,1265.48 536.517,1261.02 538.779,1256.26 541.042,1251.21 543.305,1245.87 545.567,1240.23 547.83,1234.31 550.093,1228.09 552.355,1221.59 554.618,1214.79 556.88,1207.7 559.143,1200.32 561.406,1192.65 563.668,1184.68 565.931,1176.41 568.194,1167.83 570.456,1158.95 572.719,1149.76 574.981,1140.25 577.244,1130.43 579.507,1120.28 581.769,1109.8 584.032,1098.99 586.295,1087.85 588.557,1076.36 590.82,1064.52 593.082,1052.33 595.345,1039.78 597.608,1026.87 599.87,1013.58 602.133,999.919 604.396,985.875 606.658,971.445 608.921,956.621 611.183,941.4 613.446,925.777 615.709,909.749 617.971,893.311 620.234,876.461 622.497,859.197 624.759,841.516 627.022,823.417 629.284,804.899 631.547,785.978 633.81,766.658 636.072,746.93 638.335,726.792 640.598,706.245 642.86,685.297 645.123,663.961 647.385,642.256 649.648,620.204 651.911,597.834 654.173,575.18 656.436,552.281 658.698,529.182 660.961,505.933 663.224,482.588 665.486,459.209 667.749,435.859 670.012,412.612 672.274,389.537 674.537,366.69 676.799,344.221 679.062,322.313 681.325,301.161 683.587,280.971 685.85,261.961 688.113,244.358 690.375,228.405 692.638,214.351 694.9,202.461 697.163,193.009 699.426,186.279 701.688,182.571 703.951,182.192 706.214,185.462 708.476,192.712 710.739,204.284 713.001,220.413 715.264,241.15 717.527,266.45 719.789,296.182 722.052,330.129 724.315,367.985 726.577,409.358 728.84,453.771 731.102,500.656 733.365,549.362 735.628,599.147 737.89,649.231 740.153,699.057 742.416,748.013 744.678,795.546 746.941,841.197 749.203,884.603 751.466,925.491 753.729,963.687 755.991,999.109 758.254,1031.77 760.517,1061.77 762.779,1089.26 765.042,1114.28 767.304,1137 769.567,1157.55 771.83,1176.09 774.092,1192.76 776.355,1207.71 778.617,1221.06 780.88,1232.94 783.143,1243.47 785.405,1252.76 787.668,1260.93 789.931,1268.07 792.193,1274.26 794.456,1279.58 796.718,1284.09 798.981,1287.87 801.244,1290.98 803.506,1293.45 805.769,1295.33 808.032,1296.67 810.294,1297.49 812.557,1297.82 814.819,1297.7 817.082,1297.15 819.345,1296.19 821.607,1294.85 823.87,1293.13 826.133,1291.05 828.395,1288.62 830.658,1285.87 832.92,1282.79 835.183,1279.4 837.446,1275.71 839.708,1271.72 841.971,1267.44 844.234,1262.86 846.496,1258 848.759,1252.86 851.021,1247.43 853.284,1241.72 855.547,1235.73 857.809,1229.45 860.072,1222.89 862.335,1216.05 864.597,1208.93 866.86,1201.52 869.122,1193.82 871.385,1185.83 873.648,1177.54 875.91,1168.96 878.173,1160.07 880.436,1150.88 882.698,1141.38 884.961,1131.56 887.223,1121.43 889.486,1110.97 891.749,1100.19 894.011,1089.07 896.274,1077.61 898.536,1065.81 900.799,1053.66 903.062,1041.15 905.324,1028.28 907.587,1015.04 909.85,1001.44 912.112,987.454 914.375,973.087 916.637,958.331 918.9,943.181 921.163,927.634 923.425,911.686 925.688,895.333 927.951,878.573 930.213,861.404 932.476,843.824 934.738,825.834 937.001,807.432 939.264,788.618 941.526,769.399 943.789,749.804 946.052,729.832 948.314,709.472 950.577,688.724 952.839,667.593 955.102,646.092 957.365,624.239 959.627,602.063 961.89,579.597 964.153,556.881 966.415,533.965 968.678,510.902 970.94,487.756 973.203,464.596 975.466,441.497 977.728,418.545 979.991,395.828 982.254,373.445 984.516,351.501 986.779,330.104 989.041,309.332 991.304,289.411 993.567,270.614 995.829,253.215 998.092,237.485 1000.35,223.697 1002.62,212.124 1004.88,203.038 1007.14,196.712 1009.41,193.417 1011.67,193.427 1013.93,197.013 1016.19,204.447 1018.46,216.002 1020.72,231.95 1022.98,252.585 1025.24,277.849 1027.51,307.484 1029.77,341.182 1032.03,378.584 1034.29,419.283 1036.56,462.819 1038.82,508.687 1041.08,556.327 1043.34,605.135 1045.61,654.451 1047.87,703.57 1050.13,751.738 1052.39,798.445 1054.66,843.387 1056.92,886.244 1059.18,926.759 1061.45,964.744 1063.71,1000.08 1065.97,1032.7 1068.23,1062.61 1070.5,1089.91 1072.76,1114.72 1075.02,1137.25 1077.28,1157.77 1079.55,1176.38 1081.81,1193.13 1084.07,1208.18 1086.33,1221.67 1088.6,1233.71 1090.86,1244.43 1093.12,1253.94 1095.38,1262.34 1097.65,1269.71 1099.91,1276.12 1102.17,1281.67 1104.44,1286.42 1106.7,1290.44 1108.96,1293.77 1111.22,1296.48 1113.49,1298.59 1115.75,1300.16 1118.01,1301.22 1120.27,1301.8 1122.54,1301.94 1124.8,1301.65 1127.06,1300.96 1129.32,1299.88 1131.59,1298.43 1133.85,1296.64 1136.11,1294.51 1138.37,1292.05 1140.64,1289.27 1142.9,1286.18 1145.16,1282.79 1147.42,1279.1 1149.69,1275.12 1151.95,1270.86 1154.21,1266.32 1156.48,1261.5 1158.74,1256.4 1161,1251.04 1163.26,1245.4 1165.53,1239.48 1167.79,1233.3 1170.05,1226.83 1172.31,1220.09 1174.58,1213.08 1176.84,1205.78 1179.1,1198.2 1181.36,1190.33 1183.63,1182.17 1185.89,1173.73 1188.15,1164.98 1190.41,1155.94 1192.68,1146.6 1194.94,1136.94 1197.2,1126.97 1199.47,1116.69 1201.73,1106.08 1203.99,1095.14 1206.25,1083.87 1208.52,1072.26 1210.78,1060.31 1213.04,1048.01 1215.3,1035.36 1217.57,1022.34 1219.83,1008.97 1222.09,995.217 1224.35,981.092 1226.62,966.587 1228.88,951.695 1231.14,936.413 1233.4,920.741 1235.67,904.671 1237.93,888.198 1240.19,871.32 1242.46,854.033 1244.72,836.337 1246.98,818.232 1249.24,799.722 1251.51,780.81 1253.77,761.5 1256.03,741.8 1258.29,721.718 1260.56,701.263 1262.82,680.446 1265.08,659.28 1267.34,637.808 1269.61,616.076 1271.87,594.079 1274.13,571.823 1276.39,549.33 1278.66,526.637 1280.92,503.791 1283.18,480.854 1285.44,457.905 1287.71,435.031 1289.97,412.337 1292.23,389.94 1294.5,367.971 1296.76,346.575 1299.02,325.909 1301.28,306.147 1303.55,287.473 1305.81,270.088 1308.07,254.203 1310.33,240.047 1312.6,227.859 1314.86,217.893 1317.12,210.41 1319.38,205.71 1321.65,204.201 1323.91,206.241 1326.17,212.123 1328.43,222.067 1330.7,236.229 1332.96,254.698 1335.22,277.491 1337.49,304.562 1339.75,335.795 1342.01,371.009 1344.27,409.964 1346.54,452.075 1348.8,496.675 1351.06,543.122 1353.32,590.792 1355.59,639.082 1357.85,687.41 1360.11,735.216 1362.37,781.959 1364.64,827.121 1366.9,870.245 1369.16,911.126 1371.42,949.622 1373.69,985.632 1375.95,1019.1 1378.21,1050.01 1380.48,1078.4 1382.74,1104.34 1385,1127.95 1387.26,1149.4 1389.53,1168.89 1391.79,1186.51 1394.05,1202.37 1396.31,1216.63 1398.58,1229.42 1400.84,1240.85 1403.1,1251.04 1405.36,1260.09 1407.63,1268.09 1409.89,1275.13 1412.15,1281.28 1414.41,1286.59 1416.68,1291.12 1418.94,1294.95 1421.2,1298.13 1423.46,1300.72 1425.73,1302.74 1427.99,1304.24 1430.25,1305.25 1432.52,1305.8 1434.78,1305.91 1437.04,1305.63 1439.3,1304.95 1441.57,1303.9 1443.83,1302.5 1446.09,1300.77 1448.35,1298.7 1450.62,1296.32 1452.88,1293.64 1455.14,1290.65 1457.4,1287.36 1459.67,1283.79 1461.93,1279.94 1464.19,1275.8 1466.45,1271.4 1468.72,1266.72 1470.98,1261.78 1473.24,1256.57 1475.51,1251.1 1477.77,1245.36 1480.03,1239.35 1482.29,1233.07 1484.56,1226.52 1486.82,1219.71 1489.08,1212.62 1491.34,1205.25 1493.61,1197.6 1495.87,1189.67 1498.13,1181.46 1500.39,1172.96 1502.66,1164.17 1504.92,1155.07 1507.18,1145.68 1509.44,1135.98 1511.71,1125.98 1513.97,1115.65 1516.23,1105.01 1518.5,1094.04 1520.76,1082.73 1523.02,1071.1 1525.28,1059.12 1527.55,1046.79 1529.81,1034.11 1532.07,1021.08 1534.33,1007.68 1536.6,993.92 1538.86,979.784 1541.12,965.269 1543.38,950.371 1545.65,935.086 1547.91,919.414 1550.17,903.349 1552.43,886.886 1554.7,870.021 1556.96,852.751 1559.22,835.078 1561.48,817.001 1563.75,798.524 1566.01,779.651 1568.27,760.387 1570.54,740.741 1572.8,720.721 1575.06,700.338 1577.32,679.604 1579.59,658.532 1581.85,637.149 1584.11,615.516 1586.37,593.637 1588.64,571.522 1590.9,549.194 1593.16,526.688 1595.42,504.054 1597.69,481.356 1599.95,458.672 1602.21,436.092 1604.47,413.722 1606.74,391.678 1609,370.094 1611.26,349.116 1613.53,328.902 1615.79,309.626 1618.05,291.475 1620.31,274.649 1622.58,259.363 1624.84,245.844 1627.1,234.335 1629.36,225.089 1631.63,218.365 1633.89,214.47 1636.15,213.8 1638.41,216.693 1640.68,223.417 1642.94,234.176 1645.2,249.105 1647.46,268.274 1649.73,291.685 1651.99,319.273 1654.25,350.906 1656.52,386.393 1658.78,425.46 1661.04,467.504 1663.3,511.877 1665.57,557.952 1667.83,605.123 1670.09,652.806 1672.35,700.436 1674.62,747.472 1676.88,793.391 1679.14,837.693 1681.4,879.964 1683.67,920.026 1685.93,957.743 1688.19,993.02 1690.45,1025.81 1692.72,1056.09 1694.98,1083.92 1697.24,1109.36 1699.5,1132.54 1701.77,1153.62 1704.03,1172.8 1706.29,1190.14 1708.56,1205.78 1710.82,1219.85 1713.08,1232.49 1715.34,1243.81 1717.61,1253.91 1719.87,1262.91 1722.13,1270.88 1724.39,1277.91 1726.66,1284.06 1728.92,1289.39 1731.18,1293.96 1733.44,1297.85 1735.71,1301.1 1737.97,1303.77 1740.23,1305.88 1742.49,1307.48 1744.76,1308.6 1747.02,1309.27 1749.28,1309.52 1751.55,1309.36 1753.81,1308.83 1756.07,1307.93 1758.33,1306.68 1760.6,1305.11 1762.86,1303.21 1765.12,1301.01 1767.38,1298.5 1769.65,1295.69 1771.91,1292.6 1774.17,1289.22 1776.43,1285.57 1778.7,1281.65 1780.96,1277.46 1783.22,1273 1785.48,1268.29 1787.75,1263.31 1790.01,1258.07 1792.27,1252.58 1794.54,1246.82 1796.8,1240.8 1799.06,1234.52 1801.32,1227.97 1803.59,1221.16 1805.85,1214.07 1808.11,1206.72 1810.37,1199.09 1812.64,1191.18 1814.9,1182.99 1817.16,1174.52 1819.42,1165.76 1821.69,1156.7 1823.95,1147.35 1826.21,1137.69 1828.47,1127.73 1830.74,1117.45 1833,1106.86 1835.26,1095.95 1837.52,1084.7 1839.79,1073.13 1842.05,1061.22 1844.31,1048.96 1846.58,1036.36 1848.84,1023.4 1851.1,1010.09 1853.36,996.41 1855.63,982.361 1857.89,967.938 1860.15,953.135 1862.41,937.953 1864.68,922.386 1866.94,906.428 1869.2,890.075 1871.46,873.324 1873.73,856.174 1875.99,838.625 1878.25,820.679 1880.51,802.337 1882.78,783.606 1885.04,764.489 1887.3,744.996 1889.57,725.133 1891.83,704.912 1894.09,684.343 1896.35,663.441 1898.62,642.265 1900.88,620.834 1903.14,599.148 1905.4,577.219 1907.67,555.075 1909.93,532.754 1912.19,510.309 1914.45,487.805 1916.72,465.32 1918.98,442.945 1921.24,420.783 1923.5,398.953 1925.77,377.582 1928.03,356.816 1930.29,336.808 1932.56,317.728 1934.82,299.757 1937.08,283.091 1939.34,267.935 1941.61,254.512 1943.87,243.054 1946.13,233.807 1948.39,227.014 1950.66,223.039 1952.92,222.256 1955.18,224.977 1957.44,231.454 1959.71,241.88 1961.97,256.385 1964.23,275.042 1966.49,297.862 1968.76,324.795 1971.02,355.732 1973.28,390.52 1975.54,428.842 1977.81,470.097 1980.07,513.677 1982.33,558.988 1984.6,605.452 1986.86,652.5 1989.12,699.58 1991.38,746.153 1993.65,791.693 1995.91,835.689 1998.17,877.741 2000.43,917.671 2002.7,955.328 2004.96,990.606 2007.22,1023.44 2009.48,1053.82 2011.75,1081.77 2014.01,1107.36 2016.27,1130.71 2018.53,1151.99 2020.8,1171.37 2023.06,1188.93 2025.32,1204.8 2027.59,1219.1 2029.85,1231.97 2032.11,1243.52 2034.37,1253.86 2036.64,1263.09 2038.9,1271.29 2041.16,1278.54 2043.42,1284.91 2045.69,1290.47 2047.95,1295.26 2050.21,1299.37 2052.47,1302.85 2054.74,1305.74 2057,1308.07 2059.26,1309.89 2061.52,1311.23 2063.79,1312.12 2066.05,1312.59 2068.31,1312.66 2070.58,1312.35 2072.84,1311.68 2075.1,1310.66 2077.36,1309.32 2079.63,1307.66 2081.89,1305.68 2084.15,1303.41 2086.41,1300.85 2088.68,1298 2090.94,1294.87 2093.2,1291.47 2095.46,1287.81 2097.73,1283.88 2099.99,1279.69 2102.25,1275.24 2104.51,1270.54 2106.78,1265.59 2109.04,1260.38 2111.3,1254.91 2113.56,1249.19 2115.83,1243.21 2118.09,1236.98 2120.35,1230.48 2122.62,1223.72 2124.88,1216.7 2127.14,1209.4 2129.4,1201.84 2131.67,1194.01 2133.93,1185.9 2136.19,1177.5 2138.45,1168.83 2140.72,1159.86 2142.98,1150.6 2145.24,1141.04 2147.5,1131.17 2149.77,1121 2152.03,1110.52 2154.29,1099.72 2156.55,1088.59 2158.82,1077.14 2161.08,1065.35 2163.34,1053.22 2165.61,1040.75 2167.87,1027.94 2170.13,1014.76 2172.39,1001.23 2174.66,987.331 2176.92,973.061 2179.18,958.419 2181.44,943.401 2183.71,928.001 2185.97,912.213 2188.23,896.035 2190.49,879.463 2192.76,862.497 2195.02,845.137 2197.28,827.384 2199.54,809.241 2201.81,790.712 2204.07,771.802 2206.33,752.518 2208.59,732.867 2210.86,712.859 2213.12,692.504 2215.38,671.837 2217.65,650.906 2219.91,629.705 2222.17,608.237 2224.43,586.517 2226.7,564.574 2228.96,542.447 2231.22,520.188 2233.48,497.863 2235.75,475.547 2238.01,453.33 2240.27,431.311 2242.53,409.606 2244.8,388.338 2247.06,367.645 2249.32,347.678 2251.58,328.598 2253.85,310.579 2256.11,293.807 2258.37,278.481 2260.64,264.813 2262.9,253.024 2265.16,243.346 2267.42,236.027 2269.69,231.441 2271.95,229.949 2274.21,231.852 2276.47,237.399 2278.74,246.785 2281,260.149 2283.26,277.576 2285.52,299.095 2287.79,324.682 2290.05,354.257 2292.31,387.704 2294.57,424.727 2296.84,464.758 2299.1,507.22 2301.36,551.544 2303.63,597.171 2305.89,643.548 2308.15,690.132 2310.41,736.385 2312.68,781.781 2314.94,825.799 2317.2,868.001 2319.46,908.189 2321.73,946.197 2323.99,981.9 2326.25,1015.22 2328.51,1046.13 2330.78,1074.63 2333.04,1100.78 2335.3,1124.69 2337.56,1146.49 2339.83,1166.39 2342.09,1184.48 2344.35,1200.86 2346.61,1215.65 2348.88,1228.99 2351.14,1240.98 2353.4,1251.75 2355.67,1261.38 2357.93,1269.97 2360.19,1277.6 2362.45,1284.34 2364.72,1290.24 2366.98,1295.38 2369.24,1299.81 2371.5,1303.6 2373.77,1306.8 2376.03,1309.43 2378.29,1311.54 2380.55,1313.17 2382.82,1314.34 2385.08,1315.08 2387.34,1315.43 2389.6,1315.39 2391.87,1314.98 2394.13,1314.23 2396.39,1313.15 2398.66,1311.75 2400.92,1310.05 2403.18,1308.04 2405.44,1305.74 2407.71,1303.17 2409.97,1300.31 2412.23,1297.19 2414.49,1293.8 2416.76,1290.15 2419.02,1286.24 2421.28,1282.08 2423.54,1277.67 2425.81,1273.01 2428.07,1268.11 2430.33,1262.95 2432.59,1257.54 2434.86,1251.88 2437.12,1245.96 2439.38,1239.79 2441.65,1233.37 2443.91,1226.69 2446.17,1219.75 2448.43,1212.54 2450.7,1205.07 2452.96,1197.33 2455.22,1189.31 2457.48,1181.02 2459.75,1172.45 2462.01,1163.59 2464.27,1154.44 2466.53,1145 2468.8,1135.26 2471.06,1125.22 2473.32,1114.86 2475.58,1104.19 2477.85,1093.21 2480.11,1081.9 2482.37,1070.26 2484.63,1058.28 2486.9,1045.97 2489.16,1033.31 2491.42,1020.3 2493.69,1006.94 2495.95,993.211 2498.21,979.119 2500.47,964.66 2502.74,949.829 2505,934.619 2507.26,919.025 2509.52,903.045 2511.79,886.677 2514.05,869.918 2516.31,852.769 2518.57,835.231 2520.84,817.307 2523.1,799 2525.36,780.315 2527.62,761.258 2529.89,741.837 2532.15,722.059 2534.41,701.933 2536.68,681.504 2538.94,660.808 2541.2,639.836 2543.46,618.593 2545.73,597.092 2547.99,575.361 2550.25,553.436 2552.51,531.368 2554.78,509.219 2557.04,487.062 2559.3,464.982 2561.56,443.077 2563.83,421.453 2566.09,400.233 2568.35,379.548 2570.61,359.541 2572.88,340.369 2575.14,322.198 2577.4,305.209 2579.67,289.59 2581.93,275.546 2584.19,263.29 2586.45,253.047 2588.72,245.046 2590.98,239.645 2593.24,237.203 2595.5,238.029 2597.77,242.377 2600.03,250.453 2602.29,262.407 2604.55,278.34 2606.82,298.299 2609.08,322.281 2611.34,350.228 2613.6,382.042 2615.87,417.52 2618.13,456.143 2620.39,497.349 2622.65,540.586 2624.92,585.306 2627.18,630.967 2629.44,677.035 2631.71,722.98 2633.97,768.28 2636.23,812.418 2638.49,854.912 2640.76,895.515 "></polyline>
<polyline clip-path="url(#clip232)" style="stroke:#e26f46; stroke-linecap:round; stroke-linejoin:round; stroke-width:8; stroke-opacity:1; fill:none" points="380.396,1430.81 382.659,1420.32 384.921,1408.65 387.184,1395.69 389.446,1381.3 391.709,1365.37 393.972,1347.77 396.234,1328.37 398.497,1307.07 400.76,1283.79 403.022,1258.47 405.285,1231.09 407.547,1201.71 409.81,1170.43 412.073,1137.45 414.335,1103.04 416.598,1067.56 418.861,1031.5 421.123,995.376 423.386,959.79 425.648,925.393 427.911,892.836 430.174,862.787 432.436,835.847 434.699,812.512 436.961,793.174 439.224,778.118 441.487,767.525 443.749,761.436 446.012,759.749 448.275,762.287 450.537,768.804 452.8,778.989 455.062,792.458 457.325,808.814 459.588,827.655 461.85,848.567 464.113,871.161 466.376,895.073 468.638,919.965 470.901,945.522 473.163,971.457 475.426,997.507 477.689,1023.46 479.951,1049.11 482.214,1074.32 484.477,1098.94 486.739,1122.85 489.002,1145.97 491.264,1168.25 493.527,1189.62 495.79,1210.07 498.052,1229.56 500.315,1248.11 502.578,1265.71 504.84,1282.38 507.103,1298.13 509.365,1312.98 511.628,1326.96 513.891,1340.12 516.153,1352.49 518.416,1364.09 520.679,1374.97 522.941,1385.18 525.204,1394.73 527.466,1403.67 529.729,1412.03 531.992,1419.85 534.254,1427.15 536.517,1433.97 538.779,1440.35 541.042,1446.3 543.305,1451.85 545.567,1457.03 547.83,1461.87 550.093,1466.39 552.355,1470.6 554.618,1474.53 556.88,1478.19 559.143,1481.61 561.406,1484.8 563.668,1487.76 565.931,1490.52 568.194,1493.09 570.456,1495.47 572.719,1497.69 574.981,1499.74 577.244,1501.65 579.507,1503.41 581.769,1505.04 584.032,1506.54 586.295,1507.92 588.557,1509.18 590.82,1510.33 593.082,1511.38 595.345,1512.32 597.608,1513.16 599.87,1513.9 602.133,1514.55 604.396,1515.11 606.658,1515.57 608.921,1515.95 611.183,1516.24 613.446,1516.44 615.709,1516.54 617.971,1516.56 620.234,1516.48 622.497,1516.31 624.759,1516.04 627.022,1515.67 629.284,1515.19 631.547,1514.59 633.81,1513.86 636.072,1513 638.335,1512.02 640.598,1510.89 642.86,1509.62 645.123,1508.18 647.385,1506.58 649.648,1504.78 651.911,1502.77 654.173,1500.53 656.436,1498.02 658.698,1495.22 660.961,1492.1 663.224,1488.62 665.486,1484.74 667.749,1480.43 670.012,1475.64 672.274,1470.32 674.537,1464.47 676.799,1457.98 679.062,1450.75 681.325,1442.67 683.587,1433.62 685.85,1423.5 688.113,1412.21 690.375,1399.65 692.638,1385.71 694.9,1370.3 697.163,1353.32 699.426,1334.68 701.688,1314.3 703.951,1292.07 706.214,1267.92 708.476,1241.76 710.739,1213.49 713.001,1183.13 715.264,1150.98 717.527,1117.4 719.789,1082.79 722.052,1047.59 724.315,1012.25 726.577,977.271 728.84,943.182 731.102,910.544 733.365,879.95 735.628,852.024 737.89,827.385 740.153,806.373 742.416,789.32 744.678,776.478 746.941,767.99 749.203,763.892 751.466,764.112 753.729,768.467 755.991,776.668 758.254,788.315 760.517,802.901 762.779,819.926 765.042,839.168 767.304,860.248 769.567,882.795 771.83,906.467 774.092,930.952 776.355,955.967 778.617,981.256 780.88,1006.59 783.143,1031.78 785.405,1056.65 787.668,1081.04 789.931,1104.84 792.193,1127.96 794.456,1150.34 796.718,1171.9 798.981,1192.6 801.244,1212.41 803.506,1231.31 805.769,1249.3 808.032,1266.38 810.294,1282.57 812.557,1297.91 814.819,1312.4 817.082,1326.08 819.345,1338.96 821.607,1351.1 823.87,1362.51 826.133,1373.23 828.395,1383.29 830.658,1392.73 832.92,1401.58 835.183,1409.87 837.446,1417.63 839.708,1424.89 841.971,1431.7 844.234,1438.06 846.496,1444.01 848.759,1449.58 851.021,1454.79 853.284,1459.66 855.547,1464.21 857.809,1468.47 860.072,1472.44 862.335,1476.16 864.597,1479.63 866.86,1482.87 869.122,1485.89 871.385,1488.7 873.648,1491.33 875.91,1493.77 878.173,1496.04 880.436,1498.16 882.698,1500.12 884.961,1501.94 887.223,1503.62 889.486,1505.18 891.749,1506.61 894.011,1507.93 896.274,1509.14 898.536,1510.24 900.799,1511.24 903.062,1512.14 905.324,1512.94 907.587,1513.64 909.85,1514.26 912.112,1514.78 914.375,1515.21 916.637,1515.56 918.9,1515.82 921.163,1515.99 923.425,1516.07 925.688,1516.06 927.951,1515.96 930.213,1515.76 932.476,1515.47 934.738,1515.07 937.001,1514.56 939.264,1513.94 941.526,1513.21 943.789,1512.32 946.052,1511.29 948.314,1510.12 950.577,1508.79 952.839,1507.3 955.102,1505.64 957.365,1503.79 959.627,1501.74 961.89,1499.45 964.153,1496.92 966.415,1494.09 968.678,1490.95 970.94,1487.45 973.203,1483.54 975.466,1479.2 977.728,1474.36 979.991,1468.98 982.254,1462.99 984.516,1456.34 986.779,1448.97 989.041,1440.85 991.304,1431.84 993.567,1421.81 995.829,1410.61 998.092,1398.12 1000.35,1384.22 1002.62,1368.81 1004.88,1351.79 1007.14,1333.09 1009.41,1312.65 1011.67,1290.4 1013.93,1266.31 1016.19,1240.34 1018.46,1212.47 1020.72,1182.7 1022.98,1151 1025.24,1117.72 1027.51,1083.38 1029.77,1048.49 1032.03,1013.58 1034.29,979.158 1036.56,945.733 1038.82,913.813 1041.08,883.904 1043.34,856.507 1045.61,832.119 1047.87,811.238 1050.13,794.354 1052.39,781.661 1054.66,773.114 1056.92,768.688 1059.18,768.3 1061.45,771.808 1063.71,779.01 1065.97,789.645 1068.23,803.393 1070.5,819.878 1072.76,838.659 1075.02,859.242 1077.28,881.075 1079.55,903.918 1081.81,927.61 1084.07,951.876 1086.33,976.463 1088.6,1001.15 1090.86,1025.74 1093.12,1050.06 1095.38,1073.97 1097.65,1097.35 1099.91,1120.12 1102.17,1142.2 1104.44,1163.5 1106.7,1184.01 1108.96,1203.69 1111.22,1222.53 1113.49,1240.51 1115.75,1257.64 1118.01,1273.91 1120.27,1289.34 1122.54,1303.95 1124.8,1317.75 1127.06,1330.79 1129.32,1343.09 1131.59,1354.68 1133.85,1365.6 1136.11,1375.87 1138.37,1385.53 1140.64,1394.6 1142.9,1403.12 1145.16,1411.12 1147.42,1418.63 1149.69,1425.67 1151.95,1432.26 1154.21,1438.44 1156.48,1444.23 1158.74,1449.66 1161,1454.73 1163.26,1459.49 1165.53,1463.94 1167.79,1468.1 1170.05,1472 1172.31,1475.65 1174.58,1479.06 1176.84,1482.25 1179.1,1485.23 1181.36,1488.01 1183.63,1490.61 1185.89,1493.04 1188.15,1495.3 1190.41,1497.4 1192.68,1499.35 1194.94,1501.17 1197.2,1502.85 1199.47,1504.41 1201.73,1505.84 1203.99,1507.16 1206.25,1508.37 1208.52,1509.48 1210.78,1510.48 1213.04,1511.38 1215.3,1512.19 1217.57,1512.91 1219.83,1513.54 1222.09,1514.08 1224.35,1514.53 1226.62,1514.89 1228.88,1515.17 1231.14,1515.35 1233.4,1515.45 1235.67,1515.45 1237.93,1515.37 1240.19,1515.19 1242.46,1514.91 1244.72,1514.54 1246.98,1514.06 1249.24,1513.48 1251.51,1512.77 1253.77,1511.94 1256.03,1510.98 1258.29,1509.88 1260.56,1508.62 1262.82,1507.2 1265.08,1505.61 1267.34,1503.8 1269.61,1501.77 1271.87,1499.5 1274.13,1496.97 1276.39,1494.18 1278.66,1491.08 1280.92,1487.66 1283.18,1483.87 1285.44,1479.68 1287.71,1475.02 1289.97,1469.86 1292.23,1464.12 1294.5,1457.74 1296.76,1450.66 1299.02,1442.78 1301.28,1434.04 1303.55,1424.33 1305.81,1413.56 1308.07,1401.64 1310.33,1388.45 1312.6,1373.87 1314.86,1357.8 1317.12,1340.12 1319.38,1320.71 1321.65,1299.48 1323.91,1276.33 1326.17,1251.24 1328.43,1224.27 1330.7,1195.49 1332.96,1165.06 1335.22,1133.19 1337.49,1100.14 1339.75,1066.22 1342.01,1031.82 1344.27,997.369 1346.54,963.529 1348.8,930.973 1351.06,900.305 1353.32,872.059 1355.59,846.706 1357.85,824.646 1360.11,806.215 1362.37,791.68 1364.64,781.239 1366.9,774.998 1369.16,772.823 1371.42,774.494 1373.69,779.771 1375.95,788.388 1378.21,800.053 1380.48,814.448 1382.74,831.232 1385,850.037 1387.26,870.47 1389.53,892.129 1391.79,914.757 1394.05,938.101 1396.31,961.91 1398.58,985.955 1400.84,1010.04 1403.1,1033.97 1405.36,1057.61 1407.63,1080.81 1409.89,1103.49 1412.15,1125.54 1414.41,1146.92 1416.68,1167.59 1418.94,1187.49 1421.2,1206.58 1423.46,1224.86 1425.73,1242.33 1427.99,1258.98 1430.25,1274.82 1432.52,1289.87 1434.78,1304.12 1437.04,1317.62 1439.3,1330.37 1441.57,1342.42 1443.83,1353.8 1446.09,1364.53 1448.35,1374.63 1450.62,1384.15 1452.88,1393.11 1455.14,1401.53 1457.4,1409.45 1459.67,1416.89 1461.93,1423.89 1464.19,1430.45 1466.45,1436.61 1468.72,1442.39 1470.98,1447.81 1473.24,1452.9 1475.51,1457.67 1477.77,1462.13 1480.03,1466.32 1482.29,1470.25 1484.56,1473.92 1486.82,1477.37 1489.08,1480.59 1491.34,1483.61 1493.61,1486.43 1495.87,1489.07 1498.13,1491.54 1500.39,1493.84 1502.66,1495.99 1504.92,1497.99 1507.18,1499.85 1509.44,1501.58 1511.71,1503.18 1513.97,1504.66 1516.23,1506.02 1518.5,1507.28 1520.76,1508.43 1523.02,1509.48 1525.28,1510.43 1527.55,1511.28 1529.81,1512.05 1532.07,1512.72 1534.33,1513.3 1536.6,1513.8 1538.86,1514.21 1541.12,1514.53 1543.38,1514.77 1545.65,1514.92 1547.91,1514.97 1550.17,1514.94 1552.43,1514.82 1554.7,1514.6 1556.96,1514.29 1559.22,1513.87 1561.48,1513.35 1563.75,1512.72 1566.01,1511.98 1568.27,1511.1 1570.54,1510.09 1572.8,1508.94 1575.06,1507.63 1577.32,1506.15 1579.59,1504.49 1581.85,1502.63 1584.11,1500.53 1586.37,1498.19 1588.64,1495.59 1590.9,1492.71 1593.16,1489.52 1595.42,1485.99 1597.69,1482.09 1599.95,1477.76 1602.21,1472.97 1604.47,1467.65 1606.74,1461.75 1609,1455.2 1611.26,1447.93 1613.53,1439.86 1615.79,1430.9 1618.05,1420.97 1620.31,1409.97 1622.58,1397.81 1624.84,1384.37 1627.1,1369.54 1629.36,1353.2 1631.63,1335.25 1633.89,1315.59 1636.15,1294.1 1638.41,1270.73 1640.68,1245.47 1642.94,1218.37 1645.2,1189.54 1647.46,1159.14 1649.73,1127.38 1651.99,1094.53 1654.25,1060.92 1656.52,1026.93 1658.78,993.011 1661.04,959.817 1663.3,927.995 1665.57,898.121 1667.83,870.706 1670.09,846.195 1672.35,824.966 1674.62,807.331 1676.88,793.536 1679.14,783.762 1681.4,778.079 1683.67,776.332 1685.93,778.308 1688.19,783.77 1690.45,792.457 1692.72,804.082 1694.98,818.336 1697.24,834.886 1699.5,853.372 1701.77,873.413 1704.03,894.627 1706.29,916.779 1708.56,939.62 1710.82,962.911 1713.08,986.433 1715.34,1009.99 1717.61,1033.42 1719.87,1056.57 1722.13,1079.32 1724.39,1101.55 1726.66,1123.21 1728.92,1144.22 1731.18,1164.56 1733.44,1184.16 1735.71,1202.99 1737.97,1221.05 1740.23,1238.32 1742.49,1254.82 1744.76,1270.53 1747.02,1285.48 1749.28,1299.66 1751.55,1313.11 1753.81,1325.85 1756.07,1337.9 1758.33,1349.29 1760.6,1360.05 1762.86,1370.2 1765.12,1379.78 1767.38,1388.81 1769.65,1397.31 1771.91,1405.32 1774.17,1412.86 1776.43,1419.95 1778.7,1426.62 1780.96,1432.89 1783.22,1438.78 1785.48,1444.31 1787.75,1449.51 1790.01,1454.39 1792.27,1458.97 1794.54,1463.27 1796.8,1467.3 1799.06,1471.09 1801.32,1474.64 1803.59,1477.97 1805.85,1481.09 1808.11,1484.01 1810.37,1486.75 1812.64,1489.31 1814.9,1491.71 1817.16,1493.95 1819.42,1496.04 1821.69,1497.99 1823.95,1499.8 1826.21,1501.49 1828.47,1503.05 1830.74,1504.49 1833,1505.83 1835.26,1507.05 1837.52,1508.18 1839.79,1509.2 1842.05,1510.13 1844.31,1510.96 1846.58,1511.71 1848.84,1512.37 1851.1,1512.93 1853.36,1513.42 1855.63,1513.81 1857.89,1514.12 1860.15,1514.35 1862.41,1514.48 1864.68,1514.53 1866.94,1514.49 1869.2,1514.35 1871.46,1514.13 1873.73,1513.81 1875.99,1513.39 1878.25,1512.86 1880.51,1512.22 1882.78,1511.47 1885.04,1510.58 1887.3,1509.56 1889.57,1508.4 1891.83,1507.08 1894.09,1505.59 1896.35,1503.93 1898.62,1502.05 1900.88,1499.93 1903.14,1497.58 1905.4,1494.97 1907.67,1492.09 1909.93,1488.9 1912.19,1485.37 1914.45,1481.48 1916.72,1477.16 1918.98,1472.38 1921.24,1467.09 1923.5,1461.21 1925.77,1454.7 1928.03,1447.46 1930.29,1439.44 1932.56,1430.54 1934.82,1420.68 1937.08,1409.77 1939.34,1397.71 1941.61,1384.39 1943.87,1369.7 1946.13,1353.53 1948.39,1335.79 1950.66,1316.36 1952.92,1295.13 1955.18,1272.05 1957.44,1247.12 1959.71,1220.4 1961.97,1191.98 1964.23,1162.01 1966.49,1130.7 1968.76,1098.31 1971.02,1065.13 1973.28,1031.53 1975.54,997.968 1977.81,965.111 1980.07,933.563 1982.33,903.874 1984.6,876.536 1986.86,851.982 1989.12,830.587 1991.38,812.67 1993.65,798.489 1995.91,788.245 1998.17,782.009 2000.43,779.628 2002.7,780.909 2004.96,785.634 2007.22,793.56 2009.48,804.414 2011.75,817.9 2014.01,833.694 2016.27,851.446 2018.53,870.779 2020.8,891.31 2023.06,912.812 2025.32,935.045 2027.59,957.773 2029.85,980.781 2032.11,1003.88 2034.37,1026.89 2036.64,1049.68 2038.9,1072.11 2041.16,1094.09 2043.42,1115.53 2045.69,1136.37 2047.95,1156.58 2050.21,1176.09 2052.47,1194.88 2054.74,1212.92 2057,1230.22 2059.26,1246.76 2061.52,1262.55 2063.79,1277.59 2066.05,1291.89 2068.31,1305.48 2070.58,1318.36 2072.84,1330.58 2075.1,1342.15 2077.36,1353.09 2079.63,1363.44 2081.89,1373.21 2084.15,1382.44 2086.41,1391.15 2088.68,1399.36 2090.94,1407.1 2093.2,1414.4 2095.46,1421.26 2097.73,1427.73 2099.99,1433.82 2102.25,1439.54 2104.51,1444.92 2106.78,1449.99 2109.04,1454.75 2111.3,1459.22 2113.56,1463.42 2115.83,1467.37 2118.09,1471.08 2120.35,1474.57 2122.62,1477.84 2124.88,1480.91 2127.14,1483.79 2129.4,1486.49 2131.67,1489.02 2133.93,1491.38 2136.19,1493.6 2138.45,1495.66 2140.72,1497.59 2142.98,1499.39 2145.24,1501.06 2147.5,1502.61 2149.77,1504.04 2152.03,1505.37 2154.29,1506.59 2156.55,1507.71 2158.82,1508.73 2161.08,1509.66 2163.34,1510.5 2165.61,1511.25 2167.87,1511.9 2170.13,1512.48 2172.39,1512.96 2174.66,1513.36 2176.92,1513.68 2179.18,1513.91 2181.44,1514.05 2183.71,1514.1 2185.97,1514.07 2188.23,1513.95 2190.49,1513.73 2192.76,1513.42 2195.02,1513.01 2197.28,1512.5 2199.54,1511.87 2201.81,1511.13 2204.07,1510.27 2206.33,1509.26 2208.59,1508.12 2210.86,1506.83 2213.12,1505.36 2215.38,1503.72 2217.65,1501.85 2219.91,1499.77 2222.17,1497.45 2224.43,1494.89 2226.7,1492.05 2228.96,1488.93 2231.22,1485.47 2233.48,1481.66 2235.75,1477.44 2238.01,1472.77 2240.27,1467.59 2242.53,1461.85 2244.8,1455.49 2247.06,1448.43 2249.32,1440.6 2251.58,1431.92 2253.85,1422.31 2256.11,1411.68 2258.37,1399.93 2260.64,1386.96 2262.9,1372.66 2265.16,1356.93 2267.42,1339.67 2269.69,1320.77 2271.95,1300.11 2274.21,1277.64 2276.47,1253.36 2278.74,1227.3 2281,1199.56 2283.26,1170.27 2285.52,1139.61 2287.79,1107.81 2290.05,1075.16 2292.31,1041.97 2294.57,1008.7 2296.84,975.996 2299.1,944.435 2301.36,914.557 2303.63,886.849 2305.89,861.743 2308.15,839.623 2310.41,820.819 2312.68,805.609 2314.94,794.222 2317.2,786.774 2319.46,783.139 2321.73,783.145 2323.99,786.597 2326.25,793.267 2328.51,802.903 2330.78,815.226 2333.04,829.926 2335.3,846.668 2337.56,865.089 2339.83,884.8 2342.09,905.534 2344.35,927.081 2346.61,949.205 2348.88,971.688 2351.14,994.338 2353.4,1016.98 2355.67,1039.47 2357.93,1061.66 2360.19,1083.47 2362.45,1104.79 2364.72,1125.57 2366.98,1145.76 2369.24,1165.29 2371.5,1184.14 2373.77,1202.29 2376.03,1219.71 2378.29,1236.41 2380.55,1252.38 2382.82,1267.63 2385.08,1282.16 2387.34,1295.98 2389.6,1309.11 2391.87,1321.59 2394.13,1333.42 2396.39,1344.63 2398.66,1355.25 2400.92,1365.3 2403.18,1374.8 2405.44,1383.78 2407.71,1392.26 2409.97,1400.27 2412.23,1407.82 2414.49,1414.95 2416.76,1421.67 2419.02,1428 2421.28,1433.96 2423.54,1439.58 2425.81,1444.87 2428.07,1449.85 2430.33,1454.54 2432.59,1458.95 2434.86,1463.09 2437.12,1467 2439.38,1470.66 2441.65,1474.11 2443.91,1477.35 2446.17,1480.4 2448.43,1483.26 2450.7,1485.94 2452.96,1488.46 2455.22,1490.81 2457.48,1493.02 2459.75,1495.08 2462.01,1497.01 2464.27,1498.8 2466.53,1500.47 2468.8,1502.03 2471.06,1503.47 2473.32,1504.8 2475.58,1506.03 2477.85,1507.15 2480.11,1508.19 2482.37,1509.12 2484.63,1509.97 2486.9,1510.73 2489.16,1511.4 2491.42,1511.98 2493.69,1512.48 2495.95,1512.89 2498.21,1513.22 2500.47,1513.46 2502.74,1513.62 2505,1513.69 2507.26,1513.67 2509.52,1513.57 2511.79,1513.37 2514.05,1513.08 2516.31,1512.7 2518.57,1512.2 2520.84,1511.6 2523.1,1510.89 2525.36,1510.05 2527.62,1509.08 2529.89,1507.97 2532.15,1506.71 2534.41,1505.29 2536.68,1503.68 2538.94,1501.86 2541.2,1499.83 2543.46,1497.57 2545.73,1495.07 2547.99,1492.31 2550.25,1489.27 2552.51,1485.91 2554.78,1482.21 2557.04,1478.11 2559.3,1473.57 2561.56,1468.55 2563.83,1462.99 2566.09,1456.82 2568.35,1449.99 2570.61,1442.41 2572.88,1434.01 2575.14,1424.72 2577.4,1414.44 2579.67,1403.08 2581.93,1390.54 2584.19,1376.73 2586.45,1361.53 2588.72,1344.86 2590.98,1326.6 2593.24,1306.63 2595.5,1284.9 2597.77,1261.38 2600.03,1236.1 2602.29,1209.13 2604.55,1180.59 2606.82,1150.65 2609.08,1119.51 2611.34,1087.44 2613.6,1054.73 2615.87,1021.76 2618.13,989.152 2620.39,957.483 2622.65,927.292 2624.92,899.068 2627.18,873.251 2629.44,850.232 2631.71,830.353 2633.97,813.907 2636.23,801.138 2638.49,792.216 2640.76,787.068 "></polyline>
<polyline clip-path="url(#clip232)" style="stroke:#3da44d; stroke-linecap:round; stroke-linejoin:round; stroke-width:8; stroke-opacity:1; fill:none" points="380.396,1534.54 382.659,1534.98 384.921,1535.38 387.184,1535.74 389.446,1536.05 391.709,1536.3 393.972,1536.5 396.234,1536.64 398.497,1536.72 400.76,1536.72 403.022,1536.65 405.285,1536.5 407.547,1536.26 409.81,1535.92 412.073,1535.46 414.335,1534.89 416.598,1534.18 418.861,1533.32 421.123,1532.31 423.386,1531.11 425.648,1529.73 427.911,1528.14 430.174,1526.32 432.436,1524.27 434.699,1521.97 436.961,1519.41 439.224,1516.58 441.487,1513.47 443.749,1510.09 446.012,1506.44 448.275,1502.52 450.537,1498.36 452.8,1493.98 455.062,1489.39 457.325,1484.64 459.588,1479.75 461.85,1474.78 464.113,1469.76 466.376,1464.74 468.638,1459.76 470.901,1454.88 473.163,1450.13 475.426,1445.56 477.689,1441.21 479.951,1437.12 482.214,1433.31 484.477,1429.81 486.739,1426.64 489.002,1423.82 491.264,1421.35 493.527,1419.24 495.79,1417.5 498.052,1416.11 500.315,1415.07 502.578,1414.37 504.84,1414 507.103,1413.94 509.365,1414.17 511.628,1414.68 513.891,1415.44 516.153,1416.45 518.416,1417.67 520.679,1419.09 522.941,1420.68 525.204,1422.44 527.466,1424.34 529.729,1426.37 531.992,1428.5 534.254,1430.74 536.517,1433.05 538.779,1435.43 541.042,1437.87 543.305,1440.34 545.567,1442.85 547.83,1445.39 550.093,1447.94 552.355,1450.49 554.618,1453.05 556.88,1455.59 559.143,1458.13 561.406,1460.64 563.668,1463.14 565.931,1465.6 568.194,1468.04 570.456,1470.44 572.719,1472.81 574.981,1475.14 577.244,1477.43 579.507,1479.68 581.769,1481.88 584.032,1484.04 586.295,1486.16 588.557,1488.22 590.82,1490.25 593.082,1492.22 595.345,1494.15 597.608,1496.03 599.87,1497.86 602.133,1499.65 604.396,1501.39 606.658,1503.09 608.921,1504.74 611.183,1506.34 613.446,1507.9 615.709,1509.42 617.971,1510.89 620.234,1512.32 622.497,1513.71 624.759,1515.05 627.022,1516.36 629.284,1517.63 631.547,1518.85 633.81,1520.04 636.072,1521.19 638.335,1522.3 640.598,1523.38 642.86,1524.42 645.123,1525.43 647.385,1526.4 649.648,1527.33 651.911,1528.23 654.173,1529.1 656.436,1529.94 658.698,1530.74 660.961,1531.51 663.224,1532.25 665.486,1532.96 667.749,1533.63 670.012,1534.27 672.274,1534.88 674.537,1535.46 676.799,1536 679.062,1536.52 681.325,1536.99 683.587,1537.44 685.85,1537.84 688.113,1538.21 690.375,1538.54 692.638,1538.83 694.9,1539.07 697.163,1539.26 699.426,1539.4 701.688,1539.49 703.951,1539.51 706.214,1539.47 708.476,1539.36 710.739,1539.18 713.001,1538.92 715.264,1538.56 717.527,1538.11 719.789,1537.54 722.052,1536.84 724.315,1536 726.577,1535.02 728.84,1533.88 731.102,1532.56 733.365,1531.06 735.628,1529.36 737.89,1527.44 740.153,1525.31 742.416,1522.94 744.678,1520.33 746.941,1517.48 749.203,1514.4 751.466,1511.09 753.729,1507.55 755.991,1503.82 758.254,1499.89 760.517,1495.8 762.779,1491.58 765.042,1487.24 767.304,1482.85 769.567,1478.42 771.83,1474.01 774.092,1469.65 776.355,1465.38 778.617,1461.24 780.88,1457.25 783.143,1453.47 785.405,1449.91 787.668,1446.6 789.931,1443.57 792.193,1440.82 794.456,1438.37 796.718,1436.22 798.981,1434.39 801.244,1432.88 803.506,1431.67 805.769,1430.77 808.032,1430.16 810.294,1429.84 812.557,1429.79 814.819,1429.99 817.082,1430.43 819.345,1431.1 821.607,1431.97 823.87,1433.03 826.133,1434.26 828.395,1435.66 830.658,1437.2 832.92,1438.86 835.183,1440.64 837.446,1442.52 839.708,1444.48 841.971,1446.51 844.234,1448.61 846.496,1450.75 848.759,1452.93 851.021,1455.15 853.284,1457.39 855.547,1459.64 857.809,1461.9 860.072,1464.17 862.335,1466.42 864.597,1468.67 866.86,1470.91 869.122,1473.12 871.385,1475.31 873.648,1477.48 875.91,1479.62 878.173,1481.73 880.436,1483.81 882.698,1485.85 884.961,1487.85 887.223,1489.82 889.486,1491.75 891.749,1493.64 894.011,1495.49 896.274,1497.3 898.536,1499.06 900.799,1500.79 903.062,1502.47 905.324,1504.12 907.587,1505.72 909.85,1507.28 912.112,1508.8 914.375,1510.28 916.637,1511.72 918.9,1513.12 921.163,1514.48 923.425,1515.81 925.688,1517.09 927.951,1518.34 930.213,1519.55 932.476,1520.73 934.738,1521.87 937.001,1522.97 939.264,1524.04 941.526,1525.08 943.789,1526.08 946.052,1527.06 948.314,1527.99 950.577,1528.9 952.839,1529.78 955.102,1530.62 957.365,1531.44 959.627,1532.23 961.89,1532.99 964.153,1533.72 966.415,1534.42 968.678,1535.09 970.94,1535.73 973.203,1536.35 975.466,1536.93 977.728,1537.49 979.991,1538.02 982.254,1538.53 984.516,1539 986.779,1539.44 989.041,1539.86 991.304,1540.24 993.567,1540.59 995.829,1540.91 998.092,1541.19 1000.35,1541.44 1002.62,1541.65 1004.88,1541.82 1007.14,1541.94 1009.41,1542.01 1011.67,1542.03 1013.93,1541.99 1016.19,1541.89 1018.46,1541.73 1020.72,1541.49 1022.98,1541.18 1025.24,1540.77 1027.51,1540.27 1029.77,1539.66 1032.03,1538.93 1034.29,1538.07 1036.56,1537.07 1038.82,1535.91 1041.08,1534.6 1043.34,1533.12 1045.61,1531.45 1047.87,1529.6 1050.13,1527.54 1052.39,1525.28 1054.66,1522.81 1056.92,1520.13 1059.18,1517.25 1061.45,1514.18 1063.71,1510.92 1065.97,1507.5 1068.23,1503.94 1070.5,1500.25 1072.76,1496.46 1075.02,1492.62 1077.28,1488.74 1079.55,1484.86 1081.81,1481.01 1084.07,1477.23 1086.33,1473.55 1088.6,1470 1090.86,1466.62 1093.12,1463.41 1095.38,1460.42 1097.65,1457.65 1099.91,1455.12 1102.17,1452.85 1104.44,1450.85 1106.7,1449.12 1108.96,1447.66 1111.22,1446.46 1113.49,1445.53 1115.75,1444.85 1118.01,1444.43 1120.27,1444.25 1122.54,1444.3 1124.8,1444.56 1127.06,1445.03 1129.32,1445.69 1131.59,1446.52 1133.85,1447.52 1136.11,1448.65 1138.37,1449.92 1140.64,1451.32 1142.9,1452.81 1145.16,1454.4 1147.42,1456.08 1149.69,1457.83 1151.95,1459.63 1154.21,1461.49 1156.48,1463.4 1158.74,1465.33 1161,1467.29 1163.26,1469.27 1165.53,1471.26 1167.79,1473.26 1170.05,1475.26 1172.31,1477.25 1174.58,1479.23 1176.84,1481.2 1179.1,1483.16 1181.36,1485.09 1183.63,1487.01 1185.89,1488.89 1188.15,1490.75 1190.41,1492.58 1192.68,1494.38 1194.94,1496.15 1197.2,1497.89 1199.47,1499.59 1201.73,1501.26 1203.99,1502.89 1206.25,1504.49 1208.52,1506.05 1210.78,1507.57 1213.04,1509.06 1215.3,1510.51 1217.57,1511.93 1219.83,1513.31 1222.09,1514.65 1224.35,1515.96 1226.62,1517.23 1228.88,1518.47 1231.14,1519.68 1233.4,1520.85 1235.67,1521.99 1237.93,1523.09 1240.19,1524.16 1242.46,1525.2 1244.72,1526.21 1246.98,1527.19 1249.24,1528.14 1251.51,1529.06 1253.77,1529.95 1256.03,1530.81 1258.29,1531.64 1260.56,1532.44 1262.82,1533.22 1265.08,1533.97 1267.34,1534.7 1269.61,1535.39 1271.87,1536.07 1274.13,1536.71 1276.39,1537.33 1278.66,1537.93 1280.92,1538.5 1283.18,1539.05 1285.44,1539.58 1287.71,1540.08 1289.97,1540.55 1292.23,1541 1294.5,1541.43 1296.76,1541.83 1299.02,1542.2 1301.28,1542.54 1303.55,1542.86 1305.81,1543.14 1308.07,1543.4 1310.33,1543.62 1312.6,1543.82 1314.86,1543.97 1317.12,1544.09 1319.38,1544.17 1321.65,1544.21 1323.91,1544.2 1326.17,1544.14 1328.43,1544.02 1330.7,1543.84 1332.96,1543.59 1335.22,1543.27 1337.49,1542.86 1339.75,1542.37 1342.01,1541.78 1344.27,1541.08 1346.54,1540.26 1348.8,1539.32 1351.06,1538.24 1353.32,1537.01 1355.59,1535.63 1357.85,1534.1 1360.11,1532.39 1362.37,1530.51 1364.64,1528.45 1366.9,1526.21 1369.16,1523.79 1371.42,1521.19 1373.69,1518.44 1375.95,1515.53 1378.21,1512.49 1380.48,1509.32 1382.74,1506.07 1385,1502.73 1387.26,1499.35 1389.53,1495.95 1391.79,1492.56 1394.05,1489.2 1396.31,1485.9 1398.58,1482.7 1400.84,1479.63 1403.1,1476.69 1405.36,1473.92 1407.63,1471.33 1409.89,1468.94 1412.15,1466.76 1414.41,1464.81 1416.68,1463.08 1418.94,1461.59 1421.2,1460.34 1423.46,1459.31 1425.73,1458.51 1427.99,1457.94 1430.25,1457.58 1432.52,1457.42 1434.78,1457.47 1437.04,1457.71 1439.3,1458.12 1441.57,1458.69 1443.83,1459.42 1446.09,1460.29 1448.35,1461.28 1450.62,1462.39 1452.88,1463.61 1455.14,1464.92 1457.4,1466.31 1459.67,1467.78 1461.93,1469.31 1464.19,1470.89 1466.45,1472.52 1468.72,1474.19 1470.98,1475.89 1473.24,1477.61 1475.51,1479.35 1477.77,1481.11 1480.03,1482.86 1482.29,1484.62 1484.56,1486.38 1486.82,1488.13 1489.08,1489.87 1491.34,1491.6 1493.61,1493.31 1495.87,1495 1498.13,1496.67 1500.39,1498.31 1502.66,1499.93 1504.92,1501.53 1507.18,1503.1 1509.44,1504.63 1511.71,1506.14 1513.97,1507.62 1516.23,1509.07 1518.5,1510.49 1520.76,1511.88 1523.02,1513.23 1525.28,1514.56 1527.55,1515.85 1529.81,1517.11 1532.07,1518.33 1534.33,1519.53 1536.6,1520.7 1538.86,1521.83 1541.12,1522.93 1543.38,1524.01 1545.65,1525.05 1547.91,1526.07 1550.17,1527.05 1552.43,1528.01 1554.7,1528.94 1556.96,1529.84 1559.22,1530.71 1561.48,1531.56 1563.75,1532.38 1566.01,1533.18 1568.27,1533.95 1570.54,1534.69 1572.8,1535.41 1575.06,1536.11 1577.32,1536.78 1579.59,1537.43 1581.85,1538.06 1584.11,1538.66 1586.37,1539.24 1588.64,1539.8 1590.9,1540.34 1593.16,1540.85 1595.42,1541.35 1597.69,1541.82 1599.95,1542.27 1602.21,1542.7 1604.47,1543.11 1606.74,1543.5 1609,1543.86 1611.26,1544.2 1613.53,1544.52 1615.79,1544.82 1618.05,1545.09 1620.31,1545.33 1622.58,1545.55 1624.84,1545.74 1627.1,1545.89 1629.36,1546.02 1631.63,1546.12 1633.89,1546.18 1636.15,1546.2 1638.41,1546.18 1640.68,1546.12 1642.94,1546 1645.2,1545.83 1647.46,1545.6 1649.73,1545.31 1651.99,1544.94 1654.25,1544.49 1656.52,1543.96 1658.78,1543.33 1661.04,1542.6 1663.3,1541.76 1665.57,1540.79 1667.83,1539.71 1670.09,1538.48 1672.35,1537.12 1674.62,1535.61 1676.88,1533.96 1679.14,1532.14 1681.4,1530.17 1683.67,1528.04 1685.93,1525.76 1688.19,1523.35 1690.45,1520.8 1692.72,1518.14 1694.98,1515.37 1697.24,1512.52 1699.5,1509.61 1701.77,1506.65 1704.03,1503.68 1706.29,1500.71 1708.56,1497.76 1710.82,1494.88 1713.08,1492.07 1715.34,1489.37 1717.61,1486.78 1719.87,1484.34 1722.13,1482.05 1724.39,1479.93 1726.66,1477.99 1728.92,1476.24 1731.18,1474.69 1733.44,1473.34 1735.71,1472.19 1737.97,1471.24 1740.23,1470.49 1742.49,1469.93 1744.76,1469.56 1747.02,1469.38 1749.28,1469.37 1751.55,1469.52 1753.81,1469.83 1756.07,1470.29 1758.33,1470.88 1760.6,1471.6 1762.86,1472.43 1765.12,1473.36 1767.38,1474.39 1769.65,1475.51 1771.91,1476.7 1774.17,1477.96 1776.43,1479.28 1778.7,1480.65 1780.96,1482.07 1783.22,1483.52 1785.48,1485 1787.75,1486.5 1790.01,1488.02 1792.27,1489.56 1794.54,1491.1 1796.8,1492.65 1799.06,1494.19 1801.32,1495.74 1803.59,1497.27 1805.85,1498.79 1808.11,1500.31 1810.37,1501.8 1812.64,1503.28 1814.9,1504.74 1817.16,1506.18 1819.42,1507.6 1821.69,1508.99 1823.95,1510.36 1826.21,1511.7 1828.47,1513.02 1830.74,1514.31 1833,1515.58 1835.26,1516.81 1837.52,1518.02 1839.79,1519.21 1842.05,1520.36 1844.31,1521.49 1846.58,1522.59 1848.84,1523.66 1851.1,1524.7 1853.36,1525.72 1855.63,1526.71 1857.89,1527.67 1860.15,1528.6 1862.41,1529.51 1864.68,1530.4 1866.94,1531.26 1869.2,1532.09 1871.46,1532.9 1873.73,1533.69 1875.99,1534.45 1878.25,1535.19 1880.51,1535.91 1882.78,1536.6 1885.04,1537.27 1887.3,1537.92 1889.57,1538.55 1891.83,1539.16 1894.09,1539.75 1896.35,1540.31 1898.62,1540.86 1900.88,1541.39 1903.14,1541.89 1905.4,1542.38 1907.67,1542.85 1909.93,1543.3 1912.19,1543.73 1914.45,1544.14 1916.72,1544.54 1918.98,1544.91 1921.24,1545.27 1923.5,1545.61 1925.77,1545.93 1928.03,1546.22 1930.29,1546.5 1932.56,1546.76 1934.82,1547 1937.08,1547.21 1939.34,1547.4 1941.61,1547.56 1943.87,1547.7 1946.13,1547.82 1948.39,1547.9 1950.66,1547.96 1952.92,1547.98 1955.18,1547.96 1957.44,1547.91 1959.71,1547.81 1961.97,1547.66 1964.23,1547.47 1966.49,1547.21 1968.76,1546.9 1971.02,1546.51 1973.28,1546.06 1975.54,1545.52 1977.81,1544.89 1980.07,1544.17 1982.33,1543.34 1984.6,1542.41 1986.86,1541.36 1989.12,1540.19 1991.38,1538.9 1993.65,1537.47 1995.91,1535.92 1998.17,1534.22 2000.43,1532.39 2002.7,1530.43 2004.96,1528.35 2007.22,1526.15 2009.48,1523.85 2011.75,1521.46 2014.01,1518.99 2016.27,1516.46 2018.53,1513.89 2020.8,1511.29 2023.06,1508.7 2025.32,1506.12 2027.59,1503.58 2029.85,1501.1 2032.11,1498.71 2034.37,1496.41 2036.64,1494.23 2038.9,1492.17 2041.16,1490.26 2043.42,1488.49 2045.69,1486.89 2047.95,1485.46 2050.21,1484.2 2052.47,1483.11 2054.74,1482.2 2057,1481.46 2059.26,1480.88 2061.52,1480.47 2063.79,1480.23 2066.05,1480.13 2068.31,1480.19 2070.58,1480.39 2072.84,1480.71 2075.1,1481.16 2077.36,1481.72 2079.63,1482.39 2081.89,1483.15 2084.15,1484 2086.41,1484.93 2088.68,1485.93 2090.94,1486.99 2093.2,1488.11 2095.46,1489.29 2097.73,1490.5 2099.99,1491.75 2102.25,1493.03 2104.51,1494.33 2106.78,1495.65 2109.04,1496.99 2111.3,1498.34 2113.56,1499.69 2115.83,1501.05 2118.09,1502.4 2120.35,1503.75 2122.62,1505.1 2124.88,1506.43 2127.14,1507.75 2129.4,1509.06 2131.67,1510.36 2133.93,1511.63 2136.19,1512.89 2138.45,1514.13 2140.72,1515.35 2142.98,1516.55 2145.24,1517.72 2147.5,1518.88 2149.77,1520.01 2152.03,1521.11 2154.29,1522.19 2156.55,1523.25 2158.82,1524.29 2161.08,1525.3 2163.34,1526.28 2165.61,1527.24 2167.87,1528.18 2170.13,1529.1 2172.39,1529.98 2174.66,1530.85 2176.92,1531.69 2179.18,1532.51 2181.44,1533.31 2183.71,1534.09 2185.97,1534.84 2188.23,1535.57 2190.49,1536.28 2192.76,1536.97 2195.02,1537.64 2197.28,1538.28 2199.54,1538.91 2201.81,1539.52 2204.07,1540.11 2206.33,1540.68 2208.59,1541.23 2210.86,1541.76 2213.12,1542.28 2215.38,1542.77 2217.65,1543.25 2219.91,1543.71 2222.17,1544.16 2224.43,1544.59 2226.7,1545 2228.96,1545.39 2231.22,1545.77 2233.48,1546.14 2235.75,1546.48 2238.01,1546.81 2240.27,1547.13 2242.53,1547.42 2244.8,1547.7 2247.06,1547.97 2249.32,1548.21 2251.58,1548.44 2253.85,1548.65 2256.11,1548.84 2258.37,1549.01 2260.64,1549.16 2262.9,1549.28 2265.16,1549.39 2267.42,1549.47 2269.69,1549.52 2271.95,1549.55 2274.21,1549.54 2276.47,1549.5 2278.74,1549.43 2281,1549.31 2283.26,1549.15 2285.52,1548.94 2287.79,1548.68 2290.05,1548.36 2292.31,1547.98 2294.57,1547.54 2296.84,1547.01 2299.1,1546.41 2301.36,1545.72 2303.63,1544.93 2305.89,1544.05 2308.15,1543.07 2310.41,1541.98 2312.68,1540.78 2314.94,1539.46 2317.2,1538.03 2319.46,1536.48 2321.73,1534.81 2323.99,1533.04 2326.25,1531.16 2328.51,1529.19 2330.78,1527.14 2333.04,1525.02 2335.3,1522.84 2337.56,1520.61 2339.83,1518.36 2342.09,1516.1 2344.35,1513.84 2346.61,1511.61 2348.88,1509.42 2351.14,1507.3 2353.4,1505.25 2355.67,1503.29 2357.93,1501.44 2360.19,1499.7 2362.45,1498.09 2364.72,1496.61 2366.98,1495.27 2369.24,1494.08 2371.5,1493.04 2373.77,1492.15 2376.03,1491.4 2378.29,1490.81 2380.55,1490.36 2382.82,1490.05 2385.08,1489.87 2387.34,1489.83 2389.6,1489.92 2391.87,1490.12 2394.13,1490.43 2396.39,1490.85 2398.66,1491.37 2400.92,1491.97 2403.18,1492.65 2405.44,1493.41 2407.71,1494.24 2409.97,1495.12 2412.23,1496.06 2414.49,1497.05 2416.76,1498.08 2419.02,1499.15 2421.28,1500.24 2423.54,1501.37 2425.81,1502.51 2428.07,1503.67 2430.33,1504.84 2432.59,1506.02 2434.86,1507.2 2437.12,1508.39 2439.38,1509.57 2441.65,1510.75 2443.91,1511.93 2446.17,1513.09 2448.43,1514.25 2450.7,1515.4 2452.96,1516.53 2455.22,1517.64 2457.48,1518.74 2459.75,1519.83 2462.01,1520.89 2464.27,1521.94 2466.53,1522.97 2468.8,1523.98 2471.06,1524.97 2473.32,1525.93 2475.58,1526.88 2477.85,1527.81 2480.11,1528.71 2482.37,1529.6 2484.63,1530.46 2486.9,1531.3 2489.16,1532.12 2491.42,1532.92 2493.69,1533.7 2495.95,1534.46 2498.21,1535.2 2500.47,1535.92 2502.74,1536.62 2505,1537.3 2507.26,1537.96 2509.52,1538.6 2511.79,1539.22 2514.05,1539.82 2516.31,1540.41 2518.57,1540.98 2520.84,1541.53 2523.1,1542.06 2525.36,1542.58 2527.62,1543.08 2529.89,1543.56 2532.15,1544.03 2534.41,1544.48 2536.68,1544.92 2538.94,1545.34 2541.2,1545.75 2543.46,1546.14 2545.73,1546.51 2547.99,1546.88 2550.25,1547.22 2552.51,1547.56 2554.78,1547.88 2557.04,1548.18 2559.3,1548.47 2561.56,1548.75 2563.83,1549.01 2566.09,1549.26 2568.35,1549.5 2570.61,1549.71 2572.88,1549.92 2575.14,1550.1 2577.4,1550.27 2579.67,1550.42 2581.93,1550.56 2584.19,1550.67 2586.45,1550.77 2588.72,1550.85 2590.98,1550.9 2593.24,1550.93 2595.5,1550.93 2597.77,1550.91 2600.03,1550.85 2602.29,1550.76 2604.55,1550.64 2606.82,1550.47 2609.08,1550.26 2611.34,1550 2613.6,1549.69 2615.87,1549.32 2618.13,1548.89 2620.39,1548.39 2622.65,1547.82 2624.92,1547.17 2627.18,1546.44 2629.44,1545.62 2631.71,1544.71 2633.97,1543.71 2636.23,1542.61 2638.49,1541.4 2640.76,1540.1 "></polyline>
<path clip-path="url(#clip230)" d="M2142.34 383.972 L2565.41 383.972 L2565.41 176.612 L2142.34 176.612  Z" fill="#ffffff" fill-rule="evenodd" fill-opacity="1"></path>
<polyline clip-path="url(#clip230)" style="stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-width:4; stroke-opacity:1; fill:none" points="2142.34,383.972 2565.41,383.972 2565.41,176.612 2142.34,176.612 2142.34,383.972 "></polyline>
<polyline clip-path="url(#clip230)" style="stroke:#009af9; stroke-linecap:round; stroke-linejoin:round; stroke-width:8; stroke-opacity:1; fill:none" points="2167.45,228.452 2318.14,228.452 "></polyline>
<path clip-path="url(#clip230)" d="M2343.26 209.714 L2347.52 209.714 L2347.52 245.732 L2343.26 245.732 L2343.26 209.714 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2356.43 219.806 L2360.69 219.806 L2360.69 245.732 L2356.43 245.732 L2356.43 219.806 M2356.43 209.714 L2360.69 209.714 L2360.69 215.107 L2356.43 215.107 L2356.43 209.714 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2373.81 212.445 L2373.81 219.806 L2382.59 219.806 L2382.59 223.116 L2373.81 223.116 L2373.81 237.19 Q2373.81 240.362 2374.67 241.264 Q2375.55 242.167 2378.21 242.167 L2382.59 242.167 L2382.59 245.732 L2378.21 245.732 Q2373.28 245.732 2371.41 243.903 Q2369.53 242.051 2369.53 237.19 L2369.53 223.116 L2366.41 223.116 L2366.41 219.806 L2369.53 219.806 L2369.53 212.445 L2373.81 212.445 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2392.4 212.445 L2392.4 219.806 L2401.18 219.806 L2401.18 223.116 L2392.4 223.116 L2392.4 237.19 Q2392.4 240.362 2393.26 241.264 Q2394.14 242.167 2396.8 242.167 L2401.18 242.167 L2401.18 245.732 L2396.8 245.732 Q2391.87 245.732 2390 243.903 Q2388.12 242.051 2388.12 237.19 L2388.12 223.116 L2385 223.116 L2385 219.806 L2388.12 219.806 L2388.12 212.445 L2392.4 212.445 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2406.78 209.714 L2411.04 209.714 L2411.04 245.732 L2406.78 245.732 L2406.78 209.714 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2442.12 231.704 L2442.12 233.787 L2422.54 233.787 Q2422.82 238.186 2425.18 240.5 Q2427.56 242.792 2431.8 242.792 Q2434.25 242.792 2436.55 242.19 Q2438.86 241.588 2441.13 240.385 L2441.13 244.412 Q2438.84 245.385 2436.43 245.894 Q2434.02 246.403 2431.55 246.403 Q2425.34 246.403 2421.71 242.792 Q2418.1 239.181 2418.1 233.024 Q2418.1 226.658 2421.52 222.931 Q2424.97 219.181 2430.81 219.181 Q2436.04 219.181 2439.07 222.561 Q2442.12 225.917 2442.12 231.704 M2437.87 230.454 Q2437.82 226.959 2435.9 224.876 Q2434 222.792 2430.85 222.792 Q2427.29 222.792 2425.13 224.806 Q2423 226.82 2422.68 230.477 L2437.87 230.454 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2477.31 209.714 L2477.31 213.255 L2473.24 213.255 Q2470.94 213.255 2470.04 214.181 Q2469.16 215.107 2469.16 217.514 L2469.16 219.806 L2476.18 219.806 L2476.18 223.116 L2469.16 223.116 L2469.16 245.732 L2464.88 245.732 L2464.88 223.116 L2460.81 223.116 L2460.81 219.806 L2464.88 219.806 L2464.88 218.001 Q2464.88 213.672 2466.89 211.704 Q2468.91 209.714 2473.28 209.714 L2477.31 209.714 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2480.87 219.806 L2485.13 219.806 L2485.13 245.732 L2480.87 245.732 L2480.87 219.806 M2480.87 209.714 L2485.13 209.714 L2485.13 215.107 L2480.87 215.107 L2480.87 209.714 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2510.57 220.57 L2510.57 224.598 Q2508.77 223.672 2506.82 223.209 Q2504.88 222.746 2502.8 222.746 Q2499.62 222.746 2498.03 223.718 Q2496.45 224.69 2496.45 226.635 Q2496.45 228.116 2497.59 228.973 Q2498.72 229.806 2502.15 230.57 L2503.61 230.894 Q2508.14 231.866 2510.04 233.649 Q2511.96 235.408 2511.96 238.579 Q2511.96 242.19 2509.09 244.297 Q2506.24 246.403 2501.24 246.403 Q2499.16 246.403 2496.89 245.987 Q2494.65 245.593 2492.15 244.783 L2492.15 240.385 Q2494.51 241.612 2496.8 242.237 Q2499.09 242.838 2501.34 242.838 Q2504.35 242.838 2505.97 241.82 Q2507.59 240.778 2507.59 238.903 Q2507.59 237.167 2506.41 236.241 Q2505.25 235.315 2501.29 234.459 L2499.81 234.112 Q2495.85 233.278 2494.09 231.565 Q2492.33 229.829 2492.33 226.82 Q2492.33 223.163 2494.93 221.172 Q2497.52 219.181 2502.29 219.181 Q2504.65 219.181 2506.73 219.528 Q2508.81 219.876 2510.57 220.57 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2540.3 230.084 L2540.3 245.732 L2536.04 245.732 L2536.04 230.223 Q2536.04 226.542 2534.6 224.713 Q2533.17 222.885 2530.3 222.885 Q2526.85 222.885 2524.86 225.084 Q2522.86 227.283 2522.86 231.079 L2522.86 245.732 L2518.58 245.732 L2518.58 209.714 L2522.86 209.714 L2522.86 223.834 Q2524.39 221.496 2526.45 220.338 Q2528.54 219.181 2531.24 219.181 Q2535.71 219.181 2538 221.959 Q2540.3 224.713 2540.3 230.084 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><polyline clip-path="url(#clip230)" style="stroke:#e26f46; stroke-linecap:round; stroke-linejoin:round; stroke-width:8; stroke-opacity:1; fill:none" points="2167.45,280.292 2318.14,280.292 "></polyline>
<path clip-path="url(#clip230)" d="M2362.03 284.632 Q2362.03 279.933 2360.09 277.271 Q2358.17 274.586 2354.79 274.586 Q2351.41 274.586 2349.46 277.271 Q2347.54 279.933 2347.54 284.632 Q2347.54 289.331 2349.46 292.016 Q2351.41 294.678 2354.79 294.678 Q2358.17 294.678 2360.09 292.016 Q2362.03 289.331 2362.03 284.632 M2347.54 275.581 Q2348.88 273.266 2350.92 272.155 Q2352.98 271.021 2355.83 271.021 Q2360.55 271.021 2363.49 274.771 Q2366.45 278.521 2366.45 284.632 Q2366.45 290.743 2363.49 294.493 Q2360.55 298.243 2355.83 298.243 Q2352.98 298.243 2350.92 297.132 Q2348.88 295.998 2347.54 293.683 L2347.54 297.572 L2343.26 297.572 L2343.26 261.554 L2347.54 261.554 L2347.54 275.581 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2373.51 271.646 L2377.77 271.646 L2377.77 297.572 L2373.51 297.572 L2373.51 271.646 M2373.51 261.554 L2377.77 261.554 L2377.77 266.947 L2373.51 266.947 L2373.51 261.554 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2403.75 284.308 Q2403.75 279.678 2401.82 277.132 Q2399.93 274.586 2396.48 274.586 Q2393.05 274.586 2391.13 277.132 Q2389.23 279.678 2389.23 284.308 Q2389.23 288.915 2391.13 291.461 Q2393.05 294.007 2396.48 294.007 Q2399.93 294.007 2401.82 291.461 Q2403.75 288.915 2403.75 284.308 M2408 294.354 Q2408 300.975 2405.06 304.192 Q2402.12 307.433 2396.06 307.433 Q2393.81 307.433 2391.82 307.086 Q2389.83 306.762 2387.96 306.067 L2387.96 301.924 Q2389.83 302.942 2391.66 303.428 Q2393.49 303.914 2395.39 303.914 Q2399.58 303.914 2401.66 301.715 Q2403.75 299.539 2403.75 295.118 L2403.75 293.012 Q2402.43 295.303 2400.37 296.438 Q2398.31 297.572 2395.44 297.572 Q2390.67 297.572 2387.75 293.938 Q2384.83 290.303 2384.83 284.308 Q2384.83 278.29 2387.75 274.655 Q2390.67 271.021 2395.44 271.021 Q2398.31 271.021 2400.37 272.155 Q2402.43 273.29 2403.75 275.581 L2403.75 271.646 L2408 271.646 L2408 294.354 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2444.97 261.554 L2444.97 265.095 L2440.9 265.095 Q2438.61 265.095 2437.7 266.021 Q2436.82 266.947 2436.82 269.354 L2436.82 271.646 L2443.84 271.646 L2443.84 274.956 L2436.82 274.956 L2436.82 297.572 L2432.54 297.572 L2432.54 274.956 L2428.47 274.956 L2428.47 271.646 L2432.54 271.646 L2432.54 269.841 Q2432.54 265.512 2434.56 263.544 Q2436.57 261.554 2440.94 261.554 L2444.97 261.554 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2448.54 271.646 L2452.8 271.646 L2452.8 297.572 L2448.54 297.572 L2448.54 271.646 M2448.54 261.554 L2452.8 261.554 L2452.8 266.947 L2448.54 266.947 L2448.54 261.554 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2478.24 272.41 L2478.24 276.438 Q2476.43 275.512 2474.49 275.049 Q2472.54 274.586 2470.46 274.586 Q2467.29 274.586 2465.69 275.558 Q2464.12 276.53 2464.12 278.475 Q2464.12 279.956 2465.25 280.813 Q2466.38 281.646 2469.81 282.41 L2471.27 282.734 Q2475.81 283.706 2477.7 285.489 Q2479.62 287.248 2479.62 290.419 Q2479.62 294.03 2476.75 296.137 Q2473.91 298.243 2468.91 298.243 Q2466.82 298.243 2464.56 297.827 Q2462.31 297.433 2459.81 296.623 L2459.81 292.225 Q2462.17 293.452 2464.46 294.077 Q2466.75 294.678 2469 294.678 Q2472.01 294.678 2473.63 293.66 Q2475.25 292.618 2475.25 290.743 Q2475.25 289.007 2474.07 288.081 Q2472.91 287.155 2468.95 286.299 L2467.47 285.952 Q2463.51 285.118 2461.75 283.405 Q2459.99 281.669 2459.99 278.66 Q2459.99 275.003 2462.59 273.012 Q2465.18 271.021 2469.95 271.021 Q2472.31 271.021 2474.39 271.368 Q2476.48 271.716 2478.24 272.41 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2507.96 281.924 L2507.96 297.572 L2503.7 297.572 L2503.7 282.063 Q2503.7 278.382 2502.26 276.553 Q2500.83 274.725 2497.96 274.725 Q2494.51 274.725 2492.52 276.924 Q2490.53 279.123 2490.53 282.919 L2490.53 297.572 L2486.24 297.572 L2486.24 261.554 L2490.53 261.554 L2490.53 275.674 Q2492.05 273.336 2494.12 272.178 Q2496.2 271.021 2498.91 271.021 Q2503.37 271.021 2505.67 273.799 Q2507.96 276.553 2507.96 281.924 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><polyline clip-path="url(#clip230)" style="stroke:#3da44d; stroke-linecap:round; stroke-linejoin:round; stroke-width:8; stroke-opacity:1; fill:none" points="2167.45,332.132 2318.14,332.132 "></polyline>
<path clip-path="url(#clip230)" d="M2361.69 324.25 L2361.69 328.278 Q2359.88 327.352 2357.94 326.889 Q2355.99 326.426 2353.91 326.426 Q2350.74 326.426 2349.14 327.398 Q2347.57 328.37 2347.57 330.315 Q2347.57 331.796 2348.7 332.653 Q2349.83 333.486 2353.26 334.25 L2354.72 334.574 Q2359.25 335.546 2361.15 337.329 Q2363.07 339.088 2363.07 342.259 Q2363.07 345.87 2360.2 347.977 Q2357.36 350.083 2352.36 350.083 Q2350.27 350.083 2348 349.667 Q2345.76 349.273 2343.26 348.463 L2343.26 344.065 Q2345.62 345.292 2347.91 345.917 Q2350.2 346.518 2352.45 346.518 Q2355.46 346.518 2357.08 345.5 Q2358.7 344.458 2358.7 342.583 Q2358.7 340.847 2357.52 339.921 Q2356.36 338.995 2352.4 338.139 L2350.92 337.792 Q2346.96 336.958 2345.2 335.245 Q2343.44 333.509 2343.44 330.5 Q2343.44 326.843 2346.04 324.852 Q2348.63 322.861 2353.4 322.861 Q2355.76 322.861 2357.84 323.208 Q2359.93 323.556 2361.69 324.25 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2391.41 333.764 L2391.41 349.412 L2387.15 349.412 L2387.15 333.903 Q2387.15 330.222 2385.71 328.393 Q2384.28 326.565 2381.41 326.565 Q2377.96 326.565 2375.97 328.764 Q2373.98 330.963 2373.98 334.759 L2373.98 349.412 L2369.69 349.412 L2369.69 313.394 L2373.98 313.394 L2373.98 327.514 Q2375.5 325.176 2377.56 324.018 Q2379.65 322.861 2382.36 322.861 Q2386.82 322.861 2389.12 325.639 Q2391.41 328.393 2391.41 333.764 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2411.69 336.38 Q2406.52 336.38 2404.53 337.56 Q2402.54 338.741 2402.54 341.588 Q2402.54 343.856 2404.02 345.199 Q2405.53 346.518 2408.1 346.518 Q2411.64 346.518 2413.77 344.018 Q2415.92 341.495 2415.92 337.329 L2415.92 336.38 L2411.69 336.38 M2420.18 334.62 L2420.18 349.412 L2415.92 349.412 L2415.92 345.477 Q2414.46 347.838 2412.29 348.972 Q2410.11 350.083 2406.96 350.083 Q2402.98 350.083 2400.62 347.861 Q2398.28 345.616 2398.28 341.866 Q2398.28 337.491 2401.2 335.268 Q2404.14 333.046 2409.95 333.046 L2415.92 333.046 L2415.92 332.63 Q2415.92 329.69 2413.98 328.093 Q2412.06 326.472 2408.56 326.472 Q2406.34 326.472 2404.23 327.005 Q2402.12 327.537 2400.18 328.602 L2400.18 324.667 Q2402.52 323.764 2404.72 323.324 Q2406.92 322.861 2409 322.861 Q2414.62 322.861 2417.4 325.778 Q2420.18 328.694 2420.18 334.62 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2443.98 327.468 Q2443.26 327.051 2442.4 326.866 Q2441.57 326.657 2440.55 326.657 Q2436.94 326.657 2435 329.018 Q2433.07 331.356 2433.07 335.755 L2433.07 349.412 L2428.79 349.412 L2428.79 323.486 L2433.07 323.486 L2433.07 327.514 Q2434.42 325.153 2436.57 324.018 Q2438.72 322.861 2441.8 322.861 Q2442.24 322.861 2442.77 322.931 Q2443.31 322.977 2443.95 323.093 L2443.98 327.468 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2448.28 313.394 L2452.56 313.394 L2452.56 334.667 L2465.27 323.486 L2470.71 323.486 L2456.96 335.616 L2471.29 349.412 L2465.74 349.412 L2452.56 336.75 L2452.56 349.412 L2448.28 349.412 L2448.28 313.394 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path><path clip-path="url(#clip230)" d="M2492.43 324.25 L2492.43 328.278 Q2490.62 327.352 2488.68 326.889 Q2486.73 326.426 2484.65 326.426 Q2481.48 326.426 2479.88 327.398 Q2478.31 328.37 2478.31 330.315 Q2478.31 331.796 2479.44 332.653 Q2480.57 333.486 2484 334.25 L2485.46 334.574 Q2489.99 335.546 2491.89 337.329 Q2493.81 339.088 2493.81 342.259 Q2493.81 345.87 2490.94 347.977 Q2488.1 350.083 2483.1 350.083 Q2481.01 350.083 2478.74 349.667 Q2476.5 349.273 2474 348.463 L2474 344.065 Q2476.36 345.292 2478.65 345.917 Q2480.94 346.518 2483.19 346.518 Q2486.2 346.518 2487.82 345.5 Q2489.44 344.458 2489.44 342.583 Q2489.44 340.847 2488.26 339.921 Q2487.1 338.995 2483.14 338.139 L2481.66 337.792 Q2477.7 336.958 2475.94 335.245 Q2474.18 333.509 2474.18 330.5 Q2474.18 326.843 2476.78 324.852 Q2479.37 322.861 2484.14 322.861 Q2486.5 322.861 2488.58 323.208 Q2490.67 323.556 2492.43 324.25 Z" fill="#000000" fill-rule="nonzero" fill-opacity="1"></path></svg>
</div>
</div>
</section>
</section>
<section id="the-bigger-picture" class="level2">
<h2 class="anchored" data-anchor-id="the-bigger-picture">The bigger picture</h2>
<p>In this post, we discussed two theories of directed composition — <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BTh(SIPortGraph)%7D"> and <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BTh(Graph)%7D"> — which fit into the larger zoo of directed composition syntaxes.</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2021/01/machines/_svgs/242322579310c5bd64f7e7ada18d87ecc809c98e.svg" class="img-fluid">
</div>
<p>The functors between these theories define contravariant transformations between composition patterns in different syntaxes. The previous section exemplified this process applied to the functor from <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BTh(SIPortGraph)%7D"> to <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BTh(Graph)%7D">.</p>
<p>In the following subsections, we briefly describe the remaining theories of directed composition.</p>
<section id="port-graphs-and-circular-port-graphs" class="level3">
<h3 class="anchored" data-anchor-id="port-graphs-and-circular-port-graphs">Port graphs and circular port graphs</h3>
<p>Port graphs extend single-input port graphs by allowing in-ports to accept any number of incoming wires. In application, this means we can merge information (<img src="https://latex.codecogs.com/png.latex?+">) and generate trivial information (<img src="https://latex.codecogs.com/png.latex?0">). The schema for <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BSch%7D(%5Cmathsf%7BPortGraph%7D)"> is below.</p>
<div class="tikzcd">
<img src="https://blog.algebraicjulia.org/post/2021/01/machines/_svgs/6d44a783f99ab9bc3a95327b95a8b1348f59ef38.svg" class="img-fluid">
</div>
<p>Concretely, every port graph consists of a set of boxes. Each box has set of in-ports and a set of out-ports. A port graph also has a set of wires which connect out-ports to in-ports.</p>
<p>Circular port graphs<sup>5</sup> similarly consist of a set of boxes and a set of wires which connect ports, but they do not distinguish between in-ports and out-ports — a machine may both receive and emit information through any port. The functor from <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BTh(PortGraph)%7D"> to <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BTh(CPG)%7D"> turns circular port graphs into port graphs by duplicating every port with one copy interpretted as an in-port and the other as an out-port. Circular port graphs are particularly useful for modeling systems where the composition pattern is given by a network, such as a mesh of points in a reaction-diffusion model or a network of cities in a transportation grid. Such networks often arise in physics modeling.</p>
</section>
<section id="open-composition-syntaxes" class="level3">
<h3 class="anchored" data-anchor-id="open-composition-syntaxes">Open composition syntaxes</h3>
<p>The theories discussed so far generate <em>closed</em> composition patterns because they produce composite machine that have no inputs and no outputs. The composite machine is closed in the sense that it cannot interact with other machines.</p>
<p>In AlgebraicDynamics.jl, we implement two <em>open</em> theories for directed composition (1) directed wiring diagrams and (2) open circular port graphs, along with corresponding <code>oapply</code> methods.</p>
</section>
</section>
<section id="up-next" class="level2">
<h2 class="anchored" data-anchor-id="up-next">Up next</h2>
<p>In the next blog post of this series, we will investigate undirected theories for composition of dynamical systems as well as the strength of open composition syntaxes.</p>
</section>
<section id="appendix-pullback-functorial-data-migration" class="level2">
<h2 class="anchored" data-anchor-id="appendix-pullback-functorial-data-migration">Appendix: Pullback Functorial Data Migration</h2>
<p>f Let <img src="https://latex.codecogs.com/png.latex?F:%20%5Cmathsf%7BC%7D%20%5Cto%20%5Cmathsf%7BD%7D"> be a functor between categories <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D"> and <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BD%7D">. Then <img src="https://latex.codecogs.com/png.latex?F"> contravariantly induces a map from <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BD%7D">-sets to <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-sets by precomposition, which maps a <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BD%7D">-set <img src="https://latex.codecogs.com/png.latex?X:%20%5Cmathsf%7BD%7D%20%5Cto%20%5Cmathsf%7BSet%7D,"> to the <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BC%7D">-set <img src="https://latex.codecogs.com/png.latex?F%20%5Coperatorname%7B%E2%A8%9F%7DX%20:%20%5Cmathsf%7BC%7D%20%5Cto%20%5Cmathsf%7BSet%7D."> We call this transformation pulling back <img src="https://latex.codecogs.com/png.latex?X"> along <img src="https://latex.codecogs.com/png.latex?F">. We saw an example of migrating the data of a half-edge graph to the data of a symmetric graph and vice versa<sup>6</sup> in <a href="../../../../post/2020/09/cset-graphs-2/#relation_with_symmetric_graphs">a previous post</a>.</p>



</section>


<div id="quarto-appendix" class="default"><section class="quarto-appendix-contents" id="quarto-bibliography"><h2 class="anchored quarto-appendix-heading">References</h2><div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="0">
<div id="ref-1208.1513" class="csl-entry">
DeVille, Lee, and Eugene Lerman. 2012. <span>“Dynamics on Networks of Manifolds.”</span> <a href="https://doi.org/10.3842/SIGMA.2015.022">https://doi.org/10.3842/SIGMA.2015.022</a>.
</div>
<div id="ref-2007.14442" class="csl-entry">
Libkind, Sophie. 2020. <span>“An Algebra of Resource Sharing Machines.”</span>
</div>
<div id="ref-1609.08086" class="csl-entry">
Schultz, Patrick, David I. Spivak, and Christina Vasilakopoulou. 2016. <span>“Dynamical Systems and Sheaves.”</span>
</div>
<div id="ref-1408.1598" class="csl-entry">
Vagner, Dmitry, David I. Spivak, and Eugene Lerman. 2014. <span>“Algebras of Open Dynamical Systems on the Operad of Wiring Diagrams.”</span>
</div>
</div></section><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Footnotes</h2>

<ol>
<li id="fn1"><p>A third style of composition allows both directed and undirected communication. The composition theory for this style of communication is shown in orange above. We call dynamical systems that compose via both directed and undirect communcation <em>resource sharing machines</em> <span class="citation" data-cites="2007.14442">(Libkind 2020)</span>.↩︎</p></li>
<li id="fn2"><p>What does “filling a box” correspond to in the operadic setting? Consider the operad algebra <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BCDS%7D"> defined in <span class="citation" data-cites="1609.08086">(Schultz, Spivak, and Vasilakopoulou 2016)</span>. A box corresponds to a type <img src="https://latex.codecogs.com/png.latex?t"> in the operad, and a machine can fill the box if it corresponds to an element of <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BCDS%7D(t)">.↩︎</p></li>
<li id="fn3"><p>The method <code>oapply(d::SIPortGraph, xs::Vector{Machine{T}})</code> implements the operad algebra <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BCDS%7D"> defined in <span class="citation" data-cites="1609.08086">(Schultz, Spivak, and Vasilakopoulou 2016)</span> — see also <span class="citation" data-cites="1408.1598">(Vagner, Spivak, and Lerman 2014)</span> — restricted to the special case of morphisms where the codomain is the box with no incoming or outgoing wires. Such morphisms are equivalent to single-input port graphs. A generalization of the algebra <img src="https://latex.codecogs.com/png.latex?%5Cmathsf%7BCDS%7D"> to the operad of directed wiring diagrams is implemented in full in AlgebraicDynamics.jl.↩︎</p></li>
<li id="fn4"><p>This strategy is inspired by the composition of dynamical systems defined in <span class="citation" data-cites="1208.1513">(DeVille and Lerman 2012)</span>.↩︎</p></li>
<li id="fn5"><p>A note on the nomenclature. We draw the boxes of port graphs as squares with ports on the top edge indicating the in-ports and the ports on the bottom edge indicating the out-ports. Since there is no such distinction between ports of a circular port graph, we draw the boxes of a circular port graph as circles. While port graphs are established terminology in the computer science literature, circular port graphs are not.↩︎</p></li>
<li id="fn6"><p>In that particular example, we were able to migrate the data in both directions because the functor <img src="https://latex.codecogs.com/png.latex?F"> was invertible.↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>models</category>
  <category>attributed-c-sets</category>
  <category>dynamical systems</category>
  <guid>https://blog.algebraicjulia.org/post/2021/01/machines/</guid>
  <pubDate>Thu, 14 Jan 2021 00:00:00 GMT</pubDate>
</item>
</channel>
</rss>
