<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="https://www.w3.org/2005/Atom">

 <title>Breandan's Blog</title>
 <link href="breandan.net/atom.xml" rel="self"/>
 <link href="breandan.net/"/>
 <updated>2026-07-14T21:18:38+00:00</updated>
 <id>breandan.net</id>
 <author>
   <name>Breandan Considine</name>
   <email></email>
 </author>

 
 <entry>
   <title>Computation graphs and graph computation</title>
   <link href="breandan.net/2020/06/30/graph-computation/"/>
   <updated>2020-06-30T00:00:00+00:00</updated>
   <id>breandan.net/2020/06/30/graph-computation</id>
   <content type="html">&lt;p&gt;Research has begun to reveal many algorithms can be expressed as matrix multiplication, suggesting an unrealized connection between linear algebra and computer science. I speculate graphs are the missing piece of the puzzle. Graphs are not only useful as cognitive aides, but are suitable data structures for a wide variety of tasks, particularly on modern parallel processing hardware.&lt;/p&gt;

&lt;p&gt;In this essay, I explore the virtues of graphs, algebra, types, and show how these concepts can help us reason about programs. I propose a computational primitive based on graph signal processing, linking software engineering, graphs, and linear algebra. Finally, I share my predictions for the path ahead, which I consider to be the start of an exciting new chapter in computing history.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;n.b.: None of these ideas are mine alone. Shoulders of giants. Follow the links and use landscape mode for optimal reading experience.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#new-decade-new-delusions&quot;&gt;Biographical details&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#what-are-graphs&quot;&gt;Graph applications&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#induction-introduction&quot;&gt;Inductive languages&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#graphs-inductively&quot;&gt;Inductive graphs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#graph-languages&quot;&gt;Graph languages&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#graphs-computationally&quot;&gt;Dynamical systems on graphs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#graphs-efficiently&quot;&gt;Efficient implementations&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#programs-as-graphs&quot;&gt;Partial evaluation and program synthesis&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#roadmap&quot;&gt;Future roadmap&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;new-decade-new-delusions&quot;&gt;New decade, new delusions&lt;/h1&gt;

&lt;p&gt;Over the last decade, I bet on some strange ideas. A lot of people I looked up to at the time laughed at me. I’ll bet they aren’t laughing anymore. I ought to thank them one day, because their laughter gave me a lot of motivation. I’ve said some idiotic things to be sure, but I’ve also made some laughable predictions that were correct. Lesson learned: aim straighter.&lt;/p&gt;

&lt;p&gt;In 2012, I was in Austin sitting next to an ex-poker player named &lt;a href=&quot;https://twitter.com/amirpc&quot;&gt;Amir&lt;/a&gt; who was singing Hinton’s praises. Hypnotized by his technicolor slides, I quit my job in a hurry and started an educational project using speech recognition and restricted Boltzmann machines. It never panned out, but I learned a lot about ASR and Android audio. Still love &lt;a href=&quot;http://breandan.net/2014/02/09/the-end-of-illiteracy/&quot;&gt;that idea&lt;/a&gt;.&lt;/p&gt;

&lt;center&gt;
&lt;a href=&quot;https://www.cs.toronto.edu/~hinton/csc2535/notes/lec4new.pdf&quot;&gt;&lt;img align=&quot;center&quot; width=&quot;75%&quot; src=&quot;/images/rbm.png&quot; /&gt;&lt;/a&gt;
&lt;/center&gt;

&lt;p&gt;In 2017, I started writing a book on the ethics of automation and &lt;a href=&quot;http://breandan.net/2017/02/02/trust-in-automation/&quot;&gt;predicted&lt;/a&gt; mass unemployment and social unrest. Although I got the causes wrong (pandemic, go figure), the information economy and confirmation bias takes were all dead right. Sadly, this is now driving the world completely insane. Don’t say I warned you, go out and fix our broken systems. The world needs more engineers who care.&lt;/p&gt;

&lt;center&gt;
&lt;a href=&quot;https://colah.github.io/posts/2015-09-NN-Types-FP/&quot;&gt;&lt;img align=&quot;center&quot; width=&quot;75%&quot; src=&quot;/images/diff_prog.png&quot; /&gt;&lt;/a&gt;
&lt;/center&gt;

&lt;p&gt;In 2017, I witnessed the birth of &lt;a href=&quot;https://colah.github.io/posts/2015-09-NN-Types-FP/&quot;&gt;differentiable programming&lt;/a&gt;, which I stole from Chris Olah and turned into a &lt;a href=&quot;http://breandan.net/public/masters_thesis.pdf#2&quot;&gt;master’s thesis&lt;/a&gt;. Had a lot of trouble convincing people that classical programs could be made differentiable, but look at the proceedings of any machine learning conference today and you’ll find dozens of papers on differentiable sorting and rendering and simulation. Don’t thank me, thank Chris and the Theano guys.&lt;/p&gt;

&lt;p&gt;In 2018, I correctly predicted Microsoft would acquire GitHub to mine code. Why MS and not Google? I’ll bet they tried, but Google’s leadership had fantasies of AGI and besides JetBrains, MS were the only ones who gave a damn about developers. Now ML4SE is a thriving &lt;a href=&quot;https://ml4se.github.io/&quot;&gt;research area&lt;/a&gt; and showing up in &lt;a href=&quot;https://github.com/JetBrains-Research/DeepBugsPlugin&quot;&gt;real&lt;/a&gt; &lt;a href=&quot;https://devblogs.microsoft.com/visualstudio/ai-assisted-intellisense-for-your-teams-codebase/&quot;&gt;products&lt;/a&gt;, much to the chagrin of those who believed ML was a fad. I suspect their hype filter blinded them to the value those tools provide.&lt;/p&gt;

&lt;center&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;Prediction: MS will acquire GH within five years. If the &lt;a href=&quot;https://twitter.com/hashtag/ML4Code?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#ML4Code&lt;/a&gt; stuff delivers for MS, acquisition is highly likely. Although it would have been cheaper a few years ago. &lt;a href=&quot;https://t.co/5ZMtiRtifD&quot;&gt;https://t.co/5ZMtiRtifD&lt;/a&gt; &lt;a href=&quot;https://t.co/TaxkArm5ps&quot;&gt;https://t.co/TaxkArm5ps&lt;/a&gt;&lt;/p&gt;&amp;mdash; breandan (@breandan) &lt;a href=&quot;https://twitter.com/breandan/status/993553301927936001?ref_src=twsrc%5Etfw&quot;&gt;May 7, 2018&lt;/a&gt;&lt;/blockquote&gt; &lt;script async=&quot;&quot; src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;a href=&quot;https://blogs.microsoft.com/blog/2018/10/26/microsoft-completes-github-acquisition/&quot;&gt;
&lt;img align=&quot;center&quot; width=&quot;75%&quot; src=&quot;/images/microsoft_github_aquisition.png&quot; /&gt;&lt;/a&gt;
&lt;/center&gt;

&lt;p&gt;But to heck with everything I’ve said! If I had just one idea to share with these ML people, it would be types. Beat that drum as loud as I could. Types are the best tool we know for synthetic reasoning. If you want to build provably correct systems that scale on real-world applications, use types. Not everyone is convinced yet, but mark my words, &lt;a href=&quot;https://github.com/tensorflow/tensorflow/issues/12345&quot;&gt;types&lt;/a&gt; are &lt;a href=&quot;https://docs.python.org/3.9/whatsnew/3.9.html#pep-585-builtin-generic-types&quot;&gt;coming&lt;/a&gt;. Whoever figures out how to connect types and learning will be the next Barbara Liskov or Frances Allen.&lt;/p&gt;

&lt;p&gt;This year, I predicted the pandemic weeks before the lockdown, exited the market, and turned down a job at Google. Some people called me crazy. Now I’m going all-in on some new ideas (none of which are mine). I’m making some big bets and some will be wrong, but I see the very same spark of genius in them.&lt;/p&gt;

&lt;h1 id=&quot;everything-old-is-new-again&quot;&gt;Everything old is new again&lt;/h1&gt;

&lt;p&gt;As a kid, I was given a book on the history of mathematics. I remember it had some interesting puzzles, including one with &lt;a href=&quot;https://en.wikipedia.org/wiki/Seven_Bridges_of_K%C3%B6nigsberg&quot;&gt;some bridges&lt;/a&gt; in a town divided by rivers, once inhabited by a man called Euler. Was there a tour crossing each bridge exactly once? Was it possible to tell without checking every path? I remember spending days trying to figure out the answer.&lt;/p&gt;

&lt;center&gt;
&lt;a href=&quot;https://en.wikipedia.org/wiki/Seven_Bridges_of_K%C3%B6nigsberg&quot;&gt;&lt;img align=&quot;center&quot; width=&quot;60%&quot; src=&quot;/images/konigsberg_bridges.png&quot; /&gt;&lt;/a&gt;
&lt;/center&gt;

&lt;p&gt;In the late 90s, my mom and I went to Ireland. I remember visiting Trinity College, and learning about a mathematician called &lt;a href=&quot;https://en.wikipedia.org/wiki/William_Rowan_Hamilton&quot;&gt;Hamilton&lt;/a&gt; who discovered a famous formula connecting algebra and geometry, and carved it onto a &lt;a href=&quot;https://en.wikipedia.org/wiki/Broom_Bridge&quot;&gt;bridge&lt;/a&gt;. We later visited the bridge, and the tour guide pointed out the stone, which we touched for good luck. The Irish have a &lt;a href=&quot;https://en.wikipedia.org/wiki/Poulnabrone_dolmen&quot;&gt;thing&lt;/a&gt; for &lt;a href=&quot;https://en.wikipedia.org/wiki/Newgrange&quot;&gt;stones&lt;/a&gt;.&lt;/p&gt;

&lt;center&gt;
&lt;a href=&quot;http://www.kurims.kyoto-u.ac.jp/EMIS/classics/Hamilton/PRIAIcos.pdf&quot;&gt;&lt;img align=&quot;center&quot; width=&quot;40%&quot; src=&quot;/images/quaternions.jpg&quot; /&gt;&lt;/a&gt;
&lt;/center&gt;

&lt;p&gt;In 2007, I was applying to college and took the train from Boston to South Bend, Indiana, home of the Fighting Irish. Wandering about, I picked up a magazine article by a Hungarian mathematician called &lt;a href=&quot;https://en.wikipedia.org/wiki/Albert-L%C3%A1szl%C3%B3_Barab%C3%A1si&quot;&gt;Barabási&lt;/a&gt; then at Notre Dame, who had some interesting things to say about &lt;a href=&quot;https://en.wikipedia.org/wiki/Complex_network&quot;&gt;complex networks&lt;/a&gt;. Later in 2009, while studying in Rochester, I &lt;a href=&quot;/images/complex_network_seminar.png&quot;&gt;carpooled&lt;/a&gt; with a &lt;a href=&quot;https://avesis.medeniyet.edu.tr/hasan.guclu&quot;&gt;nice professor&lt;/a&gt;, and learned complex networks are found in brains, languages and many marvelous places.&lt;/p&gt;

&lt;center&gt;
&lt;a href=&quot;https://barabasi.com/f/226.pdf&quot;&gt;&lt;img align=&quot;center&quot; width=&quot;75%&quot; src=&quot;/images/complex_networks.png&quot; /&gt;&lt;/a&gt;
&lt;/center&gt;

&lt;p&gt;Fast forward to 2017. I was lured by the siren song of algorithmic differentiation. Olivier Breleux presented &lt;a href=&quot;https://github.com/mila-iqia/myia&quot;&gt;Myia&lt;/a&gt; and &lt;a href=&quot;https://github.com/breuleux/buche&quot;&gt;Buche&lt;/a&gt;. Matt Johnson gave a talk on &lt;a href=&quot;https://github.com/HIPS/autograd&quot;&gt;Autograd&lt;/a&gt;. I met Chris Olah in Long Beach, who gave me the idea to study &lt;a href=&quot;https://colah.github.io/posts/2015-09-NN-Types-FP/&quot;&gt;differentiable programming&lt;/a&gt;. I stole his idea, dressed it up in Kotlin and traded it for a POPL workshop paper and later a &lt;a href=&quot;https://github.com/breandan/kotlingrad/blob/master/latex/thesis/thesis.pdf&quot;&gt;Master’s thesis&lt;/a&gt;. Our contributions were using algebra, shape inference and presenting AD as term rewriting.&lt;/p&gt;

&lt;center&gt;
&lt;a href=&quot;https://github.com/breandan/kotlingrad#dataflow-graphs&quot;&gt;&lt;img align=&quot;center&quot; width=&quot;75%&quot; src=&quot;https://github.com/breandan/kotlingrad/raw/master/samples/src/main/resources/dataflow.svg&quot; /&gt;&lt;/a&gt;
&lt;/center&gt;

&lt;p&gt;In 2019, I joined a lab with a &lt;a href=&quot;https://www.cs.mcgill.ca/~jguo/&quot;&gt;nice professor&lt;/a&gt; at McGill applying knowledge graphs to software engineering. Like logical reasoning, knowledge graphs are an idea from the first wave of AI in the 1960s and 70s which have been revived and studied in light of recent progress in the field. I believe this is an important area of research with a lot of potential. Knowledge and traceability plays a big role in software engineering, and it’s the bread-and-butter of a good IDE. The world needs better IDEs if we’re ever going to untangle this mess we’re in.&lt;/p&gt;

&lt;center&gt;
&lt;a href=&quot;https://structurizr.com/&quot;&gt;&lt;img align=&quot;center&quot; width=&quot;45%&quot; src=&quot;https://raw.githubusercontent.com/cecuesta/structurizr-java/master/docs/images/graphviz-spring-petclinic-components.png&quot; /&gt;&lt;/a&gt;
&lt;/center&gt;

&lt;p&gt;This Spring, I took a fascinating seminar on &lt;a href=&quot;https://cs.mcgill.ca/~wlh/comp766/index.html&quot;&gt;Graph Representation Learning&lt;/a&gt;. A lot of delightful graph theory has been worked out over the last decade. &lt;a href=&quot;https://en.wikipedia.org/wiki/PageRank&quot;&gt;PageRank&lt;/a&gt; turned into power iteration. People have discovered many interesting connections to linear algebra, including Weisfeiler-Lehman graph kernels, graph Laplacians, Krylov methods, and spectral graph theory. These ideas have deepened our understanding of graph signal processing and its applications for learning and program analysis. More on that &lt;a href=&quot;#graphs-computationally&quot;&gt;later&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;what-are-graphs&quot;&gt;What are graphs?&lt;/h1&gt;

&lt;p&gt;Graphs are general-purpose data structures used to represent a variety of data types and procedural phenomena. Unlike most sequential languages, graphs are capable of expressing a much richer family of relations between entities, and are a natural fit for many problems in computer science, physics, biology and mathematics. Consider the following hierarchy of data structures, all of which are graphs with increasing expressive power:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Sets&lt;/strong&gt;: datasets, multisets, posets, alphabets&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Sequences&lt;/strong&gt;: Lists, strings, arrays, linear function composition&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Trees&lt;/strong&gt;: &lt;a href=&quot;https://en.wikipedia.org/wiki/Abstract_syntax_tree&quot;&gt;Abstract syntax&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Document_Object_Model&quot;&gt;XML&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Phylogenetic_tree&quot;&gt;phylogeny&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Decision_tree&quot;&gt;decision trees&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;DAGs&lt;/strong&gt;: &lt;a href=&quot;https://eagain.net/articles/git-for-computer-scientists/&quot;&gt;Git&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Citation_network&quot;&gt;citations&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Dependency_graph&quot;&gt;dependency graphs&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Workflow_management_system&quot;&gt;workflows&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Control-flow_graph&quot;&gt;control flow&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Multilayer_perceptron&quot;&gt;MLPs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Directed graphs&lt;/strong&gt;: &lt;a href=&quot;https://en.wikipedia.org/wiki/Finite-state_machine&quot;&gt;State machines&lt;/a&gt;, &lt;a href=&quot;http://dkeenan.com/Lambda/&quot;&gt;λ-calculus&lt;/a&gt;, &lt;a href=&quot;https://computersciencewiki.org/index.php/The_web_as_a_directed_graph&quot;&gt;the web&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Call_graph&quot;&gt;call graphs&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Recurrent_neural_network&quot;&gt;RNNs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Hypergraphs&lt;/strong&gt;: &lt;a href=&quot;https://arxiv.org/pdf/2003.02320.pdf&quot;&gt;Knowledge&lt;/a&gt;, &lt;a href=&quot;https://zettelkasten.de/&quot;&gt;Zettelkasten&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Category_theory&quot;&gt;categories&lt;/a&gt;, &lt;a href=&quot;https://writings.stephenwolfram.com/2020/04/finally-we-may-have-a-path-to-the-fundamental-theory-of-physics-and-its-beautiful/&quot;&gt;physics&lt;/a&gt;, &lt;a href=&quot;https://openreview.net/pdf?id=rkpACe1lx&quot;&gt;hypernetworks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As we realized in &lt;a href=&quot;https://github.com/breandan/kotlingrad&quot;&gt;Kotlin∇&lt;/a&gt;, directed graphs can be used to model mathematical expressions, as well as other formal languages, including source code, intermediate representations and binary artifacts. Not only can graphs be used to describe extant human knowledge, many recent examples have shown that machines can “grow” trees and graphs for various applications, such as program synthesis, mathematical deduction and physical simulation. Recent neuro-symbolic applications have shown promising early results in graph synthesis:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://arxiv.org/pdf/1711.00740.pdf&quot;&gt;Learning to Represent Programs with Graphs&lt;/a&gt;, Allamanis et al., 2018&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://arxiv.org/pdf/1912.01412.pdf&quot;&gt;Deep Learning for Symbolic Mathematics&lt;/a&gt;, Lample and Charton, 2019.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://arxiv.org/pdf/2006.11287.pdf&quot;&gt;Discovering Symbolic Models from Deep Learning with Inductive Biases&lt;/a&gt;, Cranmer et al., 2020.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://arxiv.org/pdf/2005.11212.pdf&quot;&gt;Symbolic Pregression: Discovering Physical Laws from Raw Distorted Video&lt;/a&gt; (Udrescu &amp;amp; Tegmark, 2020).&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://arxiv.org/pdf/2006.08381.pdf&quot;&gt;DreamCoder: Growing generalizable, interpretable knowledge with wake-sleep Bayesian program learning&lt;/a&gt;, Ellis et al., 2020.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://arxiv.org/abs/2007.03629&quot;&gt;Strong Generalization and Efficiency in Neural Programs&lt;/a&gt;, Li et al., 2020.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://arxiv.org/pdf/1910.10593.pdf&quot;&gt;Neural Execution of Graph Algorithms&lt;/a&gt;, Veličković et al. (2020)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The field of natural language processing has also developed a rich set of graph-based representations, such as &lt;a href=&quot;https://en.wikipedia.org/wiki/Phrase_structure_grammar&quot;&gt;constituency&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Dependency_grammar&quot;&gt;dependency&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Link_grammar&quot;&gt;link&lt;/a&gt; and other and other typed attribute grammars which can be used to reason about syntactic and semantic relations between natural language entities. Research has begun to show many practical applications for such grammars in the extraction and organization of human knowledge stored in large text corpora. Those graphs can be further processed into ontologies for logical reasoning.&lt;/p&gt;

&lt;center&gt;
&lt;img align=&quot;center&quot; width=&quot;60%&quot; src=&quot;https://upload.wikimedia.org/wikipedia/commons/8/8e/Thistreeisillustratingtherelation%28PSG%29.png&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;Using coreference resolution and entity alignment techniques, we can reconstruct internally consistent relations between entities, which capture cross-corpus consensus in natural language datasets. When stored in &lt;a href=&quot;https://arxiv.org/pdf/2003.02320.pdf&quot;&gt;knowledge graphs&lt;/a&gt;, these relations can be used for information retrieval and question answering, e.g. on wikis and other content management systems. Recent techniques have shown promise in automatic knowledge base construction (cf. &lt;a href=&quot;https://www.mitpressjournals.org/doi/pdf/10.1162/tacl_a_00088&quot;&gt;Reddy et al.&lt;/a&gt;, 2016).&lt;/p&gt;

&lt;!--![logical_forms](/images/logical_forms.png) --&gt;
&lt;center&gt;
&lt;a href=&quot;https://arxiv.org/pdf/2003.02320.pdf#page=8&quot;&gt;&lt;img align=&quot;center&quot; width=&quot;75%&quot; src=&quot;/images/knowledge_graph.png&quot; /&gt;&lt;/a&gt;
&lt;/center&gt;

&lt;p&gt;Lo and behold, the key idea behind knowledge graphs is our old friend, types. Knowledge graphs are multi-relational graphs whose nodes and edges possess a type. Two entities can be related by multiple types, and each type can relate many pairs of entities. We can index an entity based on its type for knowledge retrieval, and use types to reason about compound queries, e.g. “Which &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;company&lt;/code&gt; has a direct &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flight&lt;/code&gt; from a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;port city&lt;/code&gt; to a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;capital city&lt;/code&gt;?”, which would otherwise be difficult to answer without a type system.&lt;/p&gt;

&lt;h1 id=&quot;induction-introduction&quot;&gt;Induction introduction!&lt;/h1&gt;

&lt;p&gt;In this section, we will review some important concepts from &lt;a href=&quot;https://en.wikipedia.org/wiki/Chomsky_hierarchy&quot;&gt;Chomskyan linguistics&lt;/a&gt;, including finite automata, abstract rewriting systems, and λ-calculus. Readers already familiar with these concepts will gain a newfound appreciation for how each one shares a common thread and can be modeled using the same underlying abstractions.&lt;/p&gt;

&lt;h2 id=&quot;regular-languages&quot;&gt;Regular languages&lt;/h2&gt;

&lt;p&gt;One thing that always fascinated me is the idea of inductively defined languages, also known as recursive, or structural induction. Consider a very simple language that accepts strings of the form &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;100&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;101&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1001&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1010&lt;/code&gt;, et cetera, but rejects &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;011&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;110&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1011&lt;/code&gt;, or any string containing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;11&lt;/code&gt;. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;→&lt;/code&gt; symbol denotes a “production”. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;|&lt;/code&gt; symbol, which we read as “or”, is just shorthand for defining multiple productions on a single line:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;true → 1
term → 0 | 10 | ε
expr → term | expr term
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We have two sets of productions, those which can be expanded, called “nonterminals”, and those which can be expanded no further, called “terminals”. Notice how each non-terminal occurs at most once in any single production. This property guarantees the language is recognizable by a special kind of graph, called a &lt;a href=&quot;https://en.wikipedia.org/wiki/Finite-state_machine&quot;&gt;finite state machine&lt;/a&gt;. As their name suggests, FSMs contain a finite set of states, with labeled transitions between them:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Finite Automaton&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Library Courtesy Bell&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;center&gt;&lt;img align=&quot;center&quot; width=&quot;200%&quot; src=&quot;/images/fsm_bell.svg&quot; /&gt;&lt;/center&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;br /&gt;&lt;center&gt;&lt;img align=&quot;center&quot; width=&quot;50%&quot; src=&quot;/images/bell.png&quot; /&gt;&lt;/center&gt;&lt;br /&gt;Please ring the bell &lt;strong&gt;once&lt;/strong&gt;&lt;br /&gt; and wait for assistance.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Imagine a library desk: you can wait quietly and eventually you will be served. Or, you can ring the bell once and wait quietly to be served. Should no one arrive after a while, you may press the bell again and continue waiting. Though you must never ring the bell twice, lest you disturb the patrons and be tossed out.&lt;/p&gt;

&lt;p&gt;Regular languages can also model nested repetition. Consider a slightly more complicated language, given by the regular expression &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(0(01)*)*(10)*&lt;/code&gt;. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt;, or &lt;a href=&quot;https://en.wikipedia.org/wiki/Kleene_star&quot;&gt;Kleene star&lt;/a&gt;, means, “accept zero or more of the previous token”.&lt;/p&gt;

&lt;table&gt;
&lt;tr&gt;
&lt;td&gt; &lt;center&gt;&lt;b&gt;Backus-Naur Grammar&lt;/b&gt;&lt;/center&gt; &lt;/td&gt; &lt;td&gt;&lt;center&gt;&lt;b&gt;&lt;center&gt;Nondeterminstic Finite Automaton&lt;/center&gt;&lt;/b&gt;&lt;/center&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;

&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
   t → ε | 0
   a → 10 | a 10
   b → 0 | b 01 | b 0 ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎ ‎

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;center&gt;&lt;img src=&quot;/images/nfa.svg&quot; width=&quot;80%&quot; /&gt;&lt;/center&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Note here, a single symbol may have multiple transitions from the same state. Called a &lt;a href=&quot;https://en.wikipedia.org/wiki/Nondeterministic_finite_automaton&quot;&gt;nondeterminsic finite automaton&lt;/a&gt; (NFA), this machine can occupy multiple states simultaneously. While no more powerful than their determinstic cousins, NFAs often require far fewer states to recognize the same language. One way to implement an NFA is to simulate the superposition of all states, by cloning the machine whenever such a transition occurs. More on that &lt;a href=&quot;#nondeterminstic-finite-automata&quot;&gt;later&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;arithmetic&quot;&gt;Arithmetic&lt;/h2&gt;

&lt;p&gt;Now suppose we have a slightly more expressive language that accepts well-formed arithmetic expressions with up to two variables, in either infix or unary prefix form. In this language, a non-terminal may occur twice inside a single production – an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;expr&lt;/code&gt; can be composed of two sub&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;expr&lt;/code&gt;s:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;term → 1 | 0 | x | y
  op → + | - | ·
expr → term | op expr | expr op expr
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is an example of a &lt;a href=&quot;https://en.wikipedia.org/wiki/Context-free_language&quot;&gt;context-free language&lt;/a&gt; (CFL). We can represent strings in this language using a special kind of graph, called a syntax tree. Each time we expand an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;expr&lt;/code&gt; with a production rule, this generates a rooted subtree on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;op&lt;/code&gt;, whose branch(es) are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;expr&lt;/code&gt;s. Typically, syntax trees are inverted, with branches extending downwards, like so:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Syntax Tree&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Peach Tree&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;center&gt;&lt;img align=&quot;center&quot; width=&quot;80%&quot; src=&quot;/images/tree_syntax.svg&quot; /&gt;&lt;/center&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;center&gt;&lt;img align=&quot;center&quot; width=&quot;75%&quot; src=&quot;/images/tree_peach.png&quot; /&gt;&lt;/center&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;While syntax trees can be interpreted computationally, they do not actually perform computation unless evaluated. To [partially] evaluate a syntax tree, we will now introduce some pattern matching rules. Instead of just allowing terminals to occur on the right-hand side of a production, suppose we also allow terminals on the left, and applying a rule can shrink a string in our language. Here, we use capital letters on the same line to indicate an exact match, e.g. a rule &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;U + V → V + U&lt;/code&gt; would replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x + y&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y + x&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;                                         E + E → +E
                                         E · E → ·E
                  E + 1 | 1 + E | +1 | -0 | ·1 → 1
                         E + 0 | 0 + E | E - 0 → E
  E - E | E · 0 | 0 · E | 0 - E | +0 | -1 | ·0 → 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If we must add two identical expressions, why evaluate them twice? If we need to multiply an expression by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;, why evaluate it at all? Instead, we will try to simplify these patterns whenever we encounter them. This is known as a &lt;a href=&quot;https://en.wikipedia.org/wiki/Rewriting&quot;&gt;rewrite system&lt;/a&gt;, which we can think of as grafting or pruning the branches of a tree. Some say, “all trees are DAGs, but not all DAGs are trees”. I prefer to think of a DAG as a tree with a &lt;a href=&quot;https://en.wikipedia.org/wiki/Inosculation&quot;&gt;gemel&lt;/a&gt;:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Rewrite Rule&lt;/th&gt;
      &lt;th&gt;Deformed Tree&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;center&gt;&lt;img align=&quot;center&quot; width=&quot;100%&quot; src=&quot;/images/tree_dag.svg&quot; /&gt;&lt;/center&gt;&lt;/td&gt;
      &lt;td&gt;&lt;br /&gt;&lt;center&gt;&lt;img align=&quot;center&quot; width=&quot;50%&quot; src=&quot;/images/tree_gemel.png&quot; /&gt;&lt;/center&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;center&gt;&lt;img align=&quot;center&quot; width=&quot;100%&quot; src=&quot;/images/tree_dag_minus.svg&quot; /&gt;&lt;/center&gt;&lt;/td&gt;
      &lt;td&gt;&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;img align=&quot;center&quot; width=&quot;50%&quot; src=&quot;/images/stump.png&quot; /&gt;&lt;/center&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Let us now introduce a new operator, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dₓ&lt;/code&gt;, and some corresponding rules. In effect, these rules will push &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dₓ&lt;/code&gt; as far towards the leaves as possible, while rewriting terms along the way. We will also introduce some terminal rewrites:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[R0]       term → Dₓ(term)
[R1]      Dₓ(x) → 1  
[R2]      Dₓ(y) → 0  
[R3]    Dₓ(U+V) → Dₓ(U) + Dₓ(V)  
[R4]    Dₓ(U·V) → U·Dₓ(V) + Dₓ(U)·V  
[R5]     Dₓ(+U) → +Dₓ(U)
[R6]     Dₓ(-U) → -Dₓ(U)
[R7]     Dₓ(·U) → +U·Dₓ(U)
[R8]      Dₓ(1) → 0
[R9]      Dₓ(0) → 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Although we assign an ordering &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;R0&lt;/code&gt;-&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;R9&lt;/code&gt; for notational convenience, an initial string, once given to this system, will always converge to the same result, no matter in which order we perform the substitutions (proof required):&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Term Confluence&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Ottawa-St. Lawrence Confluence&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;br /&gt;&lt;center&gt;&lt;img align=&quot;center&quot; width=&quot;100%&quot; src=&quot;/images/confluence_term.svg&quot; /&gt;&lt;/center&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;br /&gt;&lt;center&gt;&lt;img align=&quot;center&quot; width=&quot;75%&quot; src=&quot;/images/confluence_river.png&quot; /&gt;&lt;/center&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;This feature, called &lt;a href=&quot;https://en.wikipedia.org/wiki/Confluence_(abstract_rewriting)&quot;&gt;confluence&lt;/a&gt;, is an important property of some rewrite systems: regardless of the substitution order, we will eventually arrive at the same result. If all strings in a language reduce to a form which can be simplified no further, we call such systems &lt;em&gt;strongly normalizing&lt;/em&gt;, or &lt;em&gt;terminating&lt;/em&gt;. If a rewriting system is both confluent and terminating it is said to be &lt;em&gt;convergent&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;λ-calculus&quot;&gt;λ-calculus&lt;/h2&gt;

&lt;p&gt;So far, the languages we have seen are capable of generating and simplifying arithmetic expressions, but are by themselves incapable of performing arithmetic, since they cannot evaluate arbitrary arithmetic expressions. We will now consider a language which can encode and evaluate any arithmetic expression:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;expr → var | func | appl
func → (λ var.expr)
appl → (expr expr)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To evaluate an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;expr&lt;/code&gt; in this language, we need a single substitution rule. The notation &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;expr[var → val]&lt;/code&gt;, &lt;a href=&quot;https://groups.csail.mit.edu/mac/users/gjs/6.945/readings/Steele-MIT-April-2017.pdf#page=44&quot;&gt;we read as&lt;/a&gt;, “within &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;expr&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;var&lt;/code&gt; becomes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;val&lt;/code&gt;”:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(λ var.expr) val → (expr[var → val])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For example, applying the above rule to the expression &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(λy.y z) a&lt;/code&gt; yields &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a z&lt;/code&gt;. With this seemingly trivial addition, our language is now powerful enough to encode any computable function! Known as the pure untyped λ-calculus, this system is equivalent to an idealized computer with infinite memory.&lt;/p&gt;

&lt;p&gt;While grammatically compact, computation in the λ-calculus is not particularly terse. In order to perform any computation, we will need a way to encode values. For example, we can encode the boolean algebra like so:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[D1]           λx.λy.x = T     &quot;true&quot;
[D2]           λx.λy.y = F     &quot;false&quot;
[D3]       λp.λq.p q p = &amp;amp;     &quot;and&quot;
[D4]       λp.λq.p p q = |     &quot;or&quot;
[D5]    λp.λa.λb.p b a = !     &quot;not&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To evaluate a boolean expression &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!T&lt;/code&gt;, we will first need to encode it as a λ-expression. We can then evaluate it using the λ-calculus as follows:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  (           !          ) T
→ (λp.λa.λb.    p     b a) T   [D5]
→ (   λa.λb.    T     b a)     [p → T]
→ (   λa.λb.(λx.λy.x) b a)     [D1]
→ (   λa.λb.(   λy.b)   a)     [x → b]
→ (   λa.λb.(   λy.b)    )     [y → a]
→ (   λa.λb.b            )     [y →  ]
→ (   F                  )     [D2]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We have reached a terminal, and can recurse no further. This particular program is decidable. What about others? Let us consider an undecidable example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(λg.(λx.g (x x)) (λx.g (x x))) f
    (λx.f (x x)) (λx.f (x x))                        [g → f]
        f (λx.f (x x))(λx.f (x x))                   [f → λx.f(x x)]
        f     f (λx.f (x x))(λx.f (x x))             [f → λx.f(x x)]
        f     f     f (λx.f (x x))(λx.f (x x))       [f → λx.f(x x)]
        ...                 (λx.f (x x))(λx.f (x x)) [f → λx.f(x x)]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This pattern is &lt;a href=&quot;https://doi.org/10.2307%2F2370619&quot;&gt;Curry’s (1930)&lt;/a&gt; famous fixed point combinator and the cornerstone of recursion, called Y. Unlike its typed cousin, the untyped λ-calculus is &lt;em&gt;not&lt;/em&gt; strongly normalizing and thus not guaranteed to converge. Were it convergent, it would not be Turing-complete. This &lt;a href=&quot;http://www.cts.cuni.cz/~kurka/decid1.pdf&quot;&gt;hard choice&lt;/a&gt; between decidability and universality is one which no computational language can avoid.&lt;/p&gt;

&lt;center&gt;
&lt;a href=&quot;http://bntr.planet.ee/lambda/work/visual_lambda.pdf&quot;&gt;&lt;img align=&quot;center&quot; width=&quot;75%&quot; src=&quot;/images/graphical_lambda_calculus.png&quot; /&gt;&lt;/a&gt;
&lt;/center&gt;

&lt;p&gt;The λ-calculus, can also be interpreted graphically. I refer the curious reader to some promising proposals which have attempted to formalize this perspective:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://doi.org/10.1145/96709.96711&quot;&gt;An Algorithm for Optimal Lambda Calculus Reduction&lt;/a&gt;, (Lample 1990)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://dkeenan.com/Lambda/&quot;&gt;A Graphical Notation for the Lambda Calculus&lt;/a&gt; (Keenan, 1996)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://bntr.planet.ee/lambda/work/visual_lambda.pdf&quot;&gt;Visual lambda calculus&lt;/a&gt; (Massalõgin, 2008)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://arxiv.org/pdf/1305.5786.pdf&quot;&gt;Graphic lambda calculus&lt;/a&gt; (Buliga, 2013)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://tromp.github.io/cl/diagrams.html&quot;&gt;Lambda Diagrams&lt;/a&gt; (Tromp, 2014)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;cellular-automata&quot;&gt;Cellular automata&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://en.wikipedia.org/wiki/Elementary_cellular_automaton&quot;&gt;elementary cellular automaton&lt;/a&gt; is another string rewrite system consisting of a one dimensional binary array, and a 3-cell grammar. Note there are \(2^{2^3} = 256\) possible rules for rewriting the tape. It turns out even in this tiny space, there exist remarkable automata. Consider the following rewrite system:&lt;/p&gt;

&lt;center&gt;
&lt;img align=&quot;center&quot; src=&quot;/images/ca_rule%20110.png&quot; /&gt;
&lt;/center&gt;

&lt;!--![](https://en.wikipedia.org/wiki/Cellular_automaton#/media/File:One-d-cellular-automate-rule-30.gif)--&gt;

&lt;!--We can represent this using graphs:--&gt;

&lt;!--![image](/images/ca_rule30.png)--&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;current pattern&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;111&lt;/code&gt;&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;110&lt;/code&gt;&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;101&lt;/code&gt;&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;100&lt;/code&gt;&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;011&lt;/code&gt;&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;010&lt;/code&gt;&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;001&lt;/code&gt;&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;000&lt;/code&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;next pattern&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;` 0 `&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;` 1 `&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;` 1 `&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;` 0 `&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;` 1 `&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;` 1 `&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;` 1 `&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;` 0 `&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;We can think of this machine as sliding over the tape, and replacing the centermost cell in each matching substring with the second value. Depending on the initial state and rewrite pattern, cellular autoamta can produce many visually interesting patterns. Some have spent a great deal of effort &lt;a href=&quot;https://en.wikipedia.org/wiki/A_New_Kind_of_Science&quot;&gt;cataloguing&lt;/a&gt; families of CA and their behavior. Following &lt;a href=&quot;http://wpmedia.wolfram.com/uploads/sites/13/2018/02/01-1-15.pdf&quot;&gt;Robinson (1987)&lt;/a&gt;, we can also define an ECA inductively, using the following recurrence relation:&lt;/p&gt;

\[a_i^{(t)} = \sum_j s(j)a_{(i-j)}^{t-1} \mod m\]

&lt;p&gt;This characterization might remind us of a certain operation from digital signal processing, called a &lt;a href=&quot;https://en.wikipedia.org/wiki/Convolution#Discrete_convolution&quot;&gt;discrete convolution&lt;/a&gt;. We read \(f * g\) as “\(f\) convolved by \(g\)”:&lt;/p&gt;

\[(f * g)[n] = \sum_m f[m]g[n-m]\]

&lt;p&gt;Here \(f\) is our state and \(g\) is called a “kernel”. Similar to the λ-calculus, this language also is &lt;a href=&quot;https://wpmedia.wolfram.com/uploads/sites/13/2018/02/15-1-1.pdf&quot;&gt;known to be universal&lt;/a&gt;. Disregarding efficiency, we could encode any computable function as an initial state and mechanically apply &lt;a href=&quot;https://en.wikipedia.org/wiki/Rule_110&quot;&gt;Rule 110&lt;/a&gt; to simulate a TM, λ-calculus, or any other TC system for that matter.&lt;/p&gt;

&lt;center&gt;
&lt;a href=&quot;https://www.wolframphysics.org/technical-introduction/equivalence-and-computation-in-our-models/correspondence-with-other-systems/#p-385&quot;&gt;&lt;img align=&quot;center&quot; width=&quot;75%&quot; src=&quot;/images/graph_ca.png&quot; /&gt;&lt;/a&gt;
&lt;/center&gt;

&lt;p&gt;Cellular automata can also be &lt;a href=&quot;https://www.wolframphysics.org/technical-introduction/equivalence-and-computation-in-our-models/correspondence-with-other-systems/#p-385&quot;&gt;interpreted&lt;/a&gt; as a &lt;a href=&quot;https://en.wikipedia.org/wiki/Graph_rewriting&quot;&gt;graph rewriting system&lt;/a&gt;, although the benefits of this perspective are not as clear. Unlike string rewriting, graph substitution is much more difficult to implement efficiently, as pattern matching amounts to &lt;a href=&quot;https://en.wikipedia.org/wiki/Subgraph_isomorphism_problem&quot;&gt;subgraph isomorphism&lt;/a&gt;, which is NP-complete. While there are &lt;a href=&quot;https://arxiv.org/pdf/1906.05170.pdf&quot;&gt;some optimizations&lt;/a&gt; to mitigate this problem, graph grammars do not appear to confer any additional computational benefits. Nevertheless, it is conceptually interesting.&lt;/p&gt;

&lt;h1 id=&quot;graphs-inductively&quot;&gt;Graphs, inductively&lt;/h1&gt;

&lt;p&gt;Just like grammars, we can define graphs themselves inductively. As many graph algorithms are recursive, this choice considerably simplifies their implementation. Take one definition of an unlabeled directed graph, proposed by &lt;a href=&quot;https://web.engr.oregonstate.edu/~erwig/papers/InductiveGraphs_JFP01.pdf&quot;&gt;Erwig (2001)&lt;/a&gt;. Here, the notation &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;list → [item]&lt;/code&gt; is shorthand for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;list → item list&lt;/code&gt;, where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;item&lt;/code&gt; is some terminal, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;list&lt;/code&gt; is just a list of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;item&lt;/code&gt;s:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vertex  → int
adj     → [vertex]
context → (adj, vertex, adj)
graph   → empty | context &amp;amp; graph
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Erwig defines a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;graph&lt;/code&gt; in four parts. First, we have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vertex&lt;/code&gt;, which is simply an integer. Next we have a list of vertices, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;adj&lt;/code&gt;, called an &lt;a href=&quot;https://en.wikipedia.org/wiki/Adjacency_list&quot;&gt;adjacency list&lt;/a&gt;. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;context&lt;/code&gt; is a 3-tuple containing a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vertex&lt;/code&gt; and symmetric references to its inbound and outbound neighbors, respectively. Finally, we have the inductive case: a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;graph&lt;/code&gt; is either (1) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;empty&lt;/code&gt;, or (2) a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;context&lt;/code&gt; and a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;graph&lt;/code&gt;.&lt;/p&gt;

&lt;table&gt;
&lt;tr&gt;
&lt;td&gt; &lt;center&gt;&lt;b&gt;String&lt;/b&gt;&lt;/center&gt; &lt;/td&gt; &lt;td&gt;&lt;center&gt;&lt;b&gt;&lt;center&gt;Graph&lt;/center&gt;&lt;/b&gt;&lt;/center&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;

&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
    ([3],       4, [1, 3])  &amp;amp;
    ([1, 2, 4], 3, [4]   )  &amp;amp;
    ([1],       2, [1, 3])  &amp;amp;
    ([2, 4],    1, [2, 3])

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;center&gt;&lt;img src=&quot;/images/erwig.svg&quot; width=&quot;60%&quot; /&gt;&lt;/center&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Let us consider a directed graph implementation in &lt;a href=&quot;https://kotlinlang.org/&quot;&gt;Kotlin&lt;/a&gt;. We do not store inbound neighbors, and attempt to define a vertex as a &lt;a href=&quot;https://en.wikipedia.org/wiki/Neighbourhood_(graph_theory)&quot;&gt;closed neighborhood&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Vertex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;data class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Vertex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;neighbors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Vertex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;):&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;neighbors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//                                               ↳ Compile error!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note the coinductive definition, which creates problems right off the bat. Since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;this&lt;/code&gt; is not accessible inside the constructor, we cannot have cycles or closed neighborhoods, unless we delay edge instantiation until after construction:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Vertex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Vertex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;adjacencyMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Vertex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Vertex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;neighbors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Vertex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;neighbors&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;neighbors&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;adjacencyMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;toSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can now call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Vertex() { setOf(it) }&lt;/code&gt; to create loops and closed neighborhoods. This definition admits a nice k-nearest neighbors implementation, allowing us to compute the k-hop &lt;a href=&quot;https://en.wikipedia.org/wiki/Transitive_closure&quot;&gt;transitive closure&lt;/a&gt; of a vertex or set of vertices:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;tailrec&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Vertex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;neighbors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Vertex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
                             &lt;span class=&quot;n&quot;&gt;neighbors&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Vertex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;neighbors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vertices&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;knn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vertices&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;neighbors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Vertex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;neighbors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;flatMap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;neighbors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;toSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Removes all vertices outside the set&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Vertex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;closure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Vertex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vertex&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Vertex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;neighbors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;filter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;toSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Vertex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;neighborhood&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;neighbors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;closure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Another useful representation for a graph, which we will describe in further detail &lt;a href=&quot;#graph-languages&quot;&gt;below&lt;/a&gt;, is a matrix. We can define the &lt;a href=&quot;https://en.wikipedia.org/wiki/Adjacency_matrix&quot;&gt;adjacency&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Degree_matrix&quot;&gt;degree&lt;/a&gt;, and &lt;a href=&quot;https://en.wikipedia.org/wiki/Laplacian_matrix&quot;&gt;Laplacian&lt;/a&gt; matrices like so:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;Graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;adjacency&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Mat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;also&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;adj&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;forEach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;neighbors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;forEach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;adj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;Graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;degree&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Mat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;also&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deg&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;forEach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;neighbors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;Graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;laplacian&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;degree&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;adjacency&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;These matrices have some important applications in &lt;a href=&quot;https://en.wikipedia.org/wiki/Algebraic_graph_theory&quot;&gt;algebraic&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Spectral_graph_theory&quot;&gt;spectral&lt;/a&gt; graph theory, which we will have more to stay about &lt;a href=&quot;#graphs-computationally&quot;&gt;later&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;weisfeiler-lehman&quot;&gt;Weisfeiler-Lehman&lt;/h2&gt;

&lt;p&gt;Let us consider an algorithm called the &lt;a href=&quot;http://www.jmlr.org/papers/volume12/shervashidze11a/shervashidze11a.pdf&quot;&gt;Weisfeiler-Lehman&lt;/a&gt; isomorphism test, on which my colleague David Bieber has written a &lt;a href=&quot;https://davidbieber.com/post/2019-05-10-weisfeiler-lehman-isomorphism-test/&quot;&gt;nice piece&lt;/a&gt;. I’ll focus on its implementation. First, we need a pooling operator, which will aggregate all neighbors in a node’s neighborhood using some summary statistic:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;poolBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;statistic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Vertex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;.()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Vertex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;nodes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;statistic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;neighbors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;toMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next, we’ll define a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;histogram&lt;/code&gt;, which just counts each node’s neighborhood:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;Graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;histogram&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Vertex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;poolBy&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we’re ready to define the &lt;a href=&quot;http://www.jmlr.org/papers/volume12/shervashidze11a/shervashidze11a.pdf#page=6&quot;&gt;Weisfeiler-Lehman operator&lt;/a&gt;, which recursively hashes the labels until fixpoint termination:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;tailrec&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;wl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Vertex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;):&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Vertex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;next&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;poolBy&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!!&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;wl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With one round, we’re just comparing the degree histogram. We compute the hash of the entire graph by hashing the multiset of WL labels:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;wl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;histogram&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finally, we can define a test to detect if one graph is isomorphic to another:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;isIsomorphicTo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nodes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nodes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; 
  &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numOfEdges&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numOfEdges&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; 
  &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This algorithm works on many graphs encountered in the wild, however it cannot distinguish two &lt;a href=&quot;https://en.wikipedia.org/wiki/Regular_graph&quot;&gt;regular graphs&lt;/a&gt; with an identical number of vertices and edges. Nevertheless, it is appealing for its simplicity and exemplifies a simple “message passing” algorithm, which we will revisit &lt;a href=&quot;#examples&quot;&gt;later&lt;/a&gt;. For a complete implementation and other inductive graph algorithms, such as Barabási’s &lt;a href=&quot;https://en.wikipedia.org/wiki/Preferential_attachment&quot;&gt;preferential attachment algorithm&lt;/a&gt;, check out &lt;a href=&quot;https://github.com/breandan/kaliningraph&quot;&gt;Kaliningraph&lt;/a&gt;.&lt;/p&gt;

&lt;!--TODO: Graph grammars are grammars on graphs.--&gt;

&lt;!--TODO: Single/Double pushout--&gt;

&lt;h2 id=&quot;graph-diameter&quot;&gt;Graph Diameter&lt;/h2&gt;

&lt;p&gt;A graph’s diameter is the length of the longest shortest path between any two of its vertices. Let us define the augmented adjacency matrix as \(A + A^\intercal + \mathbb{1}\), or:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;Graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;A_AUG&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;adjacency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transpose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ONES&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To compute the diameter of a connected graph \(G\), we can simply power the augmented adjacency matrix until it contains no zeros:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;/* (A&apos;)ⁿ[a, b] counts the number of walks between vertices a, b of
 * length n. Let i be the smallest natural number such that (A&apos;)ⁱ
 * has no zeros. i is the length of the longest shortest path in G.
 */&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;tailrec&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;slowDiameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;walks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;A_AUG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;walks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;all&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; 
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;slowDiameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;walks&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;walks&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;A_AUG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If we consider the complexity of this procedure, we note it takes \(\mathcal O(M \mid G\mid)\) time, where \(M\) is the &lt;a href=&quot;https://en.wikipedia.org/wiki/Matrix_multiplication_algorithm#Sub-cubic_algorithms&quot;&gt;complexity of matrix multiplication&lt;/a&gt;, and \(\mathcal O(Q\mid G \mid^2)\) space, where \(Q\) is the number of bits required for a single entry in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A_AUG&lt;/code&gt;. Since we only care whether or not the entries are zero, we can instead cast &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A_AUG&lt;/code&gt; to \(\mathbb B^{n\times n}\) and run binary search for the smallest &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; yielding a matrix with no zeros:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;tailrec&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fastDiameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;n&quot;&gt;prev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;A_AUG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isFull&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;slowDiameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fastDiameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prev&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Our improved procedure &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fastDiameter&lt;/code&gt; runs in \(\mathcal O(M\log_2\mid G\mid)\) time. An iterative version of this procedure may be found in &lt;a href=&quot;https://link.springer.com/content/pdf/10.1007/BF00264532.pdf&quot;&gt;Booth and Lipton (1981)&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;graph-neural-networks&quot;&gt;Graph Neural Networks&lt;/h2&gt;

&lt;p&gt;A graph neural network is like a graph, but whose edges are neural networks. In its simplest form, the inference step can be defined as a matrix recurrence relation \(\mathbf H^t := σ(\mathbf A \mathbf H^{t-1} \mathbf W^t + \mathbf H^{t-1} \mathbf W^t)\) following &lt;a href=&quot;https://www.cs.mcgill.ca/~wlh/grl_book/files/GRL_Book-Chapter_5-GNNs.pdf#page=18&quot;&gt;Hamilton (2020)&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;tailrec&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;gnn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Number of message passing rounds&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fastDiameter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Matrix of node representations ℝ^{|V|xd}&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;H&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Mat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// (Trainable) weight matrix ℝ^{dxd}&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;W&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;randomMatrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;H&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numCols&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Bias term ℝ^{dxd}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;randomMatrix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;H&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numCols&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Nonlinearity ℝ^{*} -&amp;gt; ℝ^{*}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;σ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Mat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;elwise&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;tanh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Layer normalization ℝ^{*} -&amp;gt; ℝ^{*}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Mat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;meanNorm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Message ℝ^{*} -&amp;gt; ℝ^{*}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;.(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Mat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;σ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;W&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;W&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Mat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;H&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;gnn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;H&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;H&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;W&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;W&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The important thing to note here is that this message passing procedure is a recurrence relation, which like the graph grammar and WL algorithm seen earlier, can be defined inductively. &lt;a href=&quot;https://cs.stanford.edu/people/jure/pubs/graphsage-nips17.pdf&quot;&gt;Hamilton et al. (2017)&lt;/a&gt; also consider induction in the context of representation learning, although their definition is more closely related to the concept of generalization. It would be interesting to explore the connection between induction in these two settings, and we will have more to say about matrix recurrence relations &lt;a href=&quot;#graphs-computationally&quot;&gt;in a bit&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;graph-languages&quot;&gt;Graph languages&lt;/h1&gt;

&lt;p&gt;Approximately 20% of the human cerebral cortex is devoted to &lt;a href=&quot;https://en.wikipedia.org/wiki/Occipital_lobe&quot;&gt;visual processing&lt;/a&gt;. By using visual representations, language designers can tap into powerful pattern matching abilities which are often underutilized by linear symbolic writing systems. Graphs are one such example which have found many applications as reasoning and communication devices in various &lt;a href=&quot;https://web.engr.oregonstate.edu/~erwig/papers/VLSemantics_JVLC98.pdf&quot;&gt;domain-specific languages&lt;/a&gt;:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Language&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Example&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Finite-state_machine&quot;&gt;Finite automata&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;br /&gt;&lt;center&gt;&lt;img align=&quot;center&quot; width=&quot;50%&quot; src=&quot;https://upload.wikimedia.org/wikipedia/commons/9/94/DFA_example_multiplies_of_3.svg&quot; /&gt;&lt;/center&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://www.mscs.dal.ca/%7Eselinger/papers/graphical-bib/public/Penrose-applications-of-negative-dimensional-tensors.pdf&quot;&gt;Tensor networks&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;br /&gt;&lt;center&gt;&lt;img align=&quot;center&quot; width=&quot;50%&quot; src=&quot;https://tensornetwork.org/diagrams/tensor_diagrams.png&quot; /&gt;&lt;/center&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Causal_graph&quot;&gt;Causal graphs&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;br /&gt;&lt;center&gt;&lt;img align=&quot;center&quot; width=&quot;50%&quot; src=&quot;https://upload.wikimedia.org/wikipedia/commons/e/ea/College_notID.png&quot; /&gt;&lt;/center&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://www.cs.mcgill.ca/~prakash/Pubs/category_theory_notes.pdf&quot;&gt;Category theory&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;br /&gt;&lt;center&gt;&lt;img align=&quot;center&quot; width=&quot;50%&quot; src=&quot;https://upload.wikimedia.org/wikipedia/commons/e/ef/Commutative_diagram_for_morphism.svg&quot; /&gt;&lt;/center&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://www.mscs.dal.ca/%7Eselinger/papers/graphical-bib/public/Penrose-applications-of-negative-dimensional-tensors.pdf&quot;&gt;Penrose notation&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;br /&gt;&lt;center&gt;&lt;img align=&quot;center&quot; width=&quot;50%&quot; src=&quot;https://enacademic.com/pictures/enwiki/80/Penrose_covariant_derivate.svg&quot; /&gt;&lt;/center&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;http://www-pnp.physics.ox.ac.uk/~barra/teaching/feynman.pdf&quot;&gt;Feynman diagrams&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;br /&gt;&lt;center&gt;&lt;img align=&quot;center&quot; width=&quot;50%&quot; src=&quot;https://upload.wikimedia.org/wikipedia/commons/1/1f/Feynmann_Diagram_Gluon_Radiation.svg&quot; /&gt;&lt;/center&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;!--| [Petri networks](https://en.wikipedia.org/wiki/Petri_net) | &lt;br/&gt;&lt;center&gt;&lt;img align=&quot;center&quot; width=&quot;50%&quot; src=&quot;https://upload.wikimedia.org/wikipedia/commons/d/d7/Animated_Petri_net_commons.gif&quot;/&gt;&lt;/center&gt; |--&gt;
&lt;!--| [Proof networks](https://en.wikipedia.org/wiki/Proof_net) | &lt;br/&gt;&lt;center&gt;&lt;img align=&quot;center&quot; width=&quot;50%&quot; src=&quot;https://www.researchgate.net/profile/Marco_Solieri/publication/311737880/figure/fig7/AS:501886778576905@1496670540685/Example-a-mMELL-proof-net-left-and-two-simple-mixed-nets-that-belong-to-its-expansion.png&quot;/&gt;&lt;/center&gt; |--&gt;

&lt;p&gt;As &lt;a href=&quot;https://www.math3ma.com/blog/matrices-probability-graphs&quot;&gt;Bradley (2019)&lt;/a&gt; vividly portrays in her writing, we can think of a matrix as not just a two-dimensional array, but a &lt;em&gt;function on a vector space&lt;/em&gt;. This perspective can be depicted using a bipartite graph:&lt;/p&gt;

&lt;center&gt;
&lt;a href=&quot;https://www.math3ma.com/blog/matrices-probability-graphs&quot;&gt;&lt;img align=&quot;center&quot; width=&quot;75%&quot; src=&quot;https://uploads-ssl.webflow.com/5b1d427ae0c922e912eda447/5c7ed4bcea0c9faeafe61466_pic1.jpg&quot; /&gt;&lt;/a&gt;
&lt;/center&gt;

&lt;p&gt;Not only do matrices correspond to graphs, graphs also correspond to matrices. One way to think of a graph is just a boolean matrix, or real matrix for weighted graphs. Consider an adjacency matrix containing nodes V, and edges E, where:&lt;/p&gt;

\[\begin{align*}
\mathbf A \in \mathbb B^{|V|\times|V|} \text{ where } \mathbf A[u, v] =
    \begin{cases}
       1,&amp;amp; \text{if } u, v \in E \\
       0,&amp;amp; \text{otherwise}
    \end{cases}
\end{align*}\]

&lt;table&gt;
&lt;tr&gt;
&lt;td&gt; &lt;center&gt;&lt;b&gt;Geometric&lt;/b&gt;&lt;/center&gt; &lt;/td&gt; &lt;td&gt;&lt;center&gt;&lt;b&gt;&lt;center&gt;Matrix&lt;/center&gt;&lt;/b&gt;&lt;/center&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;center&gt;&lt;img src=&quot;/images/ld_graph_dot.svg&quot; width=&quot;50%&quot; /&gt;&lt;/center&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;center&gt;&lt;img src=&quot;/images/ld_graph_mat.png&quot; /&gt;&lt;/center&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Note the lower triangular structure of the adjacency matrix, indicating it contains no cycles, a property that is not immediately obvious from the naïve geometric layout. Any graph whose adjacency matrix can be reordered into triangular form is a &lt;a href=&quot;https://en.wikipedia.org/wiki/Directed_acyclic_graph&quot;&gt;directed acyclic graph&lt;/a&gt;. Called a topological ordering, this algorithm can be implemented by &lt;a href=&quot;https://en.wikipedia.org/wiki/Topological_sorting#Parallel_algorithms&quot;&gt;repeatedly squaring&lt;/a&gt; the adjacency matrix.&lt;/p&gt;

&lt;p&gt;Both the geometric and matrix representations impose an extrinsic perspective on graphs, each with their own advantages and drawbacks. 2D renderings can be visually compelling, but require solving a &lt;a href=&quot;https://en.wikipedia.org/wiki/Crossing_number_(graph_theory)&quot;&gt;minimal crossing number&lt;/a&gt; or similar optimization to make connectivity plain to the naked eye. While graph drawing is an active &lt;a href=&quot;http://www.graphdrawing.org/&quot;&gt;field of research&lt;/a&gt;, matrices can often reveal symmetries that are not obvious from a naïve graph layout (and vis versa).&lt;/p&gt;

&lt;p&gt;Matrices are problematic for some reasons. Primarily, by treating a graph as a matrix, we impose an ordering over all vertices which is often arbitrary. Note also its sparsity, and consider the size of the matrix required to store even small graphs. While problematic, this can be overcome with &lt;a href=&quot;https://en.wikipedia.org/wiki/Sparse_matrix&quot;&gt;certain optimizations&lt;/a&gt;. Despite these issues, matrices and are a natural representation choice for many graph algorithms, particularly on modern parallel processing hardware.&lt;/p&gt;

&lt;center&gt;&lt;a href=&quot;https://epubs.siam.org/doi/book/10.1137/1.9780898719918&quot;&gt;&lt;img src=&quot;/images/graph_linear_algebra.png&quot; width=&quot;60%&quot; /&gt;&lt;/a&gt;&lt;/center&gt;

&lt;p&gt;Just like matrices, we can also think of a graph as a function, or &lt;a href=&quot;https://en.wikipedia.org/wiki/Transition_system&quot;&gt;transition system&lt;/a&gt;, which carries information from one state to the next - given a state or set of states, the graph tells us which other states are reachable. Recent work in graph theory has revealed a fascinating duality between &lt;a href=&quot;https://epubs.siam.org/doi/book/10.1137/1.9780898719918&quot;&gt;graphs and linear algebra&lt;/a&gt;, holding many important insights for dynamical processes on graphs.&lt;/p&gt;

&lt;h1 id=&quot;graphs-computationally&quot;&gt;Graphs, computationally&lt;/h1&gt;

&lt;p&gt;What happens when we take a square matrix \(\mathbb{R}^{n\times n}\) and raise it to a power? Which kinds of matrices converge and what are their asymptotics? This is a very fertile line of inquiry which has occupied engineers for the better part of the last century, with important applications in &lt;a href=&quot;https://books.google.ca/books/about/Works_on_the_Foundations_of_Statistical.html?id=Nbz_AwAAQBAJ&quot;&gt;statistical phyics&lt;/a&gt;, &lt;a href=&quot;https://link.springer.com/content/pdf/10.1007/BF02523124.pdf&quot;&gt;control theory&lt;/a&gt;, and &lt;a href=&quot;http://proceedings.mlr.press/v22/vinyals12/vinyals12.pdf&quot;&gt;deep learning&lt;/a&gt;. Linear algebra gives us many tricks for designing the matrix and normalizing the product to promote convergence.&lt;/p&gt;

&lt;p&gt;One way to interpret this is as follows: each time we multiply a matrix by a vector \(\mathbb{R}^{n}\), we are effectively simulating a dynamical system at discrete time steps. This method is known as &lt;a href=&quot;https://cs.mcgill.ca/~wlh/comp766/files/chapter1_draft_mar29.pdf#page=11&quot;&gt;power iteration&lt;/a&gt; or the Krylov method in linear algebra. In the limit, we are seeking &lt;em&gt;fixpoints&lt;/em&gt;, or eigenvectors, which are these islands of stability in our dynamical system. If we initialize our state at such a point, the transition matrix will send us straight back to where we started.&lt;/p&gt;

\[f(x, y) = \begin{bmatrix}
\frac{cos(x+2y)}{x} &amp;amp; 0 \\ 0 &amp;amp; \frac{sin(x-2y)}{y}
\end{bmatrix} *
\begin{bmatrix}x\\y\end{bmatrix} =
\begin{bmatrix}cos(x+2y)\\sin(x-2y)\end{bmatrix}\]

&lt;!--https://www.wolframalpha.com/input/?i=%7B%7Bcos%28x%2B2*y%29%2Fx%7D%2C+0%7D%2C+%7B0%2C%7Bsin%28x-2*y%29%2Fy%7D%7D+eigenvalues--&gt;
&lt;center&gt;&lt;img src=&quot;/images/vector_field.png&quot; width=&quot;63%&quot; /&gt;&lt;/center&gt;

&lt;p&gt;Locating a point where \(f(x, y) = f\circ f(x, y)\), indicates the trajectory has terminated. There exists a &lt;a href=&quot;https://en.wikipedia.org/wiki/Brouwer_fixed-point_theorem&quot;&gt;famous theorem&lt;/a&gt; from Brouwer: given a set \(S\) which contains its limits (i.e. &lt;em&gt;closed&lt;/em&gt;), whose contents are all a finite distance apart (i.e. &lt;em&gt;bounded&lt;/em&gt;), every continuous function from the set onto itself (\(f: S \rightarrow S\)) will map at least one of its members \(x: S\), called a fixpoint, onto itself (\(f(x)=x\)). Such points describe the asymptotic behavior of our function.&lt;/p&gt;

&lt;p&gt;First, let’s get some definitions out of the way.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  𝔹 → True | False
  𝔻 → 1 | ... | 9
  ℕ → 𝔻 | 𝔻0  | 𝔻ℕ
  ℤ → 0 | ℕ   | -ℕ
  ℚ → ℕ | ℤ/ℕ
  ℝ → ℕ | ℕ.ℕ | -ℝ
  ℂ → ℝ + ℝi
  ℍ → ℝ + ℝi + ℝj + ℝk
  T → 𝔹 | ℕ | ℤ | ℚ | ℝ | ℂ | ℍ
  n → ℕ
vec → [Tⁿ]
mat → [[Tⁿ]ⁿ]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can think of the Krylov method as either a matrix-matrix or matrix-vector product, or a recurrence relation with some normalization:&lt;/p&gt;

&lt;details&gt;
&lt;summary&gt;Krylov Method&lt;/summary&gt;
&lt;center&gt;&lt;img src=&quot;http://krylov-centre.ru/rus/images/exp_base/base-doccamers/base-doccamers-big-eng.jpg&quot; width=&quot;50%&quot; /&gt;&lt;/center&gt;
&lt;p align=&quot;justify&quot;&gt; There exists in St. Petersburg a naval research facility, known as the Krylov Shipbuilding Research Institute, which houses the world&apos;s largest &lt;a href=&quot;https://krylov-centre.ru/en/experimental/base-doccamers/&quot;&gt;full ocean depth hydraulic pressure tank&lt;/a&gt;. Capable of simulating in excess of 20,000 PSI, the DK-1000 is used to test deepwater submersible vessels. At such pressure, even water itself undergoes ~5% compression. Before inserting your &lt;a href=&quot;https://fivedeeps.com/home/technology/sub/&quot;&gt;personal submarine&lt;/a&gt;, you may wish to perform a finite element analysis to check hull integrity. Instabilities in the stiffness matrix may produce disappointing results.&lt;/p&gt;
&lt;center&gt;&lt;a href=&quot;https://www.wolframalpha.com/input/?i=water+density+vs+pressure+at+20+deg+c&quot;&gt;&lt;img src=&quot;/images/water_density.svg&quot; /&gt;&lt;/a&gt;&lt;/center&gt;
&lt;/details&gt;

&lt;table&gt;
&lt;tr&gt;
&lt;td&gt; &lt;center&gt;&lt;b&gt;Grammar&lt;/b&gt;&lt;/center&gt; &lt;/td&gt; &lt;td&gt;&lt;center&gt;&lt;b&gt;&lt;center&gt;Example&lt;/center&gt;&lt;/b&gt;&lt;/center&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;

&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mmp → mat | mat * mmp
mvp → (mmp) * vec
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;p&gt;\((\mathbf{M}\mathbf{M})\mathbf{v}, (\mathbf{M}\mathbf{M}\mathbf{M})\mathbf{v}, \ldots\)&lt;/p&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;

&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
mvp → mat * vec | mat * (mvp)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;p&gt;\(\mathbf{M}(\mathbf{M}\mathbf{v}), \mathbf{M}(\mathbf{M}(\mathbf{M}\mathbf{v})), \ldots\)&lt;/p&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;

&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;fun → mat * vec / ‖ mat * vec ‖
rec → fun | mat * rec / ‖ mat * rec ‖
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;p&gt;\(\frac{\mathbf{M}\mathbf{v}}{\|\mathbf{M}\mathbf{v}\|}, \frac{\mathbf{M}\frac{\mathbf{M}\mathbf{v}}{\|\mathbf{M}\mathbf{v}\|}}{\|\mathbf{M}\frac{\mathbf{M}\mathbf{v}}{\|\mathbf{M}\mathbf{v}\|}\|}, \frac{\mathbf{M}\frac{\mathbf{M}\frac{\mathbf{M}\mathbf{v}}{\|\mathbf{M}\mathbf{v}\|}}{\|\mathbf{M}\frac{\mathbf{M}\mathbf{v}}{\|\mathbf{M}\mathbf{v}\|}\|}}{\|\mathbf{M}\frac{\mathbf{M}\frac{\mathbf{M}\mathbf{v}}{\|\mathbf{M}\mathbf{v}\|}}{\|\mathbf{M}\frac{\mathbf{M}\mathbf{v}}{\|\mathbf{M}\mathbf{v}\|}\|}\|}, \ldots\)&lt;/p&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Regrouping the order of matrix multiplication offers various computational benefits, and adding normalization prevents singularities from emerging. &lt;a href=&quot;https://cs.mcgill.ca/~wlh/comp766/files/chapter2_draft_mar29.pdf&quot;&gt;Alternate normalization schemes&lt;/a&gt; have been developed for various applications in graphs. This sequence forms the so-called &lt;a href=&quot;http://www.mathnet.ru/links/701af3446efa9590ab957fb2d9b5ddd5/im5215.pdf&quot;&gt;Krylov matrix&lt;/a&gt; (Krylov, 1931):&lt;/p&gt;

\[\mathbf{K}_{i} = \begin{bmatrix}\mathbf{v} &amp;amp; \mathbf{M}\mathbf{v} &amp;amp; \mathbf{M}^{2}\mathbf{v} &amp;amp; \cdots &amp;amp; \mathbf{M}^{i-1}\mathbf{v} \end{bmatrix}\]

&lt;p&gt;There exists a famous theorem known as the &lt;a href=&quot;https://en.wikipedia.org/wiki/Perron–Frobenius_theorem&quot;&gt;Perron-Frobenius theorem&lt;/a&gt;, which states that if \(\mathbf M \in \mathcal T^{n \times  n}\), then \(\mathbf M\) has a unique largest eigenvalue \(\lambda \in \mathcal T\) and dominant eigenvector \(\mathbf{q} \in \mathcal T^{n}\). It has long been known that under some weak assumptions, \(\lim_{i\rightarrow \infty} \mathbf{M}^i \mathbf{v} = c\mathbf{q}\) where \(c\) is some constant. We are primarily interested in determinstic transition systems, where \(\mathcal T \in \{\mathbb B, \mathbb N\}\).&lt;/p&gt;

&lt;p&gt;The Krylov methods have important applications for studying &lt;a href=&quot;https://en.wikipedia.org/wiki/Graph_dynamical_system&quot;&gt;dynamical systems&lt;/a&gt; and &lt;a href=&quot;https://arxiv.org/pdf/1712.00468.pdf&quot;&gt;graph signal processing&lt;/a&gt;. Researchers are just beginning to understand how eigenvalues of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Laplacian_matrix#Laplacian_matrix_for_simple_graphs&quot;&gt;graph Laplacian&lt;/a&gt; affect the asymptotics of dynamical processes on graphs. We have already seen one example of these in the &lt;a href=&quot;#weisfeiler-lehman&quot;&gt;WL algorithm&lt;/a&gt;. Another example of graph computation can be found in &lt;a href=&quot;http://theory.stanford.edu/~virgi/cs367/papers/valiantcfg.pdf&quot;&gt;Valiant (1975)&lt;/a&gt;, who shows a CFL parsing algorithm which is equivalent to matrix multiplication.&lt;/p&gt;

&lt;!--Three steps of Barabási&apos;s [preferential attachment algorithm](https://en.wikipedia.org/wiki/Preferential_attachment):--&gt;

&lt;!--|DOT Graph|Matrix|--&gt;
&lt;!--|:-------:|:----:|--&gt;
&lt;!--|&lt;center&gt;&lt;img src=&quot;/images/pref_graph0.svg&quot;/&gt;&lt;/center&gt;|&lt;center&gt;&lt;img src=&quot;/images/pref_mat0.png&quot;/&gt;&lt;/center&gt;|--&gt;
&lt;!--|&lt;center&gt;&lt;img src=&quot;/images/pref_graph1.svg&quot;/&gt;&lt;/center&gt;|&lt;center&gt;&lt;img src=&quot;/images/pref_mat1.png&quot;/&gt;&lt;/center&gt;|--&gt;
&lt;!--|&lt;center&gt;&lt;img src=&quot;/images/pref_graph2.svg&quot;/&gt;&lt;/center&gt;|&lt;center&gt;&lt;img src=&quot;/images/pref_mat2.png&quot;/&gt;&lt;/center&gt;|--&gt;

&lt;center&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;TIL: CFL parsing can be reduced to boolean matrix multiplication (Valiant, 1975), known to be subcubic (Strassen, 1969), and later proven an asymptotic lower bound (Lee, 1997). This admits efficient GPGPU implementation (Azimov, 2017) in &lt;a href=&quot;https://twitter.com/YaccConstructor?ref_src=twsrc%5Etfw&quot;&gt;@YaccConstructor&lt;/a&gt; &lt;a href=&quot;https://t.co/3Vbml0v6b9&quot;&gt;https://t.co/3Vbml0v6b9&lt;/a&gt;&lt;/p&gt;&amp;mdash; breandan (@breandan) &lt;a href=&quot;https://twitter.com/breandan/status/1277136195118600192?ref_src=twsrc%5Etfw&quot;&gt;June 28, 2020&lt;/a&gt;&lt;/blockquote&gt; &lt;script async=&quot;&quot; src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;
&lt;/center&gt;

&lt;p&gt;Yet another example of graph computation can be found in &lt;a href=&quot;https://research.cs.wisc.edu/wpis/papers/popl16.pdf&quot;&gt;Reps et al. (2016)&lt;/a&gt;, who show that boolean matrix algebra can be used for &lt;a href=&quot;https://en.wikipedia.org/wiki/Abstract_interpretation&quot;&gt;abstract interpretation&lt;/a&gt;. By representing control flow graphs as boolean matrix expressions, they show how to apply root-finding techniques like &lt;a href=&quot;https://en.wikipedia.org/wiki/Newton%27s_method&quot;&gt;Newton’s method&lt;/a&gt; (first observed by &lt;a href=&quot;https://www7.in.tum.de/um/bibdb/luttenbe/newtProgAn.pdf&quot;&gt;Esparza et al. (2010)&lt;/a&gt;) to dataflow analysis, e.g. for determining which states are reachable from some starting configuration by computing their transitive closure:&lt;/p&gt;

&lt;center&gt;&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;Newton&amp;#39;s method has some amazing applications for program analysis. Reps et al. (2016) show a mapping between control flow graphs and boolean matrix expressions. Graph reachability amounts to finding fixed points of a semiring equation. What a goldmine! &lt;a href=&quot;https://t.co/BFCZiJ1b6n&quot;&gt;https://t.co/BFCZiJ1b6n&lt;/a&gt; &lt;a href=&quot;https://t.co/Jd86bEXiIu&quot;&gt;pic.twitter.com/Jd86bEXiIu&lt;/a&gt;&lt;/p&gt;&amp;mdash; breandan (@breandan) &lt;a href=&quot;https://twitter.com/breandan/status/1282160392228286466?ref_src=twsrc%5Etfw&quot;&gt;July 12, 2020&lt;/a&gt;&lt;/blockquote&gt; &lt;script async=&quot;&quot; src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;&lt;/center&gt;

&lt;p&gt;We could spend all day listing various matrix algorithms for graph computation. Certainly, far better writers have done them justice. Instead, let’s just give some simple examples of dynamical processes on graphs.&lt;/p&gt;

&lt;h1 id=&quot;examples&quot;&gt;Examples&lt;/h1&gt;

&lt;p&gt;What happens if we define arithmetic operations on graphs? How could we define these operations in a way that allows us to perform computation? As we &lt;a href=&quot;#graph-languages&quot;&gt;already saw&lt;/a&gt;, one way to represent a directed graph is just a square matrix whose non-zero entries indicate edges between nodes. Just like real matrices in linear algebra, we can add, subtract, multiply and exponentiate them. &lt;a href=&quot;http://www.mit.edu/~kepner/GraphBLAS/GraphBLAS-Math-release.pdf#section.1.4&quot;&gt;Other composable operations&lt;/a&gt; are also possible.&lt;/p&gt;

&lt;p&gt;We will now show a few examples simulating a state machine using the Krylov method. For illustrative purposes, the state simply holds a vector of binary or integer values, although we can imagine it carrying other “messages” around the graph in a similar manner, using another algebra. Here, we will use the boolean algebra for matrix multiplication, where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; corresponds to logical disjunction (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;∨&lt;/code&gt;), and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt; corresponds to logical conjunction (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;∧&lt;/code&gt;):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;┌───┬───┬─────┬─────┐
│ x │ y │ x*y │ x+y │        Boolean Matrix Multiplication
├───┼───┼─────┼─────┤ ┌─       ─┐ ┌─ ─┐ ┌─                     ─┐
│ 0 │ 0 │  0  │  0  │ │ a  b  c │ │ j │ │ a * j + b * k + c * l │
│ 0 │ 1 │  0  │  1  │ │ d  e  f │*│ k │=│ d * j + e * k + f * l │
│ 1 │ 0 │  0  │  1  │ │ g  h  i │ │ l │ │ g * j + h * k + i * l │
│ 1 │ 1 │  1  │  1  │ └─       ─┘ └─ ─┘ └─                     ─┘
└───┴───┴─────┴─────┘
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;linear-chains&quot;&gt;Linear chains&lt;/h2&gt;

&lt;p&gt;Let’s iterate through a linked list. To do so, we will initialize the pointer to the head of the list, and use multiplication to advance the pointer by a single element. We add an implicit self-loop to the final node, and halt whenever a fixpoint is detected. This structure is known as an &lt;a href=&quot;https://en.wikipedia.org/wiki/Absorbing_Markov_chain&quot;&gt;absorbing Markov chain&lt;/a&gt;.&lt;/p&gt;

&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;&lt;center&gt;&lt;b&gt;Graph&lt;/b&gt;&lt;/center&gt;&lt;/td&gt; &lt;td&gt;&lt;center&gt;&lt;b&gt;Matrix&lt;/b&gt;&lt;/center&gt;&lt;/td&gt; &lt;td&gt;&lt;center&gt;&lt;b&gt;S&lt;/b&gt;&lt;/center&gt;&lt;/td&gt;&lt;td&gt;&lt;center&gt;&lt;b&gt;S&apos;&lt;/b&gt;&lt;/center&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;

&lt;div&gt;
        &lt;center&gt;&lt;img src=&quot;/images/lin0.svg&quot; /&gt;&lt;/center&gt;
      &lt;/div&gt;

&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    a  b  c
  ┌────────
a │ 0  0  0
b │ 1  0  0
c │ 0  1  1

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;

1
0
0

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;

0
1
0

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; 
&lt;div&gt;
        &lt;center&gt;&lt;img src=&quot;/images/lin1.svg&quot; /&gt;&lt;/center&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    a  b  c
  ┌────────
a │ 0  0  0
b │ 1  0  0
c │ 0  1  1

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;

0
1
0

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;

0
0
1

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; 
&lt;div&gt;
        &lt;center&gt;&lt;img src=&quot;/images/lin2.svg&quot; /&gt;&lt;/center&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    a  b  c
  ┌────────
a │ 0  0  0
b │ 1  0  0
c │ 0  1  1

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;

0
0
1

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;

0
0
1

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;h2 id=&quot;nondeterminstic-finite-automata&quot;&gt;Nondeterminstic finite automata&lt;/h2&gt;

&lt;p&gt;Simulating a DFA using a matrix can be inefficient since we only ever inhabit one state at a time. The real benefit of using matrices comes when simulating nondeterminstic finite automata, &lt;a href=&quot;#regular-languages&quot;&gt;seen earlier&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Formally, an NFA is a 5-tuple \(\langle Q, \Sigma, \Delta, q_0, F \rangle\), where \(Q\) is a finite set of states, \(\Sigma\) is the alphabet, \(\Delta :Q\times (\Sigma \cup \{\epsilon \})\rightarrow P(Q)\) is the transition function, \(q_0 \in Q\) is the initial state and \(F \subseteq Q\) are the terminal states. An NFA can be represented as a &lt;a href=&quot;https://www.cs.mcgill.ca/~prakash/Talks/lecture1.pdf&quot;&gt;labeled transition system&lt;/a&gt;, or directed graph whose adjacency matrix is defined by the transition function, with edge labels representing symbols from the alphabet and self-loops for each terminal state, both omitted for brevity.&lt;/p&gt;

&lt;p&gt;Typical &lt;a href=&quot;https://en.wikipedia.org/wiki/Nondeterministic_finite_automaton#Implementation&quot;&gt;implementations&lt;/a&gt; often require cloning the NFA when multiple transitions are valid, which can be inefficient. Instead of cloning the machine, we can simulate the superposition of all states using a single data structure:&lt;/p&gt;

&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;&lt;center&gt;&lt;b&gt;Graph&lt;/b&gt;&lt;/center&gt;&lt;/td&gt; &lt;td&gt;&lt;center&gt;&lt;b&gt;Matrix&lt;/b&gt;&lt;/center&gt;&lt;/td&gt; &lt;td&gt;&lt;center&gt;&lt;b&gt;S&lt;/b&gt;&lt;/center&gt;&lt;/td&gt;&lt;td&gt;&lt;center&gt;&lt;b&gt;S&apos;&lt;/b&gt;&lt;/center&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; 
&lt;div&gt;
        &lt;center&gt;&lt;img src=&quot;/images/dag0.svg&quot; /&gt;&lt;/center&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    a  b  c  d
  ┌───────────
a │ 0  0  0  0
b │ 1  0  0  0
c │ 1  0  0  0
d │ 0  1  1  1

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;

1
0
0
0

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;

0
1
1
0

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; 
&lt;div&gt;
        &lt;center&gt;&lt;img src=&quot;/images/dag1.svg&quot; /&gt;&lt;/center&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    a  b  c  d
  ┌───────────
a │ 0  0  0  0
b │ 1  0  0  0
c │ 1  0  0  0
d │ 0  1  1  1

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;

0
1
1
0

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;

0
0
0
1

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; 
&lt;div&gt;
        &lt;center&gt;&lt;img src=&quot;/images/dag2.svg&quot; /&gt;&lt;/center&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    a  b  c  d
  ┌───────────
a │ 0  0  0  0
b │ 1  0  0  0
c │ 1  0  0  0
d │ 0  1  1  1

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;

0
0
0
1

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;

0
0
0
1

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;

&lt;p&gt;We encode the accept state as a self cycle in order to detect the fixpoint criterion \(S_{t+1} = S_{t}\), after which we halt execution.&lt;/p&gt;

&lt;h2 id=&quot;dataflow-graphs&quot;&gt;Dataflow graphs&lt;/h2&gt;

&lt;p&gt;Suppose we have the function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f(a, b) = (a + b) * b&lt;/code&gt; and want to evaluate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f(2, 3)&lt;/code&gt;. For operators, we will need two tricks. First, all operators will retain their state, i.e. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;s along all operator diagonals. Second, when applying the operator, we will combine values using the operator instead of performing a sum.&lt;/p&gt;

&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;&lt;center&gt;&lt;b&gt;Graph&lt;/b&gt;&lt;/center&gt;&lt;/td&gt; &lt;td&gt;&lt;center&gt;&lt;b&gt;Matrix&lt;/b&gt;&lt;/center&gt;&lt;/td&gt; &lt;td&gt;&lt;center&gt;&lt;b&gt;S&lt;/b&gt;&lt;/center&gt;&lt;/td&gt;&lt;td&gt;&lt;center&gt;&lt;b&gt;S&apos;&lt;/b&gt;&lt;/center&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; 
&lt;div&gt;
        &lt;center&gt;&lt;img src=&quot;/images/dfg0.svg&quot; /&gt;&lt;/center&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    a  b  +  *
  ┌───────────
a │ 0  0  0  0
b │ 0  0  0  0
+ │ 1  1  1  0
* │ 0  1  1  1

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;

2
3
0
0

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;

0
0
5
3

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; 
&lt;div&gt;
        &lt;center&gt;&lt;img src=&quot;/images/dfg1.svg&quot; /&gt;&lt;/center&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    a  b  +  *
  ┌───────────
a │ 0  0  0  0
b │ 0  0  0  0
+ │ 1  1  1  0
* │ 0  1  1  1

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;

0
0
5
3

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;

0
0
0
15

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; 
&lt;div&gt;
        &lt;center&gt;&lt;img src=&quot;/images/dfg2.svg&quot; /&gt;&lt;/center&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    a  b  +  *
  ┌───────────
a │ 0  0  0  0
b │ 0  0  0  0
+ │ 1  1  1  0
* │ 0  1  1  1

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;

0
0
0
15

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;

0
0
0
15

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;center&gt;&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;Did you know? Arithmetic expressions can be efficiently parallelized using matrix arithmetic (Miller et al., 1987): &lt;a href=&quot;https://t.co/9Tr9hImPFA&quot;&gt;https://t.co/9Tr9hImPFA&lt;/a&gt; &lt;a href=&quot;https://t.co/8vBv9phssk&quot;&gt;pic.twitter.com/8vBv9phssk&lt;/a&gt;&lt;/p&gt;&amp;mdash; breandan (@breandan) &lt;a href=&quot;https://twitter.com/breandan/status/1283191471223517185?ref_src=twsrc%5Etfw&quot;&gt;July 15, 2020&lt;/a&gt;&lt;/blockquote&gt; &lt;script async=&quot;&quot; src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;&lt;/center&gt;

&lt;p&gt;The author was very excited to discover this technique while playing with matrices one day, only later to discover it was described 33 years earlier by &lt;a href=&quot;http://www.cs.cmu.edu/~glmiller/Publications/MRK86b.pdf&quot;&gt;Miller et al. (1987)&lt;/a&gt;. Miller was inspired by &lt;a href=&quot;http://www.cs.tau.ac.il/~amnon/Classes/2015-PRG/Papers/VSBR83.pdf&quot;&gt;Valiant et al.’s (1983)&lt;/a&gt; work in &lt;a href=&quot;https://en.wikipedia.org/wiki/Arithmetic_circuit_complexity&quot;&gt;arithmetic circuit complexity&lt;/a&gt;, who was in turn inspired by &lt;a href=&quot;http://www.cs.toronto.edu/~bor/Papers/fast-parallel-matrix-GCD.pdf&quot;&gt;Borodin et al.’s (1982)&lt;/a&gt; work on matrix computation. This line of research has recently been revisited by &lt;a href=&quot;https://www.math.ias.edu/~avi/PUBLICATIONS/MYPAPERS/NW96/final.pdf&quot;&gt;Nisan and Wigderson (1997)&lt;/a&gt; and later &lt;a href=&quot;https://www.cs.tau.ac.il/~shpilka/publications/KlivansShpilka_Learning_via_partial_derivatives.pdf&quot;&gt;Klivans and Shpilka (2003)&lt;/a&gt; which seeks to understand how circuit size and depth affects learning complexity.&lt;/p&gt;

&lt;h1 id=&quot;graphs-efficiently&quot;&gt;Graphs, efficiently&lt;/h1&gt;

&lt;p&gt;Due to their well-studied algebraic properties, graphs are suitable data structures for a wide variety of applications. Finding a reduction to a known graph problem can save years of effort, but graph algorithms can be challenging to implement efficiently, as dozens of libraries and compiler frameworks have found. Why have efficient implementations proven so difficult, and what has changed?&lt;/p&gt;

&lt;p&gt;One issue hindering efficient graph representation is their space complexity. Suppose we have a graph with \(10^5=100,000\) nodes, but only a single edge. We will need \(10^{5\times 2}\) bits, or about 1 GB to store its adjacency matrix, where an equivalent adjacency list would only consume \(\lceil 2\log_2 10^5 \rceil = 34\) bits. Most graphs are similarly sparse. But how do you multiply adjacency lists? One solution is to use a &lt;a href=&quot;https://en.wikipedia.org/wiki/Sparse_matrix&quot;&gt;sparse matrix&lt;/a&gt;, which is spatially denser proportional to its sparsity and can be linearly faster on parallel computing architectures.&lt;/p&gt;

&lt;center&gt;&lt;a href=&quot;http://faculty.cse.tamu.edu/davis/suitesparse.html&quot;&gt;&lt;img src=&quot;https://people.engr.tamu.edu/davis/suitesparse_files/SuiteSparse_logo.jpg&quot; width=&quot;60%&quot; /&gt;&lt;/a&gt;&lt;/center&gt;

&lt;p&gt;Perhaps the more significant barrier to widespread adoption of graph algorithms is their time complexity. Many interesting problems on graphs are NP-complete, including &lt;a href=&quot;https://en.wikipedia.org/wiki/Hamiltonian_path&quot;&gt;Hamiltonian path&lt;/a&gt; detection, &lt;a href=&quot;https://en.wikipedia.org/wiki/Travelling_salesman_problem&quot;&gt;TSP&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Subgraph_isomorphism_problem&quot;&gt;subgraph isomorphism&lt;/a&gt;. Many of those problems have approximations which are often tolerable, but even if exact solutions are needed, CS theory is primarily concerned with worst-case complexity, which seldom or rarely occurs in practice. Natural instances can often be solved quickly using heuristic-guided search, such as SAT or SMT solvers.&lt;/p&gt;

&lt;p&gt;Most graph algorithms are currently implemented using object oriented or algebraic data types as we &lt;a href=&quot;#graphs-inductively&quot;&gt;saw previously&lt;/a&gt;. While conceptually simple to grasp, this approach is computationally inefficient. We would instead prefer a high level API backed by a pure BLAS implementation. As numerous papers have shown, finding an efficient matrix representation opens the path to optimized execution on GPUs or SIMD-capable hardware. For example, all of the following automata can be greatly accelerated using sparse matrix arithmetic on modern hardware:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://doi.org/10.1007/978-3-030-38961-1_26&quot;&gt;Pushdown automata&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://people.na.infn.it/~murano/COMP1314/8.pdf&quot;&gt;Büchi automata&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://web.cs.iastate.edu/~ciardo/pubs/1989PNPM-SPNP.pdf&quot;&gt;Petri nets&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://doi.org/10.1109/APSEC.2018.00025&quot;&gt;Mealy machines&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://arxiv.org/pdf/1701.03038.pdf&quot;&gt;Finite state transducers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Suppose we want to access the source code of a program from within the program itself. How could we accomplish that? There is a famous &lt;a href=&quot;https://en.wikipedia.org/wiki/Kleene%27s_recursion_theorem&quot;&gt;theorem by Kleene&lt;/a&gt; which gives us a clue how to construct a self-replicating program. More specifically, we need an intermediate representation, or reified computation graph (i.e. runtime-accessible IR). Given any variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt;, we need some method &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y.graph()&lt;/code&gt; which programmatically returns its &lt;a href=&quot;https://en.wikipedia.org/wiki/Transitive_closure&quot;&gt;transitive closure&lt;/a&gt;, including upstream dependencies and downstream dependents. Depending on scope and granularity, this graph can expand very quickly, so efficiency is key.&lt;/p&gt;

&lt;center&gt;&lt;a href=&quot;https://github.com/breandan/kotlingrad#dataflow-graphs&quot;&gt;&lt;img src=&quot;https://raw.githubusercontent.com/breandan/kotlingrad/master/samples/src/main/resources/lr_batch_loss_graph.svg&quot; width=&quot;60%&quot; /&gt;&lt;/a&gt;&lt;/center&gt;

&lt;p&gt;With the advent of staged metaprogramming in domain-specific languages like &lt;a href=&quot;https://www.tensorflow.org/api_docs/python/tf/Graph&quot;&gt;TensorFlow&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/OCaml#MetaOCaml&quot;&gt;MetaOCaml&lt;/a&gt;, such graphs are available to introspect at runtime. By tracing all operations (e.g. using operator overloading) on an intermediate data structure (e.g. stack, AST, or DAG), these DSLs are able to embed a programming language in another language. At periodic intervals, they may perform certain optimizations (e.g. constant propagation, common subexpression elimination) and emit an intermediate language (e.g. CUDA, webasm) for optimized execution on special hardware, such as a GPU or TPU.&lt;/p&gt;

&lt;center&gt;&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;This &lt;a href=&quot;https://twitter.com/hashtag/GraphBLAS?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#GraphBLAS&lt;/a&gt; stuff is super exciting. Most graph algorithms can be expressed as linear algebra. Sparse matrix SIMD-backed graph algorithms lets us process orders-of-magnitude larger graphs. Similar to AD tools like Theano et al., this will give a huge boost to network science.&lt;/p&gt;&amp;mdash; breandan (@breandan) &lt;a href=&quot;https://twitter.com/breandan/status/1277505360127983618?ref_src=twsrc%5Etfw&quot;&gt;June 29, 2020&lt;/a&gt;&lt;/blockquote&gt; &lt;script async=&quot;&quot; src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;&lt;/center&gt;

&lt;p&gt;Recent work in linear algebra and sparse matrix representations for graphs &lt;a href=&quot;https://doi.org/10.1137/1.9780898719918.ch5&quot;&gt;shows us&lt;/a&gt; how to treat many recursive graph algorithms as pure matrix arithmetic, thus benefiting from SIMD acceleration. Researchers are just beginning to explore how these techniques can be used to &lt;a href=&quot;https://en.wikipedia.org/wiki/General-purpose_computing_on_graphics_processing_units&quot;&gt;transform general-purpose programs&lt;/a&gt; into graphs. We &lt;a href=&quot;#roadmap&quot;&gt;anticipate&lt;/a&gt; this effort will require further engineering to develop an efficient encoder, but see no fundamental obstacle for a common analysis framework or graph-based execution scheme.&lt;/p&gt;

&lt;!--A lot of the stuff in Graph Representation Learning is motivated by computational constraints. You can&apos;t instantiate the adjacency matrix, because it&apos;s too large, so you need all kinds of mathematical tricks to sum over or approximate it. But most graphs are sparse and have all kinds of symmetries. Finding the right graph embedding can get you real far...--&gt;

&lt;h1 id=&quot;programs-as-graphs&quot;&gt;Programs as graphs&lt;/h1&gt;

&lt;p&gt;Graphs are not only useful as data structures for representing programs, but we can think of the act of computation itself as traversing a graph on a binary configuration space. Each tick of the clock corresponds to one matrix multiplication on a boolean tape.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://repository.kulib.kyoto-u.ac.jp/dspace/bitstream/2433/103401/1/0482-14.pdf&quot;&gt;Futamura (1983)&lt;/a&gt; shows us that programs can be decomposed into two inputs: static and dynamic. While long considered a theoretical distinction, &lt;a href=&quot;https://en.wikipedia.org/wiki/Partial_evaluation&quot;&gt;partial evaluation&lt;/a&gt; has been successfully operationalized in several &lt;a href=&quot;https://dl.acm.org/doi/10.1145/3062341.3062381&quot;&gt;general purpose&lt;/a&gt; and &lt;a href=&quot;https://compilers.cs.uni-saarland.de/papers/gpce15.pdf&quot;&gt;domain-specific&lt;/a&gt; languages using this observation.&lt;/p&gt;

\[\mathbf P: I_{\text{static}} \times I_{\text{dynamic}} \rightarrow O\]

&lt;p&gt;Programs can be viewed as simply functions mapping inputs to output, and executing the program amounts to running a matrix dynamical system to completion. Consider the static case, in which we have all information available at compile-time. In order to evaluate the program, we can just multiply the program \(\mathbf P: \mathbb B^{\lvert S\rvert \times \lvert S\rvert}\) by the state \(S\) until termination:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    [P]────────────────────────────────           } Program
      ╲          ╲          ╲          ╲
[S₀]───*───[S₁]───*───[S₂]───*───[..]───*───[Sₜ]  } TM tape
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now consider the dynamic case, where the matrix \(\mathbf P\) at each time step might be governed by another program:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;        [Q]─────────────────────                  } Dynamics
          ╲          ╲          ╲
    [P₀]───*───[P₁]───*───[..]───*───[Pₜ₋₁]       } Program
      ╲          ╲          ╲          ╲
[S₀]───*───[S₁]───*───[S₂]───*───[..]───*───[Sₜ]  } TM tape
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We might also imagine the dynamic inputs as being generated by successively higher order programs. Parts of these may be stored elsewhere in memory.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;                     ⋮
            [R₀]─────────                         } World model
              ╲          ╲
        [Q₀]───*───[..]───*───[Pₜ₋₂]              } Dynamics
          ╲          ╲          ╲
    [P₀]───*───[P₁]───*───[..]───*───[Pₜ₋₁]       } Program
      ╲          ╲          ╲          ╲
[S₀]───*───[S₁]───*───[S₂]───*───[..]───*───[Sₜ]  } TM tape
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;What about programs of varying length? It may be the case we want to learn programs where \(t\) varies. The key is, we can choose an upper bound on \(t\), and search for fixed points, i.e. halt whenever \(S_t = S_{t+1}\).&lt;/p&gt;

&lt;p&gt;There will always be some program, at the interface of the machine and the real world, which must be approximated. One question worth asking is how large does \(\lvert S\rvert\) need to be in order to do so? If it is very large, this procedure might well be intractable. Time complexity appears to be at worst \(\mathcal{O}(tn^{2.37})\), using &lt;a href=&quot;https://en.wikipedia.org/wiki/Coppersmith%E2%80%93Winograd_algorithm&quot;&gt;CW matmuls&lt;/a&gt;, although considerably better if \(\mathbf P\) is sparse.&lt;/p&gt;

&lt;h1 id=&quot;program-synthesis&quot;&gt;Program synthesis&lt;/h1&gt;

&lt;p&gt;Many people have asked me, “Why should developers care about automatic differentiation?” Yes, we can use it to build machine learning systems. Yes, it has specialized applications in &lt;a href=&quot;https://arxiv.org/abs/1911.05063&quot;&gt;robotics&lt;/a&gt;, &lt;a href=&quot;https://doi.org/10.1145/363831.364886&quot;&gt;space travel&lt;/a&gt;, and &lt;a href=&quot;https://arxiv.org/pdf/1910.00935.pdf&quot;&gt;physical simulation&lt;/a&gt;. But does it really matter for software engineers?&lt;/p&gt;

&lt;p&gt;I have been thinking carefully about this question, and although it is not yet fully clear to me, I am starting to see how some pieces fit together. A more complete picture will require more research, engineering and rethinking the role of software, compilers and machine learning.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    [P]────────────────────────────────           } Program
      ╲          ╲          ╲          ╲
[S₀]───*───[S₁]───*───[S₂]───*───[..]───*───[Sₜ]  } TM tape
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Consider the static case seen above. Since the matrix \(\mathbf P\) is fixed throughout execution, to learn \(\mathbf P\), we need to solve the following minimization problem:&lt;/p&gt;

\[\underset{P}{\text{argmin}}\sum_{i \sim I_{static}}\mathcal L(P^t S^i_0, S_t)\]

&lt;p&gt;One issue with this formulation is we must rely on a loss over \(S_t\), which is often too sparse and generalizes poorly. It may be the case that many interesting program synthesis problems have &lt;a href=&quot;https://en.wikipedia.org/wiki/Optimal_substructure&quot;&gt;optimal substructure&lt;/a&gt;, so we should be making “progress” towards a goal state, and might be able to define a cross-entropy loss over intermediate states to guide the search process. This intuition stems from RL and needs to be explored in further depth.&lt;/p&gt;

&lt;p&gt;Some, including &lt;a href=&quot;https://arxiv.org/pdf/1608.04428.pdf&quot;&gt;Gaunt et al., (2016)&lt;/a&gt;, have shown gradient is not very effective, as the space of boolean circuits is littered with islands which have zero gradient (some results have suggested the TerpreT problem is &lt;a href=&quot;https://luxxxlucy.github.io/projects/2020_terpret/terpret.html&quot;&gt;surmountable&lt;/a&gt; by applying various smoothing tricks). However Gaunt’s representation is also relatively complex – effectively, they are trying to learn a recursively enumerable language using something like a &lt;a href=&quot;https://arxiv.org/pdf/1410.5401.pdf&quot;&gt;Neural Turing Machine&lt;/a&gt; (Graves et al., 2014).&lt;/p&gt;

&lt;p&gt;More recent work, including that of &lt;a href=&quot;https://arxiv.org/pdf/1912.01412.pdf&quot;&gt;Lample et al., (2019)&lt;/a&gt;, demonstrated gradient is effective for learning programs belonging to the class of context-free languages. This space is often much more tractable to search through and generate synthetic training data. Furthermore, this appears to be well within the reach of modern language models, i.e. &lt;a href=&quot;https://arxiv.org/abs/1506.03134&quot;&gt;pointer networks&lt;/a&gt; and &lt;a href=&quot;https://arxiv.org/pdf/1706.03762.pdf&quot;&gt;transformers&lt;/a&gt;.&lt;/p&gt;

&lt;center&gt;&lt;img src=&quot;https://raw.githubusercontent.com/quark0/darts/master/img/darts.png&quot; width=&quot;60%&quot; /&gt;&lt;/center&gt;

&lt;p&gt;In the last year, a number of interesting results in differentiable architecture search started to emerge. &lt;a href=&quot;https://arxiv.org/pdf/1806.09055.pdf&quot;&gt;DARTS&lt;/a&gt; (Liu et al., 2019) proposes to use gradient to search through the space of directed graphs. The authors first perform a continuous relaxation of the discrete graph, by reweighting the output of each potential edge by a hyperparameter, optimizing over the space of edges using gradient descent, then taking a softmax to discretize the output graph.&lt;/p&gt;

&lt;center&gt;&lt;a href=&quot;https://youtu.be/rwBbYhOAnPo?t=28272&quot;&gt;&lt;img src=&quot;/images/solar_lezma.png&quot; width=&quot;70%&quot; /&gt;&lt;/a&gt;&lt;/center&gt;

&lt;p&gt;&lt;a href=&quot;https://youtu.be/rwBbYhOAnPo?t=28272&quot;&gt;Solar-Lezma (2020)&lt;/a&gt; calls this latter approach, “program extraction”, where a network implicitly or explicitly parameterizes a function, which after training, can be decoded into a symbolic expression. This perspective also aligns with Ian Goodfellow’s notion of deep networks as performing computation, where each layer represents a residual step in a parallel program:&lt;/p&gt;

&lt;center&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&amp;quot;Can neural networks be made to reason?&amp;quot; Conversation with Ian Goodfellow (&lt;a href=&quot;https://twitter.com/goodfellow_ian?ref_src=twsrc%5Etfw&quot;&gt;@goodfellow_ian&lt;/a&gt;). Full version: &lt;a href=&quot;https://t.co/3MYC8jWjwl&quot;&gt;https://t.co/3MYC8jWjwl&lt;/a&gt; &lt;a href=&quot;https://t.co/tGcDwgZPA1&quot;&gt;pic.twitter.com/tGcDwgZPA1&lt;/a&gt;&lt;/p&gt;&amp;mdash; Lex Fridman (@lexfridman) &lt;a href=&quot;https://twitter.com/lexfridman/status/1130501145548513280?ref_src=twsrc%5Etfw&quot;&gt;May 20, 2019&lt;/a&gt;&lt;/blockquote&gt; &lt;script async=&quot;&quot; src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt; 
&lt;/center&gt;

&lt;p&gt;A less charitable interpretation is that Goodfellow is simply using a metaphor to explain deep learning to lay audience, but I prefer to think he is communicating something deeper about the role of recurrent nonlinear function approximators as computational primitives, where adding depth effectively increases serial processing capacity and layer width increases bandwidth. There may be an interesting connection between this idea and &lt;a href=&quot;https://www.cs.tau.ac.il/~shpilka/publications/KlivansShpilka_Learning_via_partial_derivatives.pdf&quot;&gt;arithmetic circuit complexity&lt;/a&gt; (Klivans and Shpilka, 2003).&lt;/p&gt;

&lt;h1 id=&quot;roadmap&quot;&gt;Roadmap&lt;/h1&gt;

&lt;p&gt;Much work lies ahead for the interested reader. Before we can claim to have a unification of graph linear algebra and computer science, at least three technical hurdles will need to be cleared. First is theoretical: we must show that binary matrix mutiplication is Turing-equivalent. Second, we must show a proof-of-concept via binary recompilation. Third, we must develop a robust toolchain for compiling and introspecting a wide variety of graph programs.&lt;/p&gt;

&lt;p&gt;While it would be sufficient to prove boolean matrix multiplication corresponds to Peano Arithmetic, a constructive proof taking physics into consideration is needed. Given some universal language \(\mathcal L\), and a program implementing a boolean vector function \(\mathcal V: \mathbb B^i \rightarrow \mathbb B^o \in \mathcal L\), we must derive a transformation \(\mathcal T_\mathcal L: \mathcal V \rightarrow \mathcal M\), which maps \(\mathcal V\) to a boolean matrix function \(\mathcal M: \mathbb B^{j \times k} \times \mathbb B^{l\times m}\), while preserving asymptotic complexity \(\mathcal O(\mathcal M) \lt \mathcal O(\mathcal V)\), i.e. which is no worse than a constant factor in space or time. Clearly, the identity function \(\mathcal I(\mathcal V)\) is a valid candidate for \(\mathcal T_{\mathcal L}\). But as recent GPGPU research has shown, we can do much better.&lt;/p&gt;

&lt;center&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;n.b. Not saying anything about the workload, just the architecture - Software 1.0 may still be the dominant paradigm. I&amp;#39;m saying there is a binary translation from load/store/jump/branch instructions to sparse BLAS primitives which imposes no constraints on the programming model.&lt;/p&gt;&amp;mdash; breandan (@breandan) &lt;a href=&quot;https://twitter.com/breandan/status/1278156002240716800?ref_src=twsrc%5Etfw&quot;&gt;July 1, 2020&lt;/a&gt;&lt;/blockquote&gt; &lt;script async=&quot;&quot; src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt; 
&lt;/center&gt;

&lt;p&gt;The second major hurdle to graph computation is developing a binary recompiler which translates programs into optimized BLAS instructions. The resulting program will eventually need to demonstrate performant execution across a variety of heterogenously-typed programs, e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Int&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Float16&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Float32&lt;/code&gt;, and physical SIMD devices. Developing the infrastructure for such a recompiler will be a major engineering undertaking in the next two decades as the world transitions to graph computing. Program induction will likely be a key step to accelerating these graphs on physical hardware.&lt;/p&gt;

&lt;p&gt;The third and final hurdle is to develop a robust compiler toolchain for graph computation. At some point, users will be able to feed a short program into a source-to-source transpiler and have the program slightly rewritten with semantics preserving guarantees. This will require progress in abstract interpretation, programming tools, runtime instrumentation, as well as shape-safe libraries and frameworks. Ultimately, we hypothesize users will adopt a more declarative programming style with resource-aware and type-directed constraints. This step will require fundamental progress in program induction and consume the better half of the next century to fully realize.&lt;/p&gt;

&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://cs.mcgill.ca/~wlh/comp766/notes.html&quot;&gt;Graph Representation Learning&lt;/a&gt; (Hamilton, 2020)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://epubs.siam.org/doi/book/10.1137/1.9780898719918&quot;&gt;Graph Algorithms in the Language of Linear Algebra&lt;/a&gt; (Kepner &amp;amp; Gilbert, 2011)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.contrib.andrew.cmu.edu/~ryanod/&quot;&gt;Analysis of Boolean Functions&lt;/a&gt; (O’Donnell, 2014)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.cs.yale.edu/homes/spielman/sagt/sagt.pdf&quot;&gt;Spectral and Algebraic Graph Theory&lt;/a&gt; (Spielman, 2019)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.mit.edu/~kepner/GraphBLAS/GraphBLAS-Math-release.pdf&quot;&gt;GraphBLAS Mathematics&lt;/a&gt; (Kepner, 2017)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://doi.org/10.1017/CBO9781139172752&quot;&gt;Term Rewriting and All That&lt;/a&gt; (Baader &amp;amp; Nipkow, 1998)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.rand.org/content/dam/rand/pubs/research_memoranda/2008/RM704.pdf&quot;&gt;Representation of Events in Nerve Nets and Finite Automata&lt;/a&gt; (Kleene, 1951)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.wolframphysics.org/technical-introduction/&quot;&gt;A Class of Models with the Potential to Represent Fundamental Physics&lt;/a&gt; (Wolfram, 2020)&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Trust in Automation</title>
   <link href="breandan.net/2017/02/02/trust-in-automation/"/>
   <updated>2017-02-02T00:00:00+00:00</updated>
   <id>breandan.net/2017/02/02/trust-in-automation</id>
   <content type="html">&lt;p&gt;&lt;em&gt;In which I discuss the trouble with trusting machines to take our jobs, curate our news feeds, drive our school buses, teach our children, and lots of boring stuff too difficult to bother doing ourselves. Oh, and quotes. Lots of quotes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Houston, we have a problem. According to social media, a large fraction of our population will soon be unemployed. Not just unemployed, but &lt;a href=&quot;https://www.youtube.com/watch?v=7Pq-S557XQU&quot;&gt;unemployable&lt;/a&gt;. Thanks to rapid growth of automation and recent breakthroughs in machine learning, a majority of the world’s human labor will soon be economically obsolete. Too young to retire, and too old to retrain, there will be an enormous displacement of unskilled labor. This is not just idle speculation. Leading &lt;a href=&quot;https://twitter.com/AndrewYNg/status/815342695321174017&quot;&gt;scientists&lt;/a&gt; and &lt;a href=&quot;https://www.youtube.com/watch?v=72bHop6AIcc&quot;&gt;politicians&lt;/a&gt; have recognized the immediacy of this problem, and the importance of addressing it in our society.&lt;/p&gt;

&lt;figure&gt;
&lt;img src=&quot;https://i.imgur.com/XnD53bA.jpg&quot; /&gt;
&lt;figcaption&gt;&lt;p&gt;&lt;small&gt;Trains will move &lt;a href=&quot;https://news.ycombinator.com/item?id=13570074&quot;&gt;~332 million&lt;/a&gt; passengers during the &lt;a href=&quot;https://en.wikipedia.org/wiki/Chunyun&quot;&gt;largest migration&lt;/a&gt; in history.&lt;/small&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Automation does not just affect unskilled labor. Many jobs which require advanced degrees and years of experience are vulnerable, including a large number of &lt;a href=&quot;https://www.nature.com/nature/journal/vaop/ncurrent/full/nature21056.html&quot;&gt;doctors&lt;/a&gt;, &lt;a href=&quot;https://www.washingtonpost.com/news/innovations/wp/2016/05/16/meet-ross-the-newly-hired-legal-robot/&quot;&gt;lawyers&lt;/a&gt;, and &lt;a href=&quot;https://www.nytimes.com/2016/02/28/magazine/the-robots-are-coming-for-wall-street.html&quot;&gt;financial analysts&lt;/a&gt;. Each of these professions does work that is already being learned, automated, and optimized by machines. Even &lt;a href=&quot;https://papers.nips.cc/paper/6280-deepmath-deep-sequence-models-for-premise-selection.pdf&quot;&gt;mathematical research&lt;/a&gt; at the boundaries of our understanding can be &lt;a href=&quot;https://www.youtube.com/watch?v=qT8NyyRgLDQ&quot;&gt;automated&lt;/a&gt;. A growing number of mathematicians today use &lt;a href=&quot;https://en.wikipedia.org/wiki/Proof_assistant&quot;&gt;interactive proof assistants&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Automated_theorem_proving&quot;&gt;automated theorem provers&lt;/a&gt; to verify proofs, and even derive &lt;a href=&quot;https://en.wikipedia.org/wiki/Computer-assisted_proof#List_of_theorems_proved_with_the_help_of_computer_programs&quot;&gt;new truths&lt;/a&gt;. But if &lt;a href=&quot;https://en.wikipedia.org/wiki/Fake_news_websites_in_the_United_States&quot;&gt;current events&lt;/a&gt; are any indication, what is true and what is &lt;a href=&quot;http://www.fakenewschallenge.org/&quot;&gt;verifiable&lt;/a&gt; are entirely &lt;a href=&quot;https://en.wikipedia.org/wiki/Wikipedia:Verifiability,_not_truth&quot;&gt;different matters&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;And when your surpassing creations find the answers you asked for, you can’t understand their analysis and you can’t verify their answers. You have to take their word on faith—Or you use information theory to flatten it for you, to squash the tesseract into two dimensions and the Klein bottle into three, to simplify reality and pray to whatever Gods survived the millennium that your honorable twisting of the truth hasn’t ruptured any of its load-bearing pylons. You hire people like me; the crossbred progeny of profilers and proof assistants and information theorists…&lt;/p&gt;

  &lt;p&gt;In formal settings you’d call me Synthesist.&lt;/p&gt;

  &lt;p&gt;—Peter Watts, &lt;em&gt;&lt;a href=&quot;http://www.rifters.com/real/Blindsight.htm&quot;&gt;Blindsight&lt;/a&gt;&lt;/em&gt; (2006)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Peter Watts, in his breakout science-fiction novel, &lt;em&gt;Blindsight&lt;/em&gt;, imagines the occupation of “synthesists”, professional interpreters who translate between AI and humans. In a future where most scientific breakthroughs are discovered by AI, synthesists, “explain the incomprehensible to the indifferent.” Watts’ protagonist, Siri Keaton, is a spacefaring science officer who encounters a &lt;a href=&quot;https://en.wikipedia.org/wiki/Matrioshka_brain&quot;&gt;Matrioshka brain&lt;/a&gt; outside the solar system. Siri joins a reconnaissance mission to collect observations and verify the true nature of this strange object. But as Siri soon realizes, not all truths can be verified.&lt;/p&gt;

&lt;p&gt;Futurist sci-fi tends to fall into three broad categories. The optimists dream of a post-scarcity utopia where technology descends like manna from AI heaven, and we all travel into some &lt;a href=&quot;https://en.wikipedia.org/wiki/Technological_singularity&quot;&gt;digital promised land&lt;/a&gt;, &lt;em&gt;en masse&lt;/em&gt; so to speak. The pessimists argue that robot overlords and megacorporations vie for control of a dystopian future where humans are mostly expendable. And the synergists suggest a hybrid future, where humans and machines &lt;a href=&quot;https://www.penny-arcade.com/comic/story/automata&quot;&gt;co-exist&lt;/a&gt; in relative happiness, clinging to the hope we possess some vestigial importance to our metallic brethren. These thought experiments serve an important function as we grapple with the increasing effects of automation.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;People think—wrongly—that speculative fiction is about predicting the future… What speculative fiction is really good at is not the future but the present—taking an aspect of it that troubles or is dangerous, and extending and extrapolating that aspect into something that allows the people of that time to see what they are doing from a different angle and from a different place. It’s cautionary.&lt;/p&gt;

  &lt;p&gt;—Neil Gaiman, Introduction to &lt;em&gt;Fahrenheit 451&lt;/em&gt; (2013)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Science fiction, or speculative fiction as some prefer, has a long history of anticipating current events, and takes lessons from past and present alike. In one remarkable passage of &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Three-Body_Problem&quot;&gt;The Three Body Problem&lt;/a&gt;, a man called Von Neumann helps an ancient Chinese emperor build a computer to predict the movements of stars across the sky. With the emperor’s help, he trains millions of soldiers to form logic gates and memory buses, as they raise and lower flags and march around a vast plain. Wherever an error occurs, the emperor simply executes everyone involved and trains new replacements.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Qin Shi Huang lifted the sword to the sky, and shouted: “Computer Formation!” Four giant bronze cauldrons at the corners of the platform came to life simultaneously with roaring flames. A group of soldiers standing on the sloping side of the pyramid facing the phalanx chanted in unison: “Computer Formation!”&lt;/p&gt;

  &lt;p&gt;On the ground below, colors in the phalanx began to shift and move. Complicated and detailed circuit patterns appeared and gradually filled the entire formation. Ten minutes later, the army had made a thirty-six kilometer square computer motherboard…&lt;/p&gt;

  &lt;p&gt;“This is really interesting,” Qin Shi Huang said, pointing to the spectacular sight. “Each individual’s behavior is so simple, yet together, they can produce such a complex, great whole! Europeans criticize me for my tyrannical rule, claiming that I suppress creativity. But in reality, a large number of men yoked by severe discipline can also produce great wisdom when bound together as one.”&lt;/p&gt;

  &lt;p&gt;—Cixin Liu, &lt;em&gt;The Three Body Problem&lt;/em&gt; (2008)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Cixin Liu, a sci-fi writer&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; in China, imagines the development of a &lt;a href=&quot;https://en.wikipedia.org/wiki/Kardashev_scale#Type.C2.A0II_civilization_methods&quot;&gt;Kardashev Type-II&lt;/a&gt; civilization through allegories. In this example, it is not difficult to see millions of factory workers across China building the devices that will soon replace them. But China is not the only country facing pressure from machines. Many countries with large manufacturing sectors are hugely threatened by the destabilizing presence of automation. As soon as you teach a robot to sew sweaters more cheaply than paying a human, suddenly every sweater-factory can run around-the-clock, displacing thousands of workers overnight. While they’re at it, why bother shipping goods half way around the world?&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;As the cost of labor goes up and the cost of machinery goes down, at some point, it’ll be cheaper to use machines than people. With the increase in productivity, the GDP goes up, but so does unemployment. What do you do? … The best way is to reduce the time a certain portion of the population spends living, and then find ways to keep them busy.&lt;/p&gt;

  &lt;p&gt;—Jingfang Hao, &lt;em&gt;&lt;a href=&quot;https://uncannymagazine.com/article/folding-beijing-2/&quot;&gt;Folding Beijing&lt;/a&gt;&lt;/em&gt; (2014)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But job displacement, while a major challenge, is not the real problem facing our species. As history has shown, humanity has survived dozens of technological upheavals. In the &lt;a href=&quot;https://en.wikipedia.org/wiki/Neolithic_Revolution&quot;&gt;agricultural revolution&lt;/a&gt;, nomadic hunter-gatherers started breeding their prey, growing their forage, wheeling their food into little villages. The &lt;a href=&quot;https://en.wikipedia.org/wiki/Industrial_Revolution&quot;&gt;industrial revolution&lt;/a&gt; enlisted those farmers as factory workers and foremen in village-sized machines which consumed raw materials and produced smaller machines. Our ancestors saw sweeping social and economic change and still landed on the moon, despite their share of contemporary &lt;a href=&quot;https://en.wikipedia.org/wiki/Luddite&quot;&gt;detractors&lt;/a&gt;. &lt;em&gt;So what is the problem exactly?&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;For too many of us, it’s become safer to retreat into our own bubbles, whether in our neighborhoods or on college campuses, or places of worship, or especially our social media feeds, surrounded by people who look like us and share the same political outlook and never challenge our assumptions. The rise of naked partisanship, and increasing economic and regional stratification, the splintering of our media into a channel for every taste — all this makes this great sorting seem natural, even inevitable. And increasingly, we become so secure in our bubbles that we start accepting only information, whether it’s true or not, that fits our opinions, instead of basing our opinions on the evidence that is out there.&lt;/p&gt;

  &lt;p&gt;—Barack Obama, &lt;a href=&quot;https://www.vox.com/policy-and-politics/2017/1/10/14229878/full-transcript-president-barack-obama-farewell-speech&quot;&gt;&lt;em&gt;Farewell Address&lt;/em&gt;&lt;/a&gt; (2016)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At the dawn of the information age, we were convinced a newfangled technology called the “internet” would save us all from the uniformity of traditional media. The growth of the internet would give voices to the voiceless and choices to the choiceless. It was a new media frontier where consumers could create and curate content according to their own tastes and desires. No longer was television the sole source of your daily entertainment. Suddenly, you could read whatever you pleased and tweet whenever you sneezed. Isn’t it great? We can share new ideas and opinions with ease. Even your boss agrees, let’s retweet and reshare this with him overseas!&lt;/p&gt;

&lt;p&gt;The internet ushered a great awakening in this new age of information. Politicians and philosophers from ancient Rome could only dream of the freedom that instant access to unlimited information would one day bring to all humankind. What they could not foresee, is how the internet would unleash a new kind of tyranny, one that would eclipse any government’s own misuse in the name of security. Instant access does not guarantee self-improvement, only the promise of easy gratification. Unlimited information does not reveal deeper truth, only an endless road of distractions. Without education, the internet is a tyranny of the mind. Without purpose, it is a prison.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“A prison?”&lt;/em&gt; you might say. &lt;span class=&quot;mathquote&quot;&gt;\(\begin{align} \large\textit{Then you will know the truth,} \\ \large\textit{and the truth will set you free.}\\ \textsf{—John, 8:32 (100 A.D., est.)}\end{align}\)&lt;/span&gt;&lt;em&gt;“Why, it’s full of shiny gadgets, great entertainment, and people who agree with me. That doesn’t sound so bad!”&lt;/em&gt; Those shiny gadgets are &lt;a href=&quot;https://en.wikipedia.org/wiki/Operant_conditioning_chamber&quot;&gt;Skinner boxes&lt;/a&gt;. The entertainment? &lt;a href=&quot;https://en.wikipedia.org/wiki/Meme&quot;&gt;Viral memes&lt;/a&gt;, waiting to infect your mind and eat your attention span. Those other people? They’re just &lt;a href=&quot;https://en.wikipedia.org/wiki/Filter_bubble&quot;&gt;reflections&lt;/a&gt; who &lt;a href=&quot;https://en.wikipedia.org/wiki/Echo_chamber_(media)&quot;&gt;echo our opinions&lt;/a&gt;, inflate our egos, and &lt;a href=&quot;https://en.wikipedia.org/wiki/Confirmation_bias&quot;&gt;confirm our biases&lt;/a&gt;. The machines are very good at keeping us fat and happy. The best part is, we don’t even need to ask. They can model our habits, predict our behavior, anticipate our desires. They can practically read our minds.&lt;/p&gt;

&lt;p&gt;Not only can AI anticipate our desires, it can trigger our impulses. And if AI can stimulate our craving for sugar by activating a group of pixels in the correct sequence, why stop at predicting the &lt;a href=&quot;https://futures.tradingcharts.com/marketquotes/SB.html&quot;&gt;price of sugar&lt;/a&gt; when we can train it to influence future demand? As long as we’re entertaining wild conspiracies, what prevents AI from generating fake news to influence public opinion, or helping elect leaders who are friendly to automation? Whether self-acting or sponsored by old-fashioned capitalism, AI has the potential to metastasize.&lt;/p&gt;

&lt;p&gt;All this sounds rather alarmist, and perhaps it is. “Never trust anything you read on the internet,” the adults used to say. The problem is, the age of automation offers opportunity and oppression, education and entertainment, truth and fiction, all in equal measure. &lt;em&gt;The problem is, each of these things begins to look exactly like the other.&lt;/em&gt; When information is cheap to produce and free to consume, there is no incentive for it to be trustworthy. How should a color-blind chap in the Matrix know &lt;a href=&quot;https://en.wikipedia.org/wiki/Red_pill_and_blue_pill&quot;&gt;which pill&lt;/a&gt; to swallow? As it happens, when dealing with black boxes that can read your mind, the problem becomes surprisingly difficult.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“If our brains were simple enough for us to understand them, we’d be so simple that we couldn’t.”&lt;/p&gt;

  &lt;p&gt;—Ian Stewart, &lt;em&gt;The Collapse of Chaos&lt;/em&gt; (1994)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Researchers have poured millions of dollars into an area of machine learning known as &lt;a href=&quot;https://www.darpa.mil/program/explainable-artificial-intelligence&quot;&gt;explainable AI&lt;/a&gt;. So far as we can tell, it can’t be explained very well. Sure, we know how to build them using GPUs and terabytes of data. We know fancy words like backpropogation, convolutions, and hyperparameters. We know how to poke and prod them, try a zillion different parameters and sometimes they get more accurate. And we know that they work. For most people that is enough. But &lt;a href=&quot;https://arxiv.org/abs/1608.08225&quot;&gt;why does deep learning work so well&lt;/a&gt;? And why does one AI classify Amy as a threat to society and Sam as an upstanding citizen? Because her face looks kind of “criminal”?&lt;/p&gt;

&lt;p&gt;Automated criminality inference based on facial images is a &lt;a href=&quot;https://arxiv.org/abs/1611.04135&quot;&gt;real thing&lt;/a&gt;, and &lt;a href=&quot;https://www.propublica.org/article/machine-bias-risk-assessments-in-criminal-sentencing&quot;&gt;not just in China&lt;/a&gt;. Although many flaws exist in criminality prediction, the underlying assumptions are probably correct. With certain technologies, if it works, somebody will find a way to use it. But even if AIs could explain their logic, the problem is not the algorithms themselves. The problem is those who are willing to apply them, regardless of whether they are right, in either the technical or the ethical sense. If some algorithm is 35% confident you will default on a home loan, the bank isn’t going to debug their lending bot until it starts loosing money. The incentives are not aligned in your favor.&lt;/p&gt;

&lt;h1 id=&quot;believe-in-bias&quot;&gt;Believe in Bias&lt;/h1&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;If you think discrimination is bad today, just wait until the machines take over. They will discriminate based on the shade of your iris, the shape of your brow, the size of a tatoo, or any arbitrary collection of low-level traits whose presence triggers a subtle bias. Regardless whether such traits are truly predictive, it will matter not unless those who benefit have an incentive to fix the model. For most applications, AI just needs to be good enough to yield a positive &lt;a href=&quot;https://en.wikipedia.org/wiki/Marginal_utility&quot;&gt;marginal utility&lt;/a&gt;. Barring blatant discrimination on certain parameters like sex or skin color, most biases will fly under the radar.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Treating the world as software promotes fantasies of control. And the best kind of control is control without responsibility. Our unique position as authors of software used by millions gives us power, but we don’t accept that this should make us accountable. We’re programmers—who else is going to write the software that runs the world? To put it plainly, we are surprised that people seem to get mad at us for trying to help.&lt;/p&gt;

  &lt;p&gt;Fortunately we are smart people and have found a way out of this predicament. Instead of relying on algorithms, which we can be accused of manipulating for our benefit, we have turned to machine learning, an ingenious way of disclaiming responsibility for anything. &lt;strong&gt;Machine learning is like money laundering for bias.&lt;/strong&gt; It’s a clean, mathematical apparatus that gives the status quo the aura of logical inevitability.&lt;/p&gt;

  &lt;p&gt;—Maciej Ceglowski, &lt;em&gt;&lt;a href=&quot;https://idlewords.com/talks/sase_panel.htm&quot;&gt;On The Moral Economy of Tech&lt;/a&gt;&lt;/em&gt; (2016)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As &lt;a href=&quot;https://www.theatlantic.com/technology/archive/2016/04/the-underlying-bias-of-facial-recognition-systems/476991/&quot;&gt;experience&lt;/a&gt; has &lt;a href=&quot;https://www.theguardian.com/technology/2016/sep/08/artificial-intelligence-beauty-contest-doesnt-like-black-people&quot;&gt;shown&lt;/a&gt;, preventing bias when training an AI is difficult enough, never mind verifying its neutrality as a subject - if you know the AI exists begin with. But let’s say you have prior knowledge, motive, and a deep background in statistics. If there is an open API and the owner is not careful, you might be able to &lt;a href=&quot;https://www.usenix.org/system/files/conference/usenixsecurity16/sec16_paper_tramer.pdf&quot;&gt;steal the model&lt;/a&gt;, or test it yourself. That’s a lot of “if”s. The average end-user has no hope of ever verifying the fairness of an AI, and no motive to do so unless they are unfairly targeted. If you are unfairly targeted by an AI, the incentives are not in your favor.&lt;/p&gt;

&lt;p&gt;&lt;span class=&quot;mathquote&quot;&gt;\(\begin{align} \large\textit{Trust, but verify.}\\ \textsf{—}\href{https://en.wikipedia.org/wiki/Trust,_but_verify}{\textsf{Russian Proverb}}\end{align}\)&lt;/span&gt;Suppose you are unfairly targeted by an AI. The egregious cases will be tested prior to release to avoid the appearance of discrimination. If you suspect yourself to be the victim of unfair discrimination in an AI decision, it will be a tough case to prove. First you will need to prove the AI exists and had a significant influence in making the decision. Then you will need to establish a statistically significant number of samples where prior discrimination occurred. Good luck getting a subpoena for terabytes of anonymized &lt;a href=&quot;https://en.wikipedia.org/wiki/Personally_identifiable_information&quot;&gt;PII&lt;/a&gt;. Finally, you will need to justify why the decision was unfair and how it caused actual harm.&lt;/p&gt;

&lt;p&gt;The problem is not algorithms. The problem is the people training AI, and the people they are trained to imitate. The people training &lt;a href=&quot;https://en.wikipedia.org/wiki/Life-critical_system&quot;&gt;life-critical systems&lt;/a&gt; are &lt;a href=&quot;https://www.bloomberg.com/features/2015-george-hotz-self-driving-car/&quot;&gt;college dropouts&lt;/a&gt; and JavaScript developers with something called a “&lt;a href=&quot;https://www.udacity.com/nanodegree&quot;&gt;nanodegree&lt;/a&gt;” in self-driving cars. If you’re lucky, maybe some of them have an actual degree in statistics or something. Whether out of &lt;a href=&quot;https://en.wikipedia.org/wiki/Hanlon&apos;s_razor&quot;&gt;ignorance or malice&lt;/a&gt;, the developers of AI will make mistakes in our headlong pursuit of autonomy. There needs to be a minimum of regulatory oversight for AI that can take a human life. Or at the very least, a certifying body for data scientists, like medical boards and bar associations. In an industry that embraces agility, the bureaucratic cost of these options is highly unattractive.&lt;/p&gt;

&lt;p&gt;&lt;span class=&quot;mathquote&quot;&gt;\(\begin{align} \large\textit{Past performance does not} \\ \large\textit{guarantee future results.}\\ \textsf{—}\href{https://www.sec.gov/news/press/2003-122.htm}{\textsf{Mandatory SEC Disclosure}} \textsf{ (2003)}\end{align}\)&lt;/span&gt;By far the thornier problem, is the data used to train AI. Most AIs today are trained on human data. Imperfect data used to predict the outcome of a scenario no human has exactly seen before, produced by conditions we can only hope are similar during operation. We take great pains to ensure that the data used to train AI comes from the same distribution we expect to see in future operation. There is an entire &lt;a href=&quot;https://en.wikipedia.org/wiki/Data_science&quot;&gt;scientific discipline&lt;/a&gt; devoted to correctly sampling, cleaning, and preparing data for machine learning. However, data science departments have budgets limited by economics. And enough data to predict accurate results is seldom enough to prevent unwanted bias.&lt;/p&gt;

&lt;p&gt;In order to prevent unwanted bias, we should understand where it comes from. “Bias” in the statistical sense is not a bad word. Bias is just a property of an estimate. A &lt;a href=&quot;https://en.wikipedia.org/wiki/Bias_of_an_estimator&quot;&gt;biased estimator&lt;/a&gt; is a function which tends to over- or under-estimate the value of a parameter. You can have a biased estimator that is still accurate. You can have a biased estimator that is inaccurate. You can have a biased estimator that is precise. And you can have one that is imprecise. Though you are seldom lucky enough to have an estimator that is perfectly unbiased and precise. A frequent compromise in machine learning is trading &lt;a href=&quot;https://en.wikipedia.org/wiki/Bias%E2%80%93variance_tradeoff&quot;&gt;variance for bias&lt;/a&gt;. Completely eliminating bias often requires sacrificing precision, and high precision usually comes at the price of additional bias.&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;center&gt;
    &lt;div class=&quot;image-content&quot;&gt;
        &lt;table class=&quot;snug&quot;&gt;
            &lt;tbody&gt;
            &lt;tr&gt;
                &lt;th&gt;&lt;/th&gt;
                &lt;td&gt;
                    &lt;center&gt;&lt;b&gt;Low Variance&lt;/b&gt;&lt;br /&gt;
                    (High Precision)&lt;/center&gt;
                &lt;/td&gt;
                &lt;td&gt;
                    &lt;center&gt;&lt;b&gt;High Variance&lt;/b&gt;&lt;br /&gt;
                    (Low Precision)&lt;/center&gt;
                &lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td class=&quot;r90&quot;&gt;
                    &lt;center&gt;&lt;b&gt;Low Bias&lt;/b&gt;&lt;/center&gt;
                &lt;/td&gt;
                &lt;td&gt;&lt;center&gt;
                    &lt;div id=&quot;bullsEyeLBLV&quot;&gt;&lt;svg width=&quot;200&quot; height=&quot;200&quot; style=&quot;border: none;&quot;&gt;&lt;circle class=&quot;ring&quot; cx=&quot;100&quot; cy=&quot;100&quot; r=&quot;90.9090909090909&quot; style=&quot;fill: white;&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;ring&quot; cx=&quot;100&quot; cy=&quot;100&quot; r=&quot;62.5&quot; style=&quot;fill: rgb(118, 179, 216);&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;ring&quot; cx=&quot;100&quot; cy=&quot;100&quot; r=&quot;36.36363636363637&quot; style=&quot;fill: white;&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;ring&quot; cx=&quot;100&quot; cy=&quot;100&quot; r=&quot;13.333333333333334&quot; style=&quot;fill: rgb(193, 47, 62);&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;95.2417299219265&quot; cy=&quot;98.78231506348611&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;94.98877477792978&quot; cy=&quot;98.35369950854978&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;98.64499086445454&quot; cy=&quot;90.1611985381718&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;98.29842135491629&quot; cy=&quot;103.46102989370513&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;95.79393665077546&quot; cy=&quot;100.68784532768193&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;99.98795100308158&quot; cy=&quot;101.81130596018545&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;89.34113757239132&quot; cy=&quot;96.3757227502656&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;92.93663382940163&quot; cy=&quot;93.85728904385391&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;91.27400877365645&quot; cy=&quot;92.74432495644449&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;98.35171143651966&quot; cy=&quot;90.25639751501993&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;89.84479267773501&quot; cy=&quot;89.80271518867866&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;102.92811906669978&quot; cy=&quot;102.31429122988574&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;98.43292822053172&quot; cy=&quot;94.33502755999424&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;100.03977392090455&quot; cy=&quot;88.32650985799843&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;90.45638062240717&quot; cy=&quot;91.38063914598084&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;91.814500886036&quot; cy=&quot;105.83526025811605&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;93.48689316677351&quot; cy=&quot;94.63423346645308&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;93.2603587976381&quot; cy=&quot;98.98875335330786&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;96.46568926721694&quot; cy=&quot;92.17361145704697&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;91.90571922505733&quot; cy=&quot;88.55473443715668&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;103.20972223139&quot; cy=&quot;96.86760959426755&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;90.45135687581899&quot; cy=&quot;102.46241789283684&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;96.83775784414765&quot; cy=&quot;109.14141342737429&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;88.47009267490499&quot; cy=&quot;102.33783592020343&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;103.08969765418682&quot; cy=&quot;99.25599334201341&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;/svg&gt;&lt;/div&gt;&lt;/center&gt;
                    &lt;center&gt;&lt;small&gt;&lt;i&gt;Most Accurate&lt;/i&gt;&lt;/small&gt;&lt;/center&gt;
                &lt;/td&gt;
                &lt;td&gt;&lt;center&gt;
                    &lt;div id=&quot;bullsEyeLBHV&quot;&gt;&lt;svg width=&quot;200&quot; height=&quot;200&quot; style=&quot;border: none;&quot;&gt;&lt;circle class=&quot;ring&quot; cx=&quot;100&quot; cy=&quot;100&quot; r=&quot;90.9090909090909&quot; style=&quot;fill: white;&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;ring&quot; cx=&quot;100&quot; cy=&quot;100&quot; r=&quot;62.5&quot; style=&quot;fill: rgb(118, 179, 216);&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;ring&quot; cx=&quot;100&quot; cy=&quot;100&quot; r=&quot;36.36363636363637&quot; style=&quot;fill: white;&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;ring&quot; cx=&quot;100&quot; cy=&quot;100&quot; r=&quot;13.333333333333334&quot; style=&quot;fill: rgb(193, 47, 62);&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;135.30208525468566&quot; cy=&quot;109.53667975411805&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;128.43144410223016&quot; cy=&quot;73.55338417474053&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;62.46329544014869&quot; cy=&quot;115.09033226489368&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;126.27343247249648&quot; cy=&quot;66.14548779266283&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;87.5311440807998&quot; cy=&quot;96.79804569434428&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;89.86553587619488&quot; cy=&quot;73.31114567408036&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;72.14224642068129&quot; cy=&quot;71.56278538776868&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;133.67943947732815&quot; cy=&quot;99.4197165637036&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;95.39079143636448&quot; cy=&quot;118.7690125167322&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;94.97114920044513&quot; cy=&quot;89.90155532250407&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;97.76397547830885&quot; cy=&quot;104.44717591002323&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;89.30844911697717&quot; cy=&quot;85.24513430882038&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;84.9656556483016&quot; cy=&quot;110.46435847056802&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;94.47025121828862&quot; cy=&quot;111.22511714783076&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;81.19000260405745&quot; cy=&quot;87.45496868419164&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;52.31412324140461&quot; cy=&quot;109.70597207613788&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;84.07493934147824&quot; cy=&quot;121.38043888867571&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;79.96730411760538&quot; cy=&quot;96.32433545651551&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;97.5698900562818&quot; cy=&quot;104.32403135668825&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;64.83727832847151&quot; cy=&quot;102.24003307409187&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;96.43564661227427&quot; cy=&quot;111.54952202719106&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;113.09578479104827&quot; cy=&quot;118.67825786463287&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;103.04118268265579&quot; cy=&quot;107.66971927290987&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;76.27875910415312&quot; cy=&quot;128.31617509558063&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;129.12754678814048&quot; cy=&quot;95.5293181876095&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;/svg&gt;&lt;/div&gt;&lt;/center&gt;
                    &lt;center&gt;&lt;small&gt; &lt;/small&gt;&lt;/center&gt;
                &lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td class=&quot;r90&quot;&gt;
                    &lt;center&gt;&lt;b&gt;High Bias&lt;/b&gt;&lt;/center&gt;
                &lt;/td&gt;
                &lt;td&gt;&lt;center&gt;
                    &lt;div id=&quot;bullsEyeHBLV&quot;&gt;&lt;svg width=&quot;200&quot; height=&quot;200&quot; style=&quot;border: none;&quot;&gt;&lt;circle class=&quot;ring&quot; cx=&quot;100&quot; cy=&quot;100&quot; r=&quot;90.9090909090909&quot; style=&quot;fill: white;&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;ring&quot; cx=&quot;100&quot; cy=&quot;100&quot; r=&quot;62.5&quot; style=&quot;fill: rgb(118, 179, 216);&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;ring&quot; cx=&quot;100&quot; cy=&quot;100&quot; r=&quot;36.36363636363637&quot; style=&quot;fill: white;&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;ring&quot; cx=&quot;100&quot; cy=&quot;100&quot; r=&quot;13.333333333333334&quot; style=&quot;fill: rgb(193, 47, 62);&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;93.27374996049726&quot; cy=&quot;42.328637258595556&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;105.52581398889991&quot; cy=&quot;44.93556686811315&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;95.26101246647794&quot; cy=&quot;46.7755302240622&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;112.05060873387474&quot; cy=&quot;52.86933183374843&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;110.17742629325286&quot; cy=&quot;57.67330743618805&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;102.62633835599787&quot; cy=&quot;47.63329341720682&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;104.97396150323235&quot; cy=&quot;53.86880949845978&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;103.76256282114713&quot; cy=&quot;48.3116835441338&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;97.84406081280112&quot; cy=&quot;48.05373982750756&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;105.47413674536088&quot; cy=&quot;60.8819662990806&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;101.32433258243718&quot; cy=&quot;50.42653499700785&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;107.75895816267607&quot; cy=&quot;53.5123837318865&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;102.34151233023265&quot; cy=&quot;43.22134477028904&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;102.74836927714325&quot; cy=&quot;48.99085752653546&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;103.5514955929248&quot; cy=&quot;50.700765047971295&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;99.66489163788832&quot; cy=&quot;52.960882058099266&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;104.03334679960989&quot; cy=&quot;50.56365067938392&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;112.40294162147084&quot; cy=&quot;51.05603578517508&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;103.77185736249525&quot; cy=&quot;48.69041724555987&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;105.75923213844915&quot; cy=&quot;52.16305294199713&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;100.02620538056256&quot; cy=&quot;45.76240834088125&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;92.6900668670068&quot; cy=&quot;49.1548990106344&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;102.52276709795272&quot; cy=&quot;54.66889873214721&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;92.63240239912123&quot; cy=&quot;54.816287121818064&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;93.67433387840616&quot; cy=&quot;44.1308081872826&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;/svg&gt;&lt;/div&gt;&lt;/center&gt;
                    &lt;center&gt;&lt;small&gt; &lt;/small&gt;&lt;/center&gt;
                &lt;/td&gt;
                &lt;td&gt;&lt;center&gt;
                    &lt;div id=&quot;bullsEyeHBHV&quot;&gt;&lt;svg width=&quot;200&quot; height=&quot;200&quot; style=&quot;border: none;&quot;&gt;&lt;circle class=&quot;ring&quot; cx=&quot;100&quot; cy=&quot;100&quot; r=&quot;90.9090909090909&quot; style=&quot;fill: white;&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;ring&quot; cx=&quot;100&quot; cy=&quot;100&quot; r=&quot;62.5&quot; style=&quot;fill: rgb(118, 179, 216);&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;ring&quot; cx=&quot;100&quot; cy=&quot;100&quot; r=&quot;36.36363636363637&quot; style=&quot;fill: white;&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;ring&quot; cx=&quot;100&quot; cy=&quot;100&quot; r=&quot;13.333333333333334&quot; style=&quot;fill: rgb(193, 47, 62);&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;103.71226190486529&quot; cy=&quot;35.245951954634805&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;85.66758527040301&quot; cy=&quot;67.2447331281883&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;62.28568550397415&quot; cy=&quot;32.140931024292215&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;44.453050499204494&quot; cy=&quot;27.594136705300244&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;65.5267486415562&quot; cy=&quot;34.97572973546029&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;52.31696098385054&quot; cy=&quot;63.901284157820186&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;48.16744830325244&quot; cy=&quot;18.83190221128146&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;74.76574746979051&quot; cy=&quot;45.429332524802895&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;93.43125456438462&quot; cy=&quot;10.626913149263643&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;68.5906869780192&quot; cy=&quot;46.07543950204163&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;76.78805778650607&quot; cy=&quot;37.09650785588681&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;72.76655176927713&quot; cy=&quot;50.971128326292146&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;42.724353763919886&quot; cy=&quot;61.927273912222816&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;112.20625419743854&quot; cy=&quot;39.15213297199204&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;88.36900320964696&quot; cy=&quot;38.854779509806455&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;63.66053914630819&quot; cy=&quot;56.46641986123598&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;68.96191500872605&quot; cy=&quot;43.16404842444755&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;35.635519046608465&quot; cy=&quot;28.74648178852344&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;68.60182810836173&quot; cy=&quot;59.740609767146466&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;95.5153403974868&quot; cy=&quot;25.547080430710736&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;46.37075852226722&quot; cy=&quot;19.62606830684345&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;89.9950666768221&quot; cy=&quot;50.71556277512999&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;64.45958584171213&quot; cy=&quot;42.52949470919935&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;95.57718864645554&quot; cy=&quot;4.197361489016814&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;circle class=&quot;arrow&quot; cx=&quot;70.63354751617322&quot; cy=&quot;32.127872854044625&quot; r=&quot;2.5&quot;&gt;&lt;/circle&gt;&lt;/svg&gt;&lt;/div&gt;&lt;/center&gt;
                    &lt;center&gt;&lt;small&gt;&lt;i&gt;Least Accurate&lt;/i&gt;&lt;/small&gt;&lt;/center&gt;
                &lt;/td&gt;
            &lt;/tr&gt;
            &lt;/tbody&gt;&lt;/table&gt;
    &lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Suppose that &lt;a href=&quot;https://www.bloomberg.com/news/articles/2017-01-18/oracle-sued-by-u-s-over-alleged-discriminatory-pay-hiring&quot;&gt;a company&lt;/a&gt; has a slight bias towards hiring Asians for technical roles. &lt;strong&gt;The following words in this paragraph are completely hypothetical&lt;/strong&gt;, although there is evidence to suggest Asians are &lt;a href=&quot;https://www.pewresearch.org/fact-tank/2016/07/01/racial-gender-wage-gaps-persist-in-u-s-despite-some-progress/&quot;&gt;disproportionately well-compensated&lt;/a&gt; in some professions. Asians are smart. Asians work hard. Smart companies want to hire smart, hard working people to build smarter products, and will pay them commensurately. Whether or not Asian bias exists, the results of hiring for diversity has higher variance, on a number of key performance metrics. Since hiring more Asians, productivity and profits have soared. As a business owner, what would you do?&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;
&amp;lt;?xml version=”1.0” encoding=”UTF-8” standalone=”no”?&amp;gt;&lt;/p&gt;
&lt;svg xmlns:dc=&quot;https://purl.org/dc/elements/1.1/&quot; xmlns:cc=&quot;https://creativecommons.org/ns#&quot; xmlns:rdf=&quot;https://www.w3.org/1999/02/22-rdf-syntax-ns#&quot; xmlns:svg=&quot;https://www.w3.org/2000/svg&quot; xmlns=&quot;https://www.w3.org/2000/svg&quot; xmlns:xlink=&quot;https://www.w3.org/1999/xlink&quot; xmlns:sodipodi=&quot;http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd&quot; xmlns:inkscape=&quot;https://www.inkscape.org/namespaces/inkscape&quot; version=&quot;1.0&quot; id=&quot;svg2&quot; sodipodi:version=&quot;0.32&quot; inkscape:version=&quot;0.48.5 r10040&quot; width=&quot;720&quot; height=&quot;460&quot; sodipodi:docname=&quot;Normal_Distribution_PDF.svg&quot; inkscape:output_extension=&quot;org.inkscape.output.svg.inkscape&quot;&gt;
        &lt;sodipodi:namedview inkscape:window-height=&quot;1392&quot; inkscape:window-width=&quot;2556&quot; inkscape:pageshadow=&quot;2&quot; inkscape:pageopacity=&quot;0.0&quot; guidetolerance=&quot;10.0&quot; gridtolerance=&quot;10000&quot; objecttolerance=&quot;10.0&quot; borderopacity=&quot;1.0&quot; bordercolor=&quot;#666666&quot; pagecolor=&quot;#ffffff&quot; id=&quot;base&quot; inkscape:zoom=&quot;2&quot; inkscape:cx=&quot;365.55683&quot; inkscape:cy=&quot;255.92719&quot; inkscape:window-x=&quot;0&quot; inkscape:window-y=&quot;46&quot; inkscape:current-layer=&quot;layer1&quot; width=&quot;720px&quot; height=&quot;460px&quot; showgrid=&quot;false&quot; inkscape:grid-points=&quot;true&quot; showguides=&quot;true&quot; inkscape:guide-bbox=&quot;true&quot; inkscape:object-nodes=&quot;true&quot; fit-margin-top=&quot;5&quot; fit-margin-left=&quot;5&quot; fit-margin-right=&quot;5&quot; fit-margin-bottom=&quot;5&quot; inkscape:window-maximized=&quot;0&quot;&gt;
            &lt;inkscape:grid id=&quot;GridFromPre046Settings&quot; type=&quot;xygrid&quot; originx=&quot;0px&quot; originy=&quot;70px&quot; spacingx=&quot;5px&quot; spacingy=&quot;5px&quot; color=&quot;#0000ff&quot; empcolor=&quot;#0000ff&quot; opacity=&quot;0.2&quot; empopacity=&quot;0.4&quot; empspacing=&quot;5&quot; visible=&quot;true&quot; enabled=&quot;true&quot; snapvisiblegridlinesonly=&quot;true&quot; /&gt;
        &lt;/sodipodi:namedview&gt;
        &lt;metadata id=&quot;metadata2112&quot;&gt;
            &lt;rdf:RDF&gt;
                &lt;cc:Work rdf:about=&quot;&quot;&gt;
                    &lt;dc:format&gt;image/svg+xml&lt;/dc:format&gt;
                    &lt;dc:type rdf:resource=&quot;https://purl.org/dc/dcmitype/StillImage&quot; /&gt;
                &lt;/cc:Work&gt;
            &lt;/rdf:RDF&gt;
        &lt;/metadata&gt;
        &lt;defs id=&quot;defs2102&quot;&gt;
            &lt;inkscape:perspective sodipodi:type=&quot;inkscape:persp3d&quot; inkscape:vp_x=&quot;0 : 230 : 1&quot; inkscape:vp_y=&quot;0 : 1000 : 0&quot; inkscape:vp_z=&quot;720 : 230 : 1&quot; inkscape:persp3d-origin=&quot;360 : 153.33333 : 1&quot; id=&quot;perspective289&quot; /&gt;
            &lt;clipPath id=&quot;cp3&quot;&gt;
                &lt;polygon id=&quot;polygon1797&quot; points=&quot;73,190 73,203.563 95,203.563 95,190 73,190 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;clipPath id=&quot;cp5&quot;&gt;
                &lt;polygon id=&quot;polygon1821&quot; points=&quot;73,190 73,203.563 95,203.563 95,190 73,190 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;clipPath id=&quot;cp7&quot;&gt;
                &lt;polygon id=&quot;polygon1845&quot; points=&quot;73,190 73,203.563 88,203.563 88,190 73,190 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;clipPath id=&quot;cp9&quot;&gt;
                &lt;polygon id=&quot;polygon1867&quot; points=&quot;73,190 73,203.563 88,203.563 88,190 73,190 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;clipPath id=&quot;cp10&quot;&gt;
                &lt;polygon id=&quot;polygon1874&quot; points=&quot;74,13 74,364 434,364 434,13 74,13 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;clipPath id=&quot;cp11&quot;&gt;
                &lt;polygon id=&quot;polygon1889&quot; points=&quot;73,190 73,203.563 88,203.563 88,190 73,190 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;clipPath id=&quot;cp13&quot;&gt;
                &lt;polygon id=&quot;polygon1907&quot; points=&quot;74,190 74,204 95,204 95,190 74,190 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;clipPath id=&quot;cp15&quot;&gt;
                &lt;polygon id=&quot;polygon1931&quot; points=&quot;74,190 74,204 95,204 95,190 74,190 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;clipPath id=&quot;cp17&quot;&gt;
                &lt;polygon id=&quot;polygon1955&quot; points=&quot;73,190 73,204 88,204 88,190 73,190 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;clipPath id=&quot;cp19&quot;&gt;
                &lt;polygon id=&quot;polygon1977&quot; points=&quot;73,190 73,204 88,204 88,190 73,190 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;clipPath id=&quot;cp21&quot;&gt;
                &lt;polygon id=&quot;polygon1999&quot; points=&quot;73,190 73,204 88,204 88,190 73,190 &quot; /&gt;
            &lt;/clipPath&gt;
        &lt;/defs&gt;
        &lt;g clip-path=&quot;url(#cp3)&quot; id=&quot;g8871&quot; transform=&quot;matrix(1.364137,0,0,1.406645,-19.376016,57.579514)&quot;&gt;
            &lt;clipPath id=&quot;clipPath9201&quot;&gt;
                &lt;polygon id=&quot;polygon8874&quot; points=&quot;73,126 73,140 87,140 87,126 73,126 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;text font-size=&quot;10px&quot; style=&quot;font-size:10px;fill:#000000;font-family:SVGTimes&quot; id=&quot;text8876&quot; y=&quot;137&quot; x=&quot;74&quot;&gt;-
            &lt;/text&gt;
            &lt;text font-size=&quot;10px&quot; style=&quot;font-size:10px;fill:#000000;font-family:Times New Roman&quot; id=&quot;text8878&quot; y=&quot;137&quot; x=&quot;80.5&quot;&gt;3
            &lt;/text&gt;
        &lt;/g&gt;
        &lt;g clip-path=&quot;url(#cp5)&quot; id=&quot;g8895&quot; transform=&quot;matrix(1.364137,0,0,1.406645,58.936361,57.579514)&quot;&gt;
            &lt;clipPath id=&quot;clipPath9216&quot;&gt;
                &lt;polygon id=&quot;polygon8898&quot; points=&quot;73,126 73,140 87,140 87,126 73,126 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;text font-size=&quot;10px&quot; style=&quot;font-size:10px;fill:#000000;font-family:SVGTimes&quot; id=&quot;text8900&quot; y=&quot;137&quot; x=&quot;74&quot;&gt;-
            &lt;/text&gt;
            &lt;text font-size=&quot;10px&quot; style=&quot;font-size:10px;fill:#000000;font-family:Times New Roman&quot; id=&quot;text8902&quot; y=&quot;137&quot; x=&quot;80.5&quot;&gt;2
            &lt;/text&gt;
        &lt;/g&gt;
        &lt;g clip-path=&quot;url(#cp7)&quot; id=&quot;g8919&quot; transform=&quot;matrix(1.364137,0,0,1.406645,137.24874,57.579514)&quot;&gt;
            &lt;clipPath id=&quot;clipPath9231&quot;&gt;
                &lt;polygon id=&quot;polygon8922&quot; points=&quot;73,126 73,140 87,140 87,126 73,126 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;text font-size=&quot;10px&quot; style=&quot;font-size:10px;fill:#000000;font-family:SVGTimes&quot; id=&quot;text8924&quot; y=&quot;137&quot; x=&quot;74&quot;&gt;-
            &lt;/text&gt;
            &lt;text font-size=&quot;10px&quot; style=&quot;font-size:10px;fill:#000000;font-family:Times New Roman&quot; id=&quot;text8926&quot; y=&quot;137&quot; x=&quot;80.5&quot;&gt;1
            &lt;/text&gt;
        &lt;/g&gt;
        &lt;g clip-path=&quot;url(#cp9)&quot; transform=&quot;matrix(1.364137,0,0,1.406645,-21.116655,57.614261)&quot; id=&quot;g8943&quot;&gt;
            &lt;clipPath id=&quot;clipPath9246&quot;&gt;
                &lt;polygon id=&quot;polygon8946&quot; points=&quot;74,13 74,236 434,236 434,13 74,13 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline8948&quot; points=&quot;265,124 265,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline8950&quot; points=&quot;276.438,124 276.438,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline8952&quot; points=&quot;287.938,124 287.938,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline8954&quot; points=&quot;299.438,124 299.438,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline8956&quot; points=&quot;310.938,124 310.938,120 &quot; /&gt;
        &lt;/g&gt;
        &lt;g clip-path=&quot;url(#cp10)&quot; id=&quot;g8958&quot; transform=&quot;matrix(1.364137,0,0,1.406645,298.64797,57.579514)&quot;&gt;
            &lt;clipPath id=&quot;clipPath9255&quot;&gt;
                &lt;polygon id=&quot;polygon8961&quot; points=&quot;73,126 73,140 80,140 80,126 73,126 &quot; /&gt;
            &lt;/clipPath&gt;
        &lt;/g&gt;
        &lt;g clip-path=&quot;url(#cp11)&quot; transform=&quot;matrix(1.364137,0,0,1.406645,-21.116655,57.614261)&quot; id=&quot;g8965&quot;&gt;
            &lt;clipPath id=&quot;clipPath9260&quot;&gt;
                &lt;polygon id=&quot;polygon8968&quot; points=&quot;74,13 74,236 434,236 434,13 74,13 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline8970&quot; points=&quot;322.375,124 322.375,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline8972&quot; points=&quot;333.875,124 333.875,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline8974&quot; points=&quot;345.375,124 345.375,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline8976&quot; points=&quot;356.813,124 356.813,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline8978&quot; points=&quot;368.313,124 368.313,120 &quot; /&gt;
        &lt;/g&gt;
        &lt;g clip-path=&quot;url(#cp13)&quot; transform=&quot;matrix(1.364137,0,0,1.406645,-21.116655,57.614261)&quot; id=&quot;g8987&quot;&gt;
            &lt;clipPath id=&quot;clipPath9274&quot;&gt;
                &lt;polygon id=&quot;polygon8990&quot; points=&quot;74,13 74,236 434,236 434,13 74,13 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline8992&quot; points=&quot;379.813,124 379.813,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline8994&quot; points=&quot;391.25,124 391.25,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline8996&quot; points=&quot;402.75,124 402.75,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline8998&quot; points=&quot;414.25,124 414.25,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline9000&quot; points=&quot;425.75,124 425.75,120 &quot; /&gt;
        &lt;/g&gt;
        &lt;g clip-path=&quot;url(#cp17)&quot; transform=&quot;matrix(1.364137,0,0,1.406645,-21.116655,57.614261)&quot; id=&quot;g9029&quot;&gt;
            &lt;clipPath id=&quot;clipPath9301&quot;&gt;
                &lt;polygon id=&quot;polygon9032&quot; points=&quot;74,13 74,236 434,236 434,13 74,13 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline9034&quot; points=&quot;253.5,219.5 255.875,219.5 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline9036&quot; points=&quot;253.5,212.688 255.875,212.688 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline9038&quot; points=&quot;253.5,205.875 255.875,205.875 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline9040&quot; points=&quot;253.5,199 255.875,199 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline9042&quot; points=&quot;253.5,192.188 257.5,192.188 &quot; /&gt;
        &lt;/g&gt;
        &lt;g clip-path=&quot;url(#cp19)&quot; transform=&quot;matrix(1.364137,0,0,1.406645,-21.116655,57.614261)&quot; id=&quot;g9053&quot;&gt;
            &lt;clipPath id=&quot;clipPath9316&quot;&gt;
                &lt;polygon id=&quot;polygon9056&quot; points=&quot;74,13 74,236 434,236 434,13 74,13 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline9058&quot; points=&quot;253.5,185.375 255.875,185.375 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline9060&quot; points=&quot;253.5,178.563 255.875,178.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline9062&quot; points=&quot;253.5,171.75 255.875,171.75 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline9064&quot; points=&quot;253.5,164.938 255.875,164.938 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline9066&quot; points=&quot;253.5,158.063 257.5,158.063 &quot; /&gt;
        &lt;/g&gt;
        &lt;g clip-path=&quot;url(#cp21)&quot; transform=&quot;matrix(1.364137,0,0,1.406645,-21.116655,57.614261)&quot; id=&quot;g9077&quot;&gt;
            &lt;clipPath id=&quot;clipPath9331&quot;&gt;
                &lt;polygon id=&quot;polygon9080&quot; points=&quot;74,13 74,236 434,236 434,13 74,13 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline9082&quot; points=&quot;253.5,151.25 255.875,151.25 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline9084&quot; points=&quot;253.5,144.438 255.875,144.438 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline9086&quot; points=&quot;253.5,137.625 255.875,137.625 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline9088&quot; points=&quot;253.5,130.813 255.875,130.813 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.13535678px;stroke-opacity:1&quot; id=&quot;polyline9090&quot; points=&quot;253.5,124 257.5,124 &quot; /&gt;
        &lt;/g&gt;
        &lt;g clip-path=&quot;url(#cp3)&quot; transform=&quot;translate(714,63)&quot; id=&quot;g10133&quot;&gt;
            &lt;clipPath id=&quot;clipPath10481&quot;&gt;
                &lt;polygon id=&quot;polygon10136&quot; points=&quot;74,13 74,236 434,236 434,13 74,13 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.1875px;stroke-opacity:1&quot; id=&quot;polyline10138&quot; points=&quot;83.9375,124 83.9375,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.1875px;stroke-opacity:1&quot; id=&quot;polyline10140&quot; points=&quot;94.5,124 94.5,120 &quot; /&gt;
        &lt;/g&gt;
        &lt;g clip-path=&quot;url(#cp5)&quot; transform=&quot;translate(714,63)&quot; id=&quot;g10151&quot;&gt;
            &lt;clipPath id=&quot;clipPath10493&quot;&gt;
                &lt;polygon id=&quot;polygon10154&quot; points=&quot;74,13 74,236 434,236 434,13 74,13 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.1875px;stroke-opacity:1&quot; id=&quot;polyline10156&quot; points=&quot;105.125,124 105.125,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.1875px;stroke-opacity:1&quot; id=&quot;polyline10158&quot; points=&quot;115.75,124 115.75,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.1875px;stroke-opacity:1&quot; id=&quot;polyline10160&quot; points=&quot;126.313,124 126.313,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.1875px;stroke-opacity:1&quot; id=&quot;polyline10162&quot; points=&quot;136.938,124 136.938,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.1875px;stroke-opacity:1&quot; id=&quot;polyline10164&quot; points=&quot;147.5,124 147.5,120 &quot; /&gt;
        &lt;/g&gt;
        &lt;g clip-path=&quot;url(#cp7)&quot; transform=&quot;translate(714,63)&quot; id=&quot;g10175&quot;&gt;
            &lt;clipPath id=&quot;clipPath10508&quot;&gt;
                &lt;polygon id=&quot;polygon10178&quot; points=&quot;74,13 74,236 434,236 434,13 74,13 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.1875px;stroke-opacity:1&quot; id=&quot;polyline10180&quot; points=&quot;158.125,124 158.125,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.1875px;stroke-opacity:1&quot; id=&quot;polyline10182&quot; points=&quot;168.688,124 168.688,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.1875px;stroke-opacity:1&quot; id=&quot;polyline10184&quot; points=&quot;179.313,124 179.313,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.1875px;stroke-opacity:1&quot; id=&quot;polyline10186&quot; points=&quot;189.938,124 189.938,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.1875px;stroke-opacity:1&quot; id=&quot;polyline10188&quot; points=&quot;200.5,124 200.5,120 &quot; /&gt;
        &lt;/g&gt;
        &lt;g clip-path=&quot;url(#cp9)&quot; transform=&quot;translate(714,63)&quot; id=&quot;g10199&quot;&gt;
            &lt;clipPath id=&quot;clipPath10523&quot;&gt;
                &lt;polygon id=&quot;polygon10202&quot; points=&quot;74,13 74,236 434,236 434,13 74,13 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.1875px;stroke-opacity:1&quot; id=&quot;polyline10204&quot; points=&quot;211.125,124 211.125,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.1875px;stroke-opacity:1&quot; id=&quot;polyline10206&quot; points=&quot;221.688,124 221.688,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.1875px;stroke-opacity:1&quot; id=&quot;polyline10208&quot; points=&quot;232.313,124 232.313,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.1875px;stroke-opacity:1&quot; id=&quot;polyline10210&quot; points=&quot;242.875,124 242.875,121.563 &quot; /&gt;
            &lt;polyline style=&quot;fill:none;stroke:#000000;stroke-width:0.1875px;stroke-opacity:1&quot; id=&quot;polyline10212&quot; points=&quot;253.5,124 253.5,120 &quot; /&gt;
        &lt;/g&gt;
        &lt;g clip-path=&quot;url(#cp11)&quot; id=&quot;g10229&quot; transform=&quot;translate(943.992,62.9753)&quot;&gt;
            &lt;clipPath id=&quot;clipPath10541&quot;&gt;
                &lt;polygon id=&quot;polygon10232&quot; points=&quot;73,126 73,140 80,140 80,126 73,126 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;text font-size=&quot;10px&quot; style=&quot;font-size:10px;fill:#000000;font-family:Times New Roman&quot; id=&quot;text10234&quot; y=&quot;137&quot; x=&quot;74&quot;&gt;1
            &lt;/text&gt;
        &lt;/g&gt;
        &lt;g clip-path=&quot;url(#cp13)&quot; id=&quot;g10251&quot; transform=&quot;translate(996.984,62.9753)&quot;&gt;
            &lt;clipPath id=&quot;clipPath10555&quot;&gt;
                &lt;polygon id=&quot;polygon10254&quot; points=&quot;73,126 73,140 80,140 80,126 73,126 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;text font-size=&quot;10px&quot; style=&quot;font-size:10px;fill:#000000;font-family:Times New Roman&quot; id=&quot;text10256&quot; y=&quot;137&quot; x=&quot;74&quot;&gt;2
            &lt;/text&gt;
        &lt;/g&gt;
        &lt;g clip-path=&quot;url(#cp15)&quot; id=&quot;g10273&quot; transform=&quot;translate(1049.976,62.9753)&quot;&gt;
            &lt;clipPath id=&quot;clipPath10569&quot;&gt;
                &lt;polygon id=&quot;polygon10276&quot; points=&quot;73,126 73,140 80,140 80,126 73,126 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;text font-size=&quot;10px&quot; style=&quot;font-size:10px;fill:#000000;font-family:Times New Roman&quot; id=&quot;text10278&quot; y=&quot;137&quot; x=&quot;74&quot;&gt;3
            &lt;/text&gt;
        &lt;/g&gt;
        &lt;g clip-path=&quot;url(#cp17)&quot; id=&quot;g10297&quot; transform=&quot;translate(878.5,142.67554)&quot;&gt;
            &lt;clipPath id=&quot;clipPath10584&quot;&gt;
                &lt;polygon id=&quot;polygon10300&quot; points=&quot;73,126 73,140 87,140 87,126 73,126 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;text font-size=&quot;10px&quot; style=&quot;font-size:10px;fill:#000000;font-family:SVGTimes&quot; id=&quot;text10302&quot; y=&quot;137&quot; x=&quot;74&quot;&gt;-
            &lt;/text&gt;
            &lt;text font-size=&quot;10px&quot; style=&quot;font-size:10px;fill:#000000;font-family:Times New Roman&quot; id=&quot;text10304&quot; y=&quot;137&quot; x=&quot;80.5&quot;&gt;3
            &lt;/text&gt;
        &lt;/g&gt;
        &lt;g clip-path=&quot;url(#cp19)&quot; id=&quot;g10321&quot; transform=&quot;translate(878.5,113.10879)&quot;&gt;
            &lt;clipPath id=&quot;clipPath10599&quot;&gt;
                &lt;polygon id=&quot;polygon10324&quot; points=&quot;73,126 73,140 87,140 87,126 73,126 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;text font-size=&quot;10px&quot; style=&quot;font-size:10px;fill:#000000;font-family:SVGTimes&quot; id=&quot;text10326&quot; y=&quot;137&quot; x=&quot;74&quot;&gt;-
            &lt;/text&gt;
            &lt;text font-size=&quot;10px&quot; style=&quot;font-size:10px;fill:#000000;font-family:Times New Roman&quot; id=&quot;text10328&quot; y=&quot;137&quot; x=&quot;80.5&quot;&gt;2
            &lt;/text&gt;
        &lt;/g&gt;
        &lt;g clip-path=&quot;url(#cp21)&quot; id=&quot;g10345&quot; transform=&quot;translate(878.5,83.54204)&quot;&gt;
            &lt;clipPath id=&quot;clipPath10614&quot;&gt;
                &lt;polygon id=&quot;polygon10348&quot; points=&quot;73,126 73,140 87,140 87,126 73,126 &quot; /&gt;
            &lt;/clipPath&gt;
            &lt;text font-size=&quot;10px&quot; style=&quot;font-size:10px;fill:#000000;font-family:SVGTimes&quot; id=&quot;text10350&quot; y=&quot;137&quot; x=&quot;74&quot;&gt;-
            &lt;/text&gt;
            &lt;text font-size=&quot;10px&quot; style=&quot;font-size:10px;fill:#000000;font-family:Times New Roman&quot; id=&quot;text10352&quot; y=&quot;137&quot; x=&quot;80.5&quot;&gt;1
            &lt;/text&gt;
        &lt;/g&gt;
        &lt;g inkscape:label=&quot;Grid&quot; style=&quot;display:inline&quot; id=&quot;layer1&quot; inkscape:groupmode=&quot;layer&quot;&gt;
            &lt;path id=&quot;path3303&quot; d=&quot;M 509.22918,101.60001 L 69.830541,101.60001&quot; style=&quot;fill:#000000;fill-opacity:1;stroke:#646464;stroke-width:1.00000011999999994;stroke-opacity:0.1254902&quot; /&gt;
            &lt;path id=&quot;path3305&quot; d=&quot;M 69.987992,173.5 L 709.99817,173.5&quot; style=&quot;fill:#000000;fill-opacity:1;stroke:#646464;stroke-width:1;stroke-opacity:0.1254902&quot; /&gt;
            &lt;path id=&quot;path3307&quot; d=&quot;M 708.93322,245.5 L 70,245.5&quot; style=&quot;fill:#000000;fill-opacity:1;stroke:#646464;stroke-width:1;stroke-opacity:0.1254902&quot; /&gt;
            &lt;path id=&quot;path3309&quot; d=&quot;M 70,317.5 L 708.9322,317.5&quot; style=&quot;fill:#000000;fill-opacity:1;stroke:#646464;stroke-width:1;stroke-opacity:0.1254902&quot; /&gt;
            &lt;path id=&quot;path3311&quot; d=&quot;M 70.59888,390 L 709.59869,390&quot; style=&quot;fill:#000000;fill-opacity:1;stroke:#646464;stroke-width:2;stroke-opacity:0.1254902&quot; /&gt;
            &lt;path d=&quot;M 449.5,410 L 449.5,10.002955&quot; id=&quot;path3339&quot; style=&quot;fill:#000000;fill-opacity:1;stroke:#646464;stroke-width:1;stroke-opacity:0.1254902;opacity:1&quot; /&gt;
            &lt;path d=&quot;M 689.50001,409.37064 L 689.50001,10.5&quot; id=&quot;path3343&quot; style=&quot;fill:#000000;fill-opacity:1;stroke:#646464;stroke-width:1;stroke-opacity:0.1254902;opacity:1&quot; /&gt;
            &lt;path id=&quot;path8393&quot; d=&quot;M 709.5,29.500016 L 70.567805,29.500016&quot; style=&quot;fill:#000000;fill-opacity:1;stroke:#646464;stroke-width:1;stroke-opacity:0.1254902&quot; /&gt;
            &lt;path d=&quot;M 89.5,409.37669 L 89.5,10.49991&quot; id=&quot;path3335&quot; style=&quot;fill:#000000;fill-opacity:1;stroke:#646464;stroke-width:1;stroke-opacity:0.1254902;opacity:1&quot; /&gt;
            &lt;rect height=&quot;400.00778&quot; x=&quot;70&quot; y=&quot;9.9949808&quot; width=&quot;640&quot; id=&quot;rect3248&quot; style=&quot;fill:none;stroke:#000000;stroke-width:1.99999964;stroke-opacity:1&quot; /&gt;
            &lt;path id=&quot;path4388&quot; d=&quot;M 569.5,409.57188 L 569.5,173.63683&quot; style=&quot;fill:#000000;fill-opacity:1;stroke:#646464;stroke-width:1.00000011999999994;stroke-opacity:0.1254902;opacity:1&quot; /&gt;
            &lt;path id=&quot;path4414&quot; d=&quot;M 209.5,409.37113 L 209.5,10.5&quot; style=&quot;fill:#000000;fill-opacity:1;stroke:#646464;stroke-width:1;stroke-opacity:0.1254902;opacity:1&quot; /&gt;
            &lt;g id=&quot;g4445&quot; transform=&quot;translate(10,0)&quot;&gt;
                &lt;g id=&quot;g4426&quot; transform=&quot;translate(0,-0.5)&quot; style=&quot;fill:none;stroke:#000000;stroke-opacity:1&quot;&gt;
                    &lt;path d=&quot;M 60,353.97661 L 70,353.97661&quot; id=&quot;path4416&quot; style=&quot;fill:none;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1&quot; /&gt;
                    &lt;path d=&quot;M 60,335.9883 L 65,335.9883&quot; id=&quot;path4418&quot; style=&quot;fill:none;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1&quot; /&gt;
                    &lt;path d=&quot;M 60,371.96491 L 65,371.96491&quot; id=&quot;path4420&quot; style=&quot;fill:none;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1&quot; /&gt;
                &lt;/g&gt;
                &lt;use height=&quot;460&quot; x=&quot;0&quot; xlink:href=&quot;#g4426&quot; y=&quot;0&quot; transform=&quot;translate(0,-72)&quot; width=&quot;720&quot; id=&quot;use4431&quot; style=&quot;fill:none;stroke:#000000;stroke-opacity:1&quot; /&gt;
                &lt;use height=&quot;460&quot; x=&quot;0&quot; xlink:href=&quot;#g4426&quot; y=&quot;0&quot; transform=&quot;translate(0,-143.9922)&quot; width=&quot;720&quot; id=&quot;use4433&quot; style=&quot;fill:none;stroke:#000000;stroke-opacity:1&quot; /&gt;
                &lt;use height=&quot;460&quot; x=&quot;0&quot; xlink:href=&quot;#g4426&quot; y=&quot;0&quot; transform=&quot;translate(0,-215.9844)&quot; width=&quot;720&quot; id=&quot;use4435&quot; style=&quot;fill:none;stroke:#000000;stroke-opacity:1&quot; /&gt;
                &lt;use height=&quot;460&quot; x=&quot;0&quot; xlink:href=&quot;#g4426&quot; y=&quot;0&quot; transform=&quot;translate(0,-287.97661)&quot; width=&quot;720&quot; id=&quot;use4437&quot; style=&quot;fill:none;stroke:#000000;stroke-opacity:1&quot; /&gt;
            &lt;/g&gt;
            &lt;use height=&quot;460&quot; x=&quot;0&quot; xlink:href=&quot;#g4445&quot; y=&quot;0&quot; transform=&quot;matrix(-1,0,0,1,779,0)&quot; width=&quot;720&quot; id=&quot;use4458&quot; /&gt;
            &lt;g id=&quot;g4499&quot; transform=&quot;translate(10,0)&quot;&gt;
                &lt;g transform=&quot;translate(-30,0)&quot; id=&quot;g4476&quot; style=&quot;stroke:#000000;stroke-opacity:1&quot;&gt;
                    &lt;path d=&quot;M 139.5,10.476191 L 139.5,20.000001&quot; id=&quot;path4464&quot; style=&quot;fill:none;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1&quot; /&gt;
                    &lt;path id=&quot;path4299&quot; d=&quot;M 154.5,9.999999 L 154.5,14.999999&quot; style=&quot;opacity:1;fill:#204a87;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline&quot; /&gt;
                    &lt;path id=&quot;path4301&quot; d=&quot;M 124.5,10 L 124.5,15&quot; style=&quot;opacity:1;fill:#204a87;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline&quot; /&gt;
                &lt;/g&gt;
                &lt;use height=&quot;460&quot; x=&quot;0&quot; xlink:href=&quot;#g4476&quot; y=&quot;0&quot; transform=&quot;translate(60,1e-6)&quot; width=&quot;720&quot; id=&quot;use4483&quot; /&gt;
                &lt;use height=&quot;460&quot; x=&quot;0&quot; xlink:href=&quot;#g4476&quot; y=&quot;0&quot; transform=&quot;translate(300,1e-6)&quot; width=&quot;720&quot; id=&quot;use4487&quot; /&gt;
                &lt;use height=&quot;460&quot; x=&quot;0&quot; xlink:href=&quot;#g4476&quot; y=&quot;0&quot; transform=&quot;translate(240,1e-6)&quot; width=&quot;720&quot; id=&quot;use2507&quot; style=&quot;display:inline&quot; /&gt;
                &lt;use height=&quot;460&quot; x=&quot;0&quot; xlink:href=&quot;#g4476&quot; y=&quot;0&quot; transform=&quot;translate(480,1e-6)&quot; width=&quot;720&quot; id=&quot;use2509&quot; style=&quot;display:inline&quot; /&gt;
                &lt;use height=&quot;460&quot; x=&quot;0&quot; xlink:href=&quot;#g4476&quot; y=&quot;0&quot; transform=&quot;translate(120,-0.476191)&quot; width=&quot;720&quot; id=&quot;use4303&quot; style=&quot;display:inline&quot; /&gt;
                &lt;use height=&quot;460&quot; x=&quot;0&quot; xlink:href=&quot;#g4476&quot; y=&quot;0&quot; transform=&quot;translate(360,1e-6)&quot; width=&quot;720&quot; id=&quot;use4307&quot; style=&quot;display:inline&quot; /&gt;
                &lt;use height=&quot;460&quot; x=&quot;0&quot; xlink:href=&quot;#g4476&quot; y=&quot;0&quot; transform=&quot;translate(420,0)&quot; width=&quot;720&quot; id=&quot;use4309&quot; style=&quot;display:inline&quot; /&gt;
                &lt;use height=&quot;460&quot; x=&quot;0&quot; xlink:href=&quot;#g4476&quot; y=&quot;0&quot; transform=&quot;translate(540,0)&quot; width=&quot;720&quot; id=&quot;use4311&quot; style=&quot;display:inline&quot; /&gt;
                &lt;use height=&quot;460&quot; x=&quot;0&quot; xlink:href=&quot;#g4476&quot; y=&quot;0&quot; transform=&quot;translate(180,1e-6)&quot; width=&quot;720&quot; id=&quot;use4305&quot; style=&quot;display:inline&quot; /&gt;
            &lt;/g&gt;
            &lt;use height=&quot;460&quot; x=&quot;0&quot; xlink:href=&quot;#g4499&quot; y=&quot;0&quot; transform=&quot;matrix(1,0,0,-1,0,420)&quot; width=&quot;720&quot; id=&quot;use4514&quot; /&gt;
            &lt;path d=&quot;M 329.5,409.37113 L 329.5,10.5&quot; id=&quot;path2505&quot; style=&quot;fill:#000000;fill-opacity:1;stroke:#646464;stroke-width:1;stroke-opacity:0.1254902;opacity:1&quot; /&gt;
            &lt;path d=&quot;M 390,409.87113 L 390,11&quot; id=&quot;path4269&quot; style=&quot;fill:#000000;fill-opacity:1;stroke:#646464;stroke-width:2;stroke-opacity:0.1254902;display:inline;opacity:1&quot; /&gt;
            &lt;path d=&quot;M 509.5,409.99704 L 509.5,10&quot; id=&quot;path4271&quot; style=&quot;fill:#000000;fill-opacity:1;stroke:#646464;stroke-width:1;stroke-opacity:0.1254902;display:inline;opacity:1&quot; /&gt;
            &lt;path d=&quot;M 629.5,410.19943 L 629.5,173.48166&quot; id=&quot;path4273&quot; style=&quot;fill:#000000;fill-opacity:1;stroke:#646464;stroke-width:0.99999981999999998;stroke-opacity:0.1254902;display:inline;opacity:1&quot; /&gt;
            &lt;path d=&quot;M 149.5,410.99704 L 149.5,11&quot; id=&quot;path4275&quot; style=&quot;fill:#000000;fill-opacity:1;stroke:#646464;stroke-width:1;stroke-opacity:0.1254902;display:inline;opacity:1&quot; /&gt;
            &lt;path d=&quot;M 269.5,410.99704 L 269.5,11&quot; id=&quot;path4277&quot; style=&quot;fill:#000000;fill-opacity:1;stroke:#646464;stroke-width:1;stroke-opacity:0.1254902;display:inline;opacity:1&quot; /&gt;
        &lt;/g&gt;
        &lt;g inkscape:label=&quot;Labels&quot; style=&quot;display:inline&quot; id=&quot;layer2&quot; inkscape:groupmode=&quot;layer&quot;&gt;
            &lt;text xml:space=&quot;preserve&quot; style=&quot;font-size:32px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman;-inkscape-font-specification:Times New Roman Italic&quot; x=&quot;-256&quot; y=&quot;26&quot; id=&quot;text4315&quot; sodipodi:linespacing=&quot;125%&quot; transform=&quot;matrix(0,-1,1,0,0,0)&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan4317&quot; x=&quot;-256&quot; y=&quot;26&quot;&gt;Density&lt;/tspan&gt;&lt;/text&gt;
    &lt;text style=&quot;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; id=&quot;text3259&quot; sodipodi:linespacing=&quot;125%&quot; y=&quot;107.90625&quot; x=&quot;64.386719&quot; xml:space=&quot;preserve&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan3261&quot; y=&quot;107.90625&quot; x=&quot;64.386719&quot;&gt;0.8&lt;/tspan&gt;&lt;/text&gt;
    &lt;text style=&quot;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-opacity:1;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; id=&quot;text3267&quot; sodipodi:linespacing=&quot;125%&quot; y=&quot;179.90625&quot; x=&quot;64.386719&quot; xml:space=&quot;preserve&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan3269&quot; y=&quot;179.90625&quot; x=&quot;64.386719&quot;&gt;0.6&lt;/tspan&gt;&lt;/text&gt;
    &lt;text style=&quot;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; id=&quot;text3283&quot; sodipodi:linespacing=&quot;125%&quot; y=&quot;251.90625&quot; x=&quot;64.386719&quot; xml:space=&quot;preserve&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan3285&quot; y=&quot;251.90625&quot; x=&quot;64.386719&quot;&gt;0.4&lt;/tspan&gt;&lt;/text&gt;
    &lt;text style=&quot;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; id=&quot;text3291&quot; sodipodi:linespacing=&quot;125%&quot; y=&quot;323.90625&quot; x=&quot;64.386719&quot; xml:space=&quot;preserve&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan3293&quot; y=&quot;323.90625&quot; x=&quot;64.386719&quot;&gt;0.2&lt;/tspan&gt;&lt;/text&gt;
    &lt;text style=&quot;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; id=&quot;text3295&quot; sodipodi:linespacing=&quot;125%&quot; y=&quot;395.90625&quot; x=&quot;64.386719&quot; xml:space=&quot;preserve&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan3297&quot; y=&quot;395.90625&quot; x=&quot;64.386719&quot;&gt;0.0&lt;/tspan&gt;&lt;/text&gt;
    &lt;text style=&quot;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; id=&quot;text3315&quot; sodipodi:linespacing=&quot;125%&quot; y=&quot;427.5&quot; x=&quot;88.796875&quot; xml:space=&quot;preserve&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan3317&quot; y=&quot;427.5&quot; x=&quot;88.796875&quot;&gt;−5&lt;/tspan&gt;&lt;/text&gt;
    &lt;text style=&quot;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; id=&quot;text3319&quot; sodipodi:linespacing=&quot;125%&quot; y=&quot;427.5&quot; x=&quot;208.83662&quot; xml:space=&quot;preserve&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan7441&quot; y=&quot;427.5&quot; x=&quot;208.83662&quot;&gt;−3&lt;/tspan&gt;&lt;/text&gt;
    &lt;text style=&quot;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; id=&quot;text3323&quot; sodipodi:linespacing=&quot;125%&quot; y=&quot;427.5&quot; x=&quot;449.43469&quot; xml:space=&quot;preserve&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan8387&quot; y=&quot;427.5&quot; x=&quot;449.43469&quot;&gt;1&lt;/tspan&gt;&lt;/text&gt;
    &lt;text style=&quot;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; id=&quot;text3327&quot; sodipodi:linespacing=&quot;125%&quot; y=&quot;427.5&quot; x=&quot;569.30304&quot; xml:space=&quot;preserve&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan3329&quot; y=&quot;427.5&quot; x=&quot;569.30304&quot;&gt;3&lt;/tspan&gt;&lt;/text&gt;
    &lt;text style=&quot;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; id=&quot;text3331&quot; sodipodi:linespacing=&quot;125%&quot; y=&quot;427.5&quot; x=&quot;689.31641&quot; xml:space=&quot;preserve&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan3333&quot; y=&quot;427.5&quot; x=&quot;689.31641&quot;&gt;5&lt;/tspan&gt;&lt;/text&gt;
    &lt;text style=&quot;font-size:32px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;font-family:Times New Roman;-inkscape-font-specification:Times New Roman Italic&quot; id=&quot;text7794&quot; sodipodi:linespacing=&quot;125%&quot; y=&quot;452.18658&quot; x=&quot;388.4942&quot; xml:space=&quot;preserve&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan7796&quot; y=&quot;452.18658&quot; x=&quot;388.4942&quot;&gt;x&lt;/tspan&gt;&lt;/text&gt;
    &lt;text style=&quot;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; id=&quot;text8399&quot; sodipodi:linespacing=&quot;125%&quot; y=&quot;35.90625&quot; x=&quot;64.386719&quot; xml:space=&quot;preserve&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan8401&quot; y=&quot;35.90625&quot; x=&quot;64.386719&quot;&gt;1.0&lt;/tspan&gt;&lt;/text&gt;
    &lt;text style=&quot;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; id=&quot;text2511&quot; sodipodi:linespacing=&quot;125%&quot; y=&quot;427.5&quot; x=&quot;329.51358&quot; xml:space=&quot;preserve&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan2513&quot; y=&quot;427.5&quot; x=&quot;329.51358&quot;&gt;−1&lt;/tspan&gt;&lt;/text&gt;
    &lt;text style=&quot;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; id=&quot;text4279&quot; sodipodi:linespacing=&quot;125%&quot; y=&quot;427.5&quot; x=&quot;389.22583&quot; xml:space=&quot;preserve&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan4281&quot; y=&quot;427.5&quot; x=&quot;389.22583&quot;&gt;0&lt;/tspan&gt;&lt;/text&gt;
    &lt;text xml:space=&quot;preserve&quot; style=&quot;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;-inkscape-font-specification:Arial&quot; x=&quot;509.56003&quot; y=&quot;427.5&quot; id=&quot;text4283&quot; sodipodi:linespacing=&quot;125%&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan4285&quot; x=&quot;509.56003&quot; y=&quot;427.5&quot;&gt;2&lt;/tspan&gt;&lt;/text&gt;
    &lt;text xml:space=&quot;preserve&quot; style=&quot;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;-inkscape-font-specification:Arial&quot; x=&quot;629.52948&quot; y=&quot;427.5&quot; id=&quot;text4287&quot; sodipodi:linespacing=&quot;125%&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan4289&quot; x=&quot;629.52948&quot; y=&quot;427.5&quot;&gt;4&lt;/tspan&gt;&lt;/text&gt;
    &lt;text xml:space=&quot;preserve&quot; style=&quot;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;-inkscape-font-specification:Arial&quot; x=&quot;269.08502&quot; y=&quot;427.5&quot; id=&quot;text4291&quot; sodipodi:linespacing=&quot;125%&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan4293&quot; x=&quot;269.08502&quot; y=&quot;427.5&quot;&gt;−2&lt;/tspan&gt;&lt;/text&gt;
    &lt;text xml:space=&quot;preserve&quot; style=&quot;font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;-inkscape-font-specification:Arial&quot; x=&quot;148.58823&quot; y=&quot;427.5&quot; id=&quot;text4295&quot; sodipodi:linespacing=&quot;125%&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan4297&quot; x=&quot;148.58823&quot; y=&quot;427.5&quot;&gt;−4&lt;/tspan&gt;&lt;/text&gt;
            &lt;path style=&quot;opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1&quot; d=&quot;M 709.98882,101.5 L 689.54239,101.5&quot; id=&quot;path5472&quot; /&gt;
            &lt;path style=&quot;opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline&quot; d=&quot;M 629.5,9.5 L 629.5,29.94643&quot; id=&quot;path5474&quot; /&gt;
            &lt;path style=&quot;opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline&quot; d=&quot;M 569.5,9.5 L 569.5,29.94643&quot; id=&quot;path5476&quot; /&gt;
            &lt;g id=&quot;g4162&quot; transform=&quot;translate(0,4.4730569)&quot;&gt;
                &lt;path id=&quot;path5446&quot; d=&quot;m 650.16668,109 35.00001,0&quot; style=&quot;fill:#000000;fill-opacity:1;stroke:#4e9a06;stroke-width:4;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline&quot; inkscape:connector-curvature=&quot;0&quot; /&gt;
                &lt;path id=&quot;path5448&quot; d=&quot;m 650.16668,84 35.00001,0&quot; style=&quot;fill:#000000;fill-opacity:1;stroke:#cc0000;stroke-width:4;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline&quot; inkscape:connector-curvature=&quot;0&quot; /&gt;
                &lt;path id=&quot;path5450&quot; d=&quot;m 650.16668,59 35.00001,0&quot; style=&quot;fill:#000000;fill-opacity:1;stroke:#204a87;stroke-width:4;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline&quot; inkscape:connector-curvature=&quot;0&quot; /&gt;
                &lt;g id=&quot;g3482&quot;&gt;
                    &lt;text sodipodi:linespacing=&quot;125%&quot; id=&quot;text5378&quot; y=&quot;65&quot; x=&quot;545&quot; style=&quot;font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; xml:space=&quot;preserve&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan3480&quot; x=&quot;545&quot; y=&quot;65&quot;&gt;0.7,&lt;/tspan&gt;&lt;/text&gt;
        &lt;text xml:space=&quot;preserve&quot; style=&quot;font-size:24px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Times New Roman;-inkscape-font-specification:Times New Roman Italic&quot; x=&quot;517&quot; y=&quot;64&quot; id=&quot;text3466&quot; sodipodi:linespacing=&quot;125%&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan3470&quot; x=&quot;517&quot; y=&quot;64&quot;&gt;μ&lt;/tspan&gt;&lt;/text&gt;
        &lt;text xml:space=&quot;preserve&quot; style=&quot;font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; x=&quot;531&quot; y=&quot;65&quot; id=&quot;text3474&quot; sodipodi:linespacing=&quot;125%&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan3478&quot; x=&quot;531&quot; y=&quot;65&quot;&gt;=&lt;/tspan&gt;&lt;/text&gt;
                &lt;/g&gt;
                &lt;g transform=&quot;translate(0,24)&quot; id=&quot;g3490&quot;&gt;
                    &lt;text xml:space=&quot;preserve&quot; style=&quot;font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; x=&quot;545&quot; y=&quot;65&quot; id=&quot;text3492&quot; sodipodi:linespacing=&quot;125%&quot;&gt;&lt;tspan y=&quot;65&quot; x=&quot;545&quot; id=&quot;tspan3494&quot; sodipodi:role=&quot;line&quot;&gt;0.3,&lt;/tspan&gt;&lt;/text&gt;
        &lt;text sodipodi:linespacing=&quot;125%&quot; id=&quot;text3496&quot; y=&quot;64&quot; x=&quot;517&quot; style=&quot;font-size:24px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Times New Roman;-inkscape-font-specification:Times New Roman Italic&quot; xml:space=&quot;preserve&quot;&gt;&lt;tspan y=&quot;64&quot; x=&quot;517&quot; id=&quot;tspan3498&quot; sodipodi:role=&quot;line&quot;&gt;μ&lt;/tspan&gt;&lt;/text&gt;
        &lt;text sodipodi:linespacing=&quot;125%&quot; id=&quot;text3500&quot; y=&quot;65&quot; x=&quot;531&quot; style=&quot;font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; xml:space=&quot;preserve&quot;&gt;&lt;tspan y=&quot;65&quot; x=&quot;531&quot; id=&quot;tspan3502&quot; sodipodi:role=&quot;line&quot;&gt;=&lt;/tspan&gt;&lt;/text&gt;
                &lt;/g&gt;
                &lt;g id=&quot;g3504&quot; transform=&quot;translate(0,50)&quot;&gt;
                    &lt;text sodipodi:linespacing=&quot;125%&quot; id=&quot;text3506&quot; y=&quot;65&quot; x=&quot;545&quot; style=&quot;font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; xml:space=&quot;preserve&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan3508&quot; x=&quot;545&quot; y=&quot;65&quot;&gt;0.0,&lt;/tspan&gt;&lt;/text&gt;
        &lt;text xml:space=&quot;preserve&quot; style=&quot;font-size:24px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Times New Roman;-inkscape-font-specification:Times New Roman Italic&quot; x=&quot;517&quot; y=&quot;64&quot; id=&quot;text3510&quot; sodipodi:linespacing=&quot;125%&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan3512&quot; x=&quot;517&quot; y=&quot;64&quot;&gt;μ&lt;/tspan&gt;&lt;/text&gt;
        &lt;text xml:space=&quot;preserve&quot; style=&quot;font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; x=&quot;531&quot; y=&quot;65&quot; id=&quot;text3514&quot; sodipodi:linespacing=&quot;125%&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan3516&quot; x=&quot;531&quot; y=&quot;65&quot;&gt;=&lt;/tspan&gt;&lt;/text&gt;
                &lt;/g&gt;
                &lt;g transform=&quot;translate(-2,0)&quot; id=&quot;g3578&quot;&gt;
                    &lt;text xml:space=&quot;preserve&quot; style=&quot;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial&quot; x=&quot;595&quot; y=&quot;57.5&quot; id=&quot;text5386&quot; sodipodi:linespacing=&quot;125%&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan5388&quot; x=&quot;595&quot; y=&quot;57.5&quot;&gt;2&lt;/tspan&gt;&lt;/text&gt;
        &lt;text xml:space=&quot;preserve&quot; style=&quot;font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; x=&quot;617&quot; y=&quot;65&quot; id=&quot;text3556&quot; sodipodi:linespacing=&quot;125%&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan3576&quot; x=&quot;617&quot; y=&quot;65&quot;&gt;0.2,&lt;/tspan&gt;&lt;/text&gt;
        &lt;text sodipodi:linespacing=&quot;125%&quot; id=&quot;text3560&quot; y=&quot;64&quot; x=&quot;581&quot; style=&quot;font-size:24px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Times New Roman;-inkscape-font-specification:Times New Roman Italic&quot; xml:space=&quot;preserve&quot;&gt;&lt;tspan y=&quot;64&quot; x=&quot;581&quot; sodipodi:role=&quot;line&quot; id=&quot;tspan3574&quot;&gt;σ&lt;/tspan&gt;&lt;/text&gt;
        &lt;text sodipodi:linespacing=&quot;125%&quot; id=&quot;text3564&quot; y=&quot;65&quot; x=&quot;603&quot; style=&quot;font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; xml:space=&quot;preserve&quot;&gt;&lt;tspan y=&quot;65&quot; x=&quot;603&quot; id=&quot;tspan3566&quot; sodipodi:role=&quot;line&quot;&gt;=&lt;/tspan&gt;&lt;/text&gt;
                &lt;/g&gt;
                &lt;g transform=&quot;translate(-2,0)&quot; id=&quot;g3616&quot;&gt;
                    &lt;text sodipodi:linespacing=&quot;125%&quot; id=&quot;text3590&quot; y=&quot;81.5&quot; x=&quot;595&quot; style=&quot;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial&quot; xml:space=&quot;preserve&quot;&gt;&lt;tspan y=&quot;81.5&quot; x=&quot;595&quot; id=&quot;tspan3592&quot; sodipodi:role=&quot;line&quot;&gt;2&lt;/tspan&gt;&lt;/text&gt;
        &lt;text sodipodi:linespacing=&quot;125%&quot; id=&quot;text3594&quot; y=&quot;89&quot; x=&quot;617&quot; style=&quot;font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; xml:space=&quot;preserve&quot;&gt;&lt;tspan y=&quot;89&quot; x=&quot;617&quot; sodipodi:role=&quot;line&quot; id=&quot;tspan3614&quot;&gt;1.0,&lt;/tspan&gt;&lt;/text&gt;
        &lt;text xml:space=&quot;preserve&quot; style=&quot;font-size:24px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Times New Roman;-inkscape-font-specification:Times New Roman Italic&quot; x=&quot;581&quot; y=&quot;88&quot; id=&quot;text3598&quot; sodipodi:linespacing=&quot;125%&quot;&gt;&lt;tspan y=&quot;88&quot; x=&quot;581&quot; id=&quot;tspan3600&quot; sodipodi:role=&quot;line&quot;&gt;σ&lt;/tspan&gt;&lt;/text&gt;
        &lt;text xml:space=&quot;preserve&quot; style=&quot;font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; x=&quot;603&quot; y=&quot;89&quot; id=&quot;text3602&quot; sodipodi:linespacing=&quot;125%&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan3604&quot; x=&quot;603&quot; y=&quot;89&quot;&gt;=&lt;/tspan&gt;&lt;/text&gt;
                &lt;/g&gt;
                &lt;g transform=&quot;translate(-2,0)&quot; id=&quot;g3654&quot;&gt;
                    &lt;text xml:space=&quot;preserve&quot; style=&quot;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial&quot; x=&quot;595&quot; y=&quot;107.5&quot; id=&quot;text3628&quot; sodipodi:linespacing=&quot;125%&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan3630&quot; x=&quot;595&quot; y=&quot;107.5&quot;&gt;2&lt;/tspan&gt;&lt;/text&gt;
        &lt;text xml:space=&quot;preserve&quot; style=&quot;font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; x=&quot;617&quot; y=&quot;115&quot; id=&quot;text3632&quot; sodipodi:linespacing=&quot;125%&quot;&gt;&lt;tspan y=&quot;115&quot; x=&quot;617&quot; sodipodi:role=&quot;line&quot; id=&quot;tspan3652&quot;&gt;5.0,&lt;/tspan&gt;&lt;/text&gt;
        &lt;text sodipodi:linespacing=&quot;125%&quot; id=&quot;text3636&quot; y=&quot;114&quot; x=&quot;581&quot; style=&quot;font-size:24px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Times New Roman;-inkscape-font-specification:Times New Roman Italic&quot; xml:space=&quot;preserve&quot;&gt;&lt;tspan sodipodi:role=&quot;line&quot; id=&quot;tspan3638&quot; x=&quot;581&quot; y=&quot;114&quot;&gt;σ&lt;/tspan&gt;&lt;/text&gt;
        &lt;text sodipodi:linespacing=&quot;125%&quot; id=&quot;text3640&quot; y=&quot;115&quot; x=&quot;603&quot; style=&quot;font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Arial;-inkscape-font-specification:Arial&quot; xml:space=&quot;preserve&quot;&gt;&lt;tspan y=&quot;115&quot; x=&quot;603&quot; id=&quot;tspan3642&quot; sodipodi:role=&quot;line&quot;&gt;=&lt;/tspan&gt;&lt;/text&gt;
                &lt;/g&gt;
            &lt;/g&gt;
        &lt;/g&gt;
        &lt;g inkscape:label=&quot;Plot&quot; style=&quot;display:inline&quot; id=&quot;layer3&quot; inkscape:groupmode=&quot;layer&quot;&gt;
            &lt;path id=&quot;path2848&quot; style=&quot;fill:none;fill-rule:evenodd;stroke:#4e9a06;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none&quot; d=&quot;M 689.24386,384.58482 C 552.4645,374.02107 489.22546,325.66253 390.00383,325.66253 C 290.7822,325.66253 227.54316,374.02107 90.763797,384.58482&quot; sodipodi:nodetypes=&quot;csc&quot; /&gt;
            &lt;path id=&quot;path2842&quot; style=&quot;fill:none;fill-rule:evenodd;stroke:#cc0000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none&quot; d=&quot;M 690.00556,390.00048 C 592.43012,390.00048 600.21168,389.02653 585.9561,388.05084 C 530.67824,384.2675 505.59061,352.10721 483.63019,321.97928 C 455.7852,283.77818 435.04993,246.05331 410.00383,246.05331 C 384.95773,246.05331 364.22246,283.77818 336.37747,321.97928 C 314.41705,352.10721 289.32942,384.2675 234.05156,388.05084 C 219.79598,389.02653 227.57754,390.00048 90.002096,390.00048&quot; sodipodi:nodetypes=&quot;csssssc&quot; /&gt;
            &lt;path id=&quot;path2846&quot; style=&quot;fill:none;fill-rule:evenodd;stroke:#204a87;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none&quot; d=&quot;M 690.00556,390.52604 L 540.23211,390.4186 C 518.08687,390.40606 508.58858,387.27973 503.7801,383.16076 C 481.11533,363.74599 475.59626,314.38284 464.03221,243.95886 C 449.46349,155.23673 442.34229,68.387971 430.00383,68.387971 C 417.66537,68.387971 410.54417,155.23673 395.97545,243.95886 C 384.4114,314.38284 378.89233,363.74599 356.22756,383.16076 C 351.41908,387.27973 351.92079,390.40606 319.77555,390.4186 L 90.002096,390.52604&quot; sodipodi:nodetypes=&quot;ccssssscc&quot; /&gt;
        &lt;/g&gt;
    &lt;/svg&gt;

&lt;center&gt;&lt;small&gt;Which would you prefer: low bias and high precision, or no bias and low(er) precision?&lt;/small&gt;&lt;/center&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;In many ways, bias is a valuable heuristic. It allows us to encode large amounts of categorical information and take action without shuffling mountains of data whenever we need to make a decision. Even when bias predicts falsely, the cost of a false positive may outweigh the cost of a false negative on average. Imagine a hiring bot rejects a West Samoan programmer, who is a genius-level engineer. While she would have made an excellent hire, if the metrics can’t properly estimate the value of a candidate, the safest strategy is to hire from a well-known population over one with unproven or uncertain quality.&lt;/p&gt;

&lt;p&gt;Society thrives on social bias. It is the glue that keeps cultures and organizations intact, in the midst of sweeping globalization. Many have biases of athletic prowess, charismatic personality, or academic aptitude. We are comfortable with these biases, proud of our tolerance and sophistication in applying them. Some have biases of religious affiliation, ethnic background or physical similarity. We call these biases shameful, whilst secretly holding them ourselves. But now we can quantify bias, and the numbers do not paint a pretty picture. There will always be more and less accurate biases. But we must exercise caution. For bias, accurate or contrived, can have long-lasting effects on a population.&lt;/p&gt;

&lt;p&gt;Human decision makers are prone to hundreds of &lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_cognitive_biases&quot;&gt;cognitive biases&lt;/a&gt;. Whether relevant, or remotely accurate in any objective measure, bias can have &lt;a href=&quot;https://en.wikipedia.org/wiki/Stereotype_threat&quot;&gt;negative&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Pygmalion_effect&quot;&gt;positive effects&lt;/a&gt; on a human population. The trouble with bias in prediction, is that any &lt;a href=&quot;https://en.wikipedia.org/wiki/Self-serving_bias&quot;&gt;success is deceptive&lt;/a&gt;. Through luck or skill&lt;sup id=&quot;fnref:4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;, whenever someone is slightly successful at prediction, they invariably want to exploit their newfound predictive abilities. And exploitation is a whole new ballgame.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;For most of ML, the training data is a given, often presumed to be representative of the data against which the prediction model will be deployed, but not much else. With a few notable exceptions, ML abstracts away from the data generating mechanism, and hence sees the data as raw material from which predictions are to be extracted. Indeed, machine learning generally lacks the vocabulary to capture the distinction between observational data and randomized data…&lt;/p&gt;

  &lt;p&gt;Most of the prediction literature assumes that predictions are made by a passive observer with no influence in the phenomenon. On the other hand, most prediction systems are used to make decisions about how to intervene in a phenomenon. Often, the assumption of non-influence is quite reasonable — say if we predict whether or not it will rain in order to determine if we should carry an umbrella. In this case, whether or not we decide to carry an umbrella clearly doesn’t affect the weather. But at other times, matters are less clear…&lt;/p&gt;

  &lt;p&gt;―Omkar Muralidharan, et al., &lt;em&gt;&lt;a href=&quot;http://www.unofficialgoogledatascience.com/2017/01/causality-in-machine-learning.html&quot;&gt;Causality in machine learning&lt;/a&gt;&lt;/em&gt; (2017)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Exploitation requires a deep understanding of cause and effect, or deep reserves of luck. &lt;a href=&quot;https://en.wikipedia.org/wiki/Causality&quot;&gt;This subject&lt;/a&gt; is challenging for even the &lt;a href=&quot;https://en.wikipedia.org/wiki/Replication_crisis&quot;&gt;scientifically trained&lt;/a&gt;, and one of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Reinforcement_learning&quot;&gt;toughest problems&lt;/a&gt; in AI. There is an outstanding body of work which explores the role of &lt;a href=&quot;http://bayes.cs.ucla.edu/BOOK-2K/causality2-epilogue.pdf&quot;&gt;causality&lt;/a&gt; in machine learning. In short, the same predictive machinery that landed humans on the moon is surprisingly easy to derail. The &lt;a href=&quot;https://en.wikipedia.org/wiki/Confirmation_bias&quot;&gt;same biases&lt;/a&gt; that impair our reasoning, make it easy to contaminate for example, AI models trained by humans, on human data, for other humans to interpret.&lt;/p&gt;

&lt;p&gt;Long after machines are calling the shots, our heuristic biases will continue to deflect their ballistic trajectories. Although we may never eliminate human bias, we can ensure machines are less prone to statistical ones like &lt;a href=&quot;https://en.wikipedia.org/wiki/Selection_bias&quot;&gt;selection&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Verification_bias&quot;&gt;verification&lt;/a&gt; bias. Those training AI in a new domain should be asking themselves three important questions:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Are we really measuring what we want to measure? (ie. &lt;a href=&quot;https://en.wikipedia.org/wiki/Test_validity&quot;&gt;Test validity&lt;/a&gt;)
    &lt;ul&gt;
      &lt;li&gt;Many advertisers try to maximize clicks. This is a &lt;a href=&quot;https://en.wikipedia.org/wiki/Click_fraud&quot;&gt;loosing battle&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;Objectives may change over the production lifetime of a model.&lt;/li&gt;
      &lt;li&gt;A poorly chosen objective can have &lt;a href=&quot;https://en.wikipedia.org/wiki/Unintended_consequences&quot;&gt;unintended consequences&lt;/a&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Is the training data accurate and free from hidden bias? (ie. &lt;a href=&quot;https://en.wikipedia.org/wiki/Internal_validity&quot;&gt;Internal validity&lt;/a&gt;)
    &lt;ul&gt;
      &lt;li&gt;People constantly forget (or conveniently overlook) &lt;a href=&quot;https://en.wikipedia.org/wiki/Confounding&quot;&gt;confounds&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;If the data generator is biased, the model will encode its bias.&lt;/li&gt;
      &lt;li&gt;The method of sampling may have &lt;a href=&quot;https://en.wikipedia.org/wiki/Selection_bias#Sampling_bias&quot;&gt;hidden biases&lt;/a&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Does the training data generalize well in practice? (ie. &lt;a href=&quot;https://en.wikipedia.org/wiki/External_validity&quot;&gt;External validity&lt;/a&gt;)
    &lt;ul&gt;
      &lt;li&gt;Maybe the training data has grown stale over time.&lt;/li&gt;
      &lt;li&gt;Maybe the model is missing data on some key demographic.&lt;/li&gt;
      &lt;li&gt;Maybe the true population is not the population we bargained for.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These questions are only clues in the search for unwanted bias. By eliminating sources of statistical bias, we can guarantee that human biases are apparent for what they are, not hiding as statistical errors in disguise. But we must not complacently check lists and perform t-tests. AI promises great predictive power, but with great power comes great responsibility. And responsible machine learning requires us to analyze human incentives, vigorously challenge our assumptions and constantly evaluate the validity of trained models.&lt;/p&gt;

&lt;p&gt;Bias is an inextricable part of the world - every die is slightly loaded, every deck slightly stacked in one way or another. Machine learning just formalizes bias, blessing it under the auspices of validity. Bias can be found everywhere from the smallest neuron in a neural network, to the &lt;a href=&quot;https://en.wikipedia.org/wiki/Ensemble_learning&quot;&gt;largest ensemble&lt;/a&gt; in a prize-winning Kaggle submission. Neural networks are essentially computing the sum of various biases - as the network sees more data, it updates the biases. Over time, some grow stronger and some grow weaker. Like their biological cousins, artificial neurons are &lt;a href=&quot;https://en.wikipedia.org/wiki/Coincidence_detection_in_neurobiology&quot;&gt;coincidence detectors&lt;/a&gt; - they cannot distinguish association from causation. Intelligence is hard-wired to attribute &lt;a href=&quot;https://en.wikipedia.org/wiki/Fundamental_attribution_error&quot;&gt;association&lt;/a&gt; to &lt;a href=&quot;https://en.wikipedia.org/wiki/Proximate_and_ultimate_causation&quot;&gt;causation&lt;/a&gt;, causing all manner of false rituals and &lt;a href=&quot;https://en.wikipedia.org/wiki/B._F._Skinner#Superstition_in_the_pigeon&quot;&gt;superstitious behavior&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Fifty thousand years ago there were these three guys spread out across the plain and they each heard something rustling in the grass. The first one thought it was a tiger, and he ran like hell, and it was a tiger but the guy got away. The second one thought the rustling was a tiger and he ran like hell, but it was only the wind and his friends all laughed at him for being such a chickenshit. But the third guy thought it was only the wind, so he shrugged it off and the tiger had him for dinner. And the same thing happened a million times across ten thousand generations - and after a while everyone was seeing tigers in the grass even when there weren’t any tigers, because even chickenshits have more kids than corpses do. And from those humble beginnings we learn to see &lt;a href=&quot;https://en.wikipedia.org/wiki/Pareidolia&quot;&gt;faces in the clouds&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Astrology&quot;&gt;portents in the stars&lt;/a&gt;, to see &lt;a href=&quot;https://en.wikipedia.org/wiki/Apophenia&quot;&gt;agency in randomness&lt;/a&gt;, because natural selection favours the paranoid. Even here in the 21st century we can make people more honest just by &lt;a href=&quot;https://en.wikipedia.org/wiki/Watching-Eye_Effect&quot;&gt;scribbling a pair of eyes on the wall&lt;/a&gt; with a Sharpie. Even now we are wired to believe that &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Truman_Show_delusion&quot;&gt;unseen things are watching us&lt;/a&gt;.&lt;/p&gt;

  &lt;p&gt;―Peter Watts, &lt;em&gt;Echopraxia&lt;/em&gt; (2015)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There will always be more and less accurate biases, depending on what we are measuring, and what outcome we hope to predict. Even so, machine learning will only reflect the data we show it, not the possible confounds from an unseen parameter, nor the possibilities if the world were a different place. If we do not probe these hypotheses, we are doomed to flee tigers in the grass, build monuments to false causes, and leave &lt;a href=&quot;https://en.wikipedia.org/wiki/Human_Potential_Movement&quot;&gt;greatness in poverty&lt;/a&gt;. How many Lincolns were shot, or Einsteins put to the sword in the name of some false bias?&lt;/p&gt;

&lt;p&gt;There is a dangerous course ahead on the path to autonomy. If we maintain the bias that only those who produce capital deserve to receive it, today’s economic inequality will grow exponentially worse. In the same way that genetic or geographic origin once predetermined a human’s social mobility, economic fitness will determine one’s financial security. In such a future, only those who are fast enough, smart enough, or wealthy enough to accelerate the pace of automation will enjoy the prosperity and wellbeing it guarantees. This is a heavy price to pay for a small increase in convenience and safety.&lt;/p&gt;

&lt;p&gt;This is not a matter of social welfare. This is a matter of prolonging our competitive advantage against automation. By applying the same biases from evolutionary biology to education and employment, we are vastly underutilizing human potential. We should seek every opportunity to provide creative agency and professional opportunity to people from all walks of life. We should prefer deaf applicants to work in noisy environments, and let elderly people take leadership positions. We should empower those with mental and physical disabilities to find roles where they can utilize their skills effectively. We should incentivize high-performers in low-paying jobs from teaching to healthcare, and give them tools to become more effective at school and in the workplace.&lt;/p&gt;

&lt;h1 id=&quot;work-in-progress&quot;&gt;Work in Progress&lt;/h1&gt;
&lt;p&gt;&lt;br /&gt;
AI sometimes gets a bad rap. We often hear about AI in very competitive terms: whenever bots are not stealing our jobs or out-maneuvering us at chess, they are &lt;a href=&quot;https://www.wired.com/2007/10/robot-cannon-ki/&quot;&gt;badly malfunctioning&lt;/a&gt; or causing some &lt;a href=&quot;https://medium.com/@jitbit/facebook-is-terrifying-8dc4a016b64b&quot;&gt;intrusion&lt;/a&gt; of &lt;a href=&quot;https://www.theguardian.com/technology/2011/aug/03/facebook-facial-recognition-privacy-germany&quot;&gt;privacy&lt;/a&gt;. And while it is important to maintain a healthy skepticism of the dangerous role that AI poses to our society, I think we will look back at many early applications as lacking sufficient imagination.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The Independents, rooted in the farms and small towns of the West, were innovators, but of a conceptual kind, not the technical kind à la Alexander Bell…They intuited that the telephone’s paramount value was not as a better version of the telegraph or a more efficient means of commerce, but as the first social technology…&lt;/p&gt;

  &lt;p&gt;Typically, the rural telephone systems were giant party lines, allowing a whole community to chat with or listen to one another. Obviously there was no privacy, but there were benefits to communal telephony other than secure person-to-person communications. Farmers would use the telephone lines to carry their own musical performances…&lt;/p&gt;

  &lt;p&gt;And so, while the Bell Company may have invented the telephone, it clearly didn’t perceive the full spectrum of its uses. This is such a common affliction that we might name it “founder’s myopia”. Again and again in the development of technology, full appreciation of an invention’s potential importance falls to others…&lt;/p&gt;

  &lt;p&gt;—Tim Wu, &lt;em&gt;The Master Switch: The Rise and Fall of Information Empires&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Technologists typically want to settle old scores. Greek astronomers invented &lt;a href=&quot;https://en.wikipedia.org/wiki/Antikythera_mechanism&quot;&gt;primitive computers&lt;/a&gt; to foretell celestial movement, but never dreamt their descendants would use them to sail the heavens. The developers of microwave technology didn’t intend radar to heat food. If you have a general algorithm which learns to maximize reward by repeatedly choosing from a set of actions, then clearly you have an algorithm which prints money.&lt;sup id=&quot;fnref:5&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:5&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; But more importantly, if you have such a technology, then you have a new form of intelligent life. Why teach it to print paper, when we could be teaching it to write books?&lt;/p&gt;

&lt;p&gt;The currency of the future is data, and the computational resources to mine it for insights. To say that money will vanish in the post-scarcity economy would be hubris, but printing money is just a side-effect, a parlor-trick compared the possible applications which AI affords. You might as well &lt;a href=&quot;https://wiki.lesswrong.com/wiki/Paperclip_maximizer&quot;&gt;print paperclips&lt;/a&gt; and trade them for timeshares on the cloud. Our goal should be improving the lives of human beings, and if money is a necessary means to do so, then let’s &lt;a href=&quot;https://en.wikipedia.org/wiki/Guaranteed_minimum_income&quot;&gt;print money&lt;/a&gt;. Although I suspect printing money is like &lt;a href=&quot;https://en.wiktionary.org/wiki/give_a_man_a_fish_and_you_feed_him_for_a_day;_teach_a_man_to_fish_and_you_feed_him_for_a_lifetime&quot;&gt;handing out fish&lt;/a&gt;. If our goal is truly improving the lives of human beings rather than manufacturing consumers, we will need to give people a stable livelihood and meaningful ways to pursue happiness in the age of automation.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The hope is that, in not too many years, human brains and computing machines will be coupled together very tightly, and that the resulting partnership will think as no human brain has ever thought and process data in a way not approached by the information-handling machines we know today.&lt;/p&gt;

  &lt;p&gt;—J. C. R. Licklider, &lt;em&gt;&lt;a href=&quot;https://groups.csail.mit.edu/medg/people/psz/Licklider.html&quot;&gt;Man-Computer Symbiosis&lt;/a&gt;&lt;/em&gt; (1960)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One of the major limitations of user interfaces is bandwidth - keyboards and screens can only exchange so much information with their users. But today’s computers have the ability to interact with their environment in brilliant new ways. From self-flying drones to &lt;a href=&quot;https://en.wikipedia.org/wiki/Virtual_patient&quot;&gt;virtual patients&lt;/a&gt;, and home appliances to &lt;a href=&quot;https://en.wikipedia.org/wiki/Intelligent_personal_assistant&quot;&gt;smart assistants&lt;/a&gt;, machines are becoming increasingly perceptive, and increasingly conversant. Machines can see, hear, and understand natural language. They can recognize faces and speech, anticipate our intentions and assist with increasingly sophisticated tasks. We call these capabilities “artificial intelligence”. But a more apt name might be “&lt;a href=&quot;https://en.wikipedia.org/wiki/Intelligence_amplification&quot;&gt;augmented intelligence&lt;/a&gt;”.&lt;/p&gt;

&lt;p&gt;There are thousands of exciting AI applications, from tracking the spread of &lt;a href=&quot;http://users.stat.umn.edu/~majum010/research/Huntin%20Zika_DSSG%20Chicago%20talk.pdf&quot;&gt;infectious diseases&lt;/a&gt; to detecting &lt;a href=&quot;http://www.fakenewschallenge.org/&quot;&gt;fake news&lt;/a&gt;, from &lt;a href=&quot;http://journals.plos.org/plosbiology/article/file?id=10.1371/journal.pbio.1002593&amp;amp;type=printable&quot;&gt;brain-computer interfaces&lt;/a&gt; for coma patients, to &lt;a href=&quot;http://www.isi.edu/~gil/papers/gil-etal-acs16.pdf&quot;&gt;automated hypothesis testing&lt;/a&gt; for scientists. Applications that are transforming our relationship with technology and improving the lives of billions of people on earth. The problems we encounter in AI are the same problems we have been struggling with for the greater part of the 20th century. Education. Equal opportunity. Employment. The democratization of technology. Solving these problems will require a more comprehensive view of AI, one that transcends just classification, prediction or automation.&lt;/p&gt;

&lt;p&gt;Progress begins when we stop using algorithms to just predict people’s habits, and start teaching them new ones. When we give people a fighting chance, by retraining those whose jobs are threatened by automation. When we identify where humans show promise and teaching them how to improve. When we use AI to prevent diseases rather than designing drugs to treat symptoms. Progress begins when we start fixing broken systems rather than exploiting their weakness. If you want to contribute to the survival of our species, get out of the prediction game, and get into the business of making progress.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://news.ycombinator.com/item?id=13565828&quot;&gt;Discuss this post on HN&lt;/a&gt;!&lt;/p&gt;

&lt;h3 id=&quot;further-reading&quot;&gt;Further Reading&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.unofficialgoogledatascience.com/2016/10/practical-advice-for-analysis-of-large.html&quot;&gt;Practical advice for analysis of large, complex data sets&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://bayes.cs.ucla.edu/BOOK-2K/causality2-epilogue.pdf&quot;&gt;The Art and Science of Cause and Effect&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://idlewords.com/talks/deep_fried_data.htm&quot;&gt;Deep-Fried Data&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h3&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Arguably China’s most famous living sci-fi writer. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Pedro Domingos, &lt;a href=&quot;http://www.astro.caltech.edu/~george/ay122/cacm12.pdf&quot;&gt;A Few Useful Things to Know about Machine Learning&lt;/a&gt;. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I have no idea whether the prior assertions are true. But a careful reading will reveal no implied causal relationship between “bias”, “productivity” and “profit”. The point is, we can replace “bias”, “productivity” and “profit” with any variable X, Y and Z. You control X, and observe the effect on Y and Z. Suppose X is positively correlated with Y and Z, i.e. higher values of X correspond to frequently higher values of Y and Z. Lower values correspond with frequently lower Y and Z, with high variance for low values of X. If we want to maximize Z, what is our best strategy? &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Although usually the former. &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:5&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Many clever but unimaginative people contracted the same idea at once, so one’s chances of developing a predictive advantage, and their profits from exploiting it, are much slimmer. &lt;a href=&quot;#fnref:5&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Tales of a Traveling Twentysomething</title>
   <link href="breandan.net/2016/12/27/traveling-tales/"/>
   <updated>2016-12-27T00:00:00+00:00</updated>
   <id>breandan.net/2016/12/27/traveling-tales</id>
   <content type="html">&lt;p&gt;&lt;em&gt;In which I describe globetrotting on &lt;a href=&quot;https://www.car2go.com/&quot;&gt;Cars2Go&lt;/a&gt;, death-defying feats of gallantry, learning how to deliver a baby, and other mildly interesting stories from a prodigal twentysomething technologist with first-world problems.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Earlier this year, I had the chance to go on sabbatical. So I went. Since then, I have spent time in many interesting places - some for work, some for conferences, some just for the hell of it. As the year is almost over, I thought I would share parts of my journey. Perhaps you may wish to visit some of these places. Some of them, you will not.&lt;/p&gt;

&lt;p&gt;In January 2016, I visited the sister of a Brother who lives in Phoenix. She kindly showed me the city where she had recently moved from somewhere in Long Island. We ate breakfast at the &lt;a href=&quot;http://www.breakfastclub.us/&quot;&gt;Breakfast Club&lt;/a&gt;, and looked for a relative who drowned in the attack on Pearl Harbor. In the middle of their city they have planted a &lt;a href=&quot;https://en.wikipedia.org/wiki/Wesley_Bolin_Memorial_Plaza&quot;&gt;huge gun&lt;/a&gt; for the lost sailors of the Battleship Arizona.&lt;/p&gt;

&lt;p&gt;In February, I flew to Atlanta, and was promptly greeted by a cheerful Hawaiian professional photographer, turned recreational Uber driver, who gave a white kid tips for how to survive on the streets of Atlanta over Italian pasta. I think he took pity on me sitting in the backseat of his Uber. Besides &lt;a href=&quot;http://www.cbs46.com/story/31337956/suspicious-package-found-under-car-in-downtown-atlanta&quot;&gt;the bomb evacuation&lt;/a&gt; at DevNexus, it was a pretty nice trip.&lt;/p&gt;

&lt;figure&gt;
&lt;img src=&quot;https://www.gstatic.com/prettyearth/assets/full/1168.jpg&quot; /&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;small&gt;From &lt;a href=&quot;https://www.google.com/maps/@33.7444502,-84.3914727,753m/data=!3m1!1e3&quot;&gt;Google Earth&lt;/a&gt;, over the I-20 and I-85 interchange in downtown Atlanta.&lt;/small&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Later that month, I boarded &lt;a href=&quot;https://en.wikipedia.org/wiki/Adirondack_(train)&quot;&gt;Adirondack #69&lt;/a&gt; from New York to Montreal for &lt;a href=&quot;https://confoo.ca/en&quot;&gt;ConFoo&lt;/a&gt;. After running for miles in the freezing sleet, wondering what I was doing with my life and nearly succumbing to hypothermia, I met some incredibly kind people, including a friend from Brasil, the organizers, a &lt;a href=&quot;https://plugins.jetbrains.com/idea/plugin/7896-markdown-navigator&quot;&gt;plugin&lt;/a&gt; developer, and lots of Canadians. Great conference.&lt;/p&gt;

&lt;p&gt;Shortly after driving down to &lt;a href=&quot;https://www.eclipsecon.org/na2016/event/619&quot;&gt;EclipseCon&lt;/a&gt; in Washington, DC, I met some friendly people from &lt;a href=&quot;https://www.youtube.com/watch?v=HJOpNss7tCQ&quot;&gt;a top-secret Russian laboratory&lt;/a&gt;, Goldman Sachs, and a couple of lawyers for the CFTC (all completely unrelated). I also had the opportunity to visit the National Basilica, a gigantic statue of Albert Einstein and the National Museum of Natural History. Go there.&lt;/p&gt;

&lt;p&gt;In April I had a layover in Hong Kong and decided to get Dim Sum. Instead, I wandered around and got caught in a thunderstorm. So I did what anyone would normally do and climbed the tallest mountain I could find. After nearly dying of electrocution, the stormclouds parted and I caught a glimpse of the sprawling cyberpunk nirvana that is Greater Hong Kong.&lt;/p&gt;

&lt;figure&gt;
&lt;img src=&quot;https://imgur.com/mzG3FIg.jpg&quot; /&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;small&gt;The 68th Hong Kong School Prize Concert for Sacred Music, at &lt;a href=&quot;https://en.wikipedia.org/wiki/St._John&apos;s_Cathedral_(Hong_Kong)&quot;&gt;St. John&apos;s Cathedral&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The rain started back up again, so I ducked into an empty church to dry off. Suddenly, there a great commotion - hundreds of children, dripping and tripping all over the place. They came in busses and bunches, shuffling onto the benches. Thunder and pouring rain. Umbrellas and coats. Candles everywhere. Then, they began to sing. I never heard anything so beautiful.&lt;/p&gt;

&lt;p&gt;Landing in Bengaluru, I was greeted by the sound of pandemonium. Bengaluru is the tech capital of India, and I was here to work. After a long series of business meetings, chasing down deliveries, hailing three-wheeled contraptions, and drinking my weight in water every day, I felt cautiously prepared for the ensuing conference festivities.&lt;/p&gt;

&lt;center&gt; &lt;figure&gt;
&lt;img src=&quot;https://imgur.com/Qf54aVZ.jpg&quot; height=&quot;500&quot; /&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;center&gt;&lt;small&gt;
    &lt;a href=&quot;https://en.wikipedia.org/wiki/Vada_pav&quot;&gt;Vada pav&lt;/a&gt;, from &lt;a href=&quot;https://goo.gl/maps/KPSXZCR2QhC2&quot;&gt;Sagar Resturant&lt;/a&gt; in Bengaluru.
&lt;/small&gt;&lt;/center&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;&lt;/center&gt;

&lt;p&gt;Our tiny booth was quickly overwhelmed by a multitude of curious people. And from dawn to dusk, we shook hands, we gave away shirts, we held quizzes. Following an amazing culinary extravaganza and near-death experience with food-poisoning on &lt;a href=&quot;https://en.wikipedia.org/wiki/M_G_Road,_Bangalore&quot;&gt;M.G. Road&lt;/a&gt;, I am convinced Indian food, like all delicious things, is best consumed in moderation.&lt;/p&gt;

&lt;p&gt;Two of my colleagues took it upon themselves to personally drive me around Bengaluru, broker steaming cups of tea from passing chaiwallas, order samosa, vada pav, and chats from busy street vendors, visit parliamentary buildings, gold-laden temples, purchase a saree, navigate massive thoroughfares and narrow alleyways, negotiate access to gated compounds.&lt;/p&gt;

&lt;p&gt;Two things stand out in my mind. Indian enthusiasm is contagious. As a North American, my people are cool, reserved. We work hard, and complain a lot. Indians are hard working, and will happily talk to you about anything under the sun. I guess everyone is the same, everyone is different. But I am deeply grateful for their kindness.&lt;/p&gt;

&lt;figure&gt;
&lt;img src=&quot;https://imgur.com/AizBAJq.jpg&quot; /&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;small&gt;Street vendors on the outskirts of &lt;a href=&quot;https://en.wikipedia.org/wiki/Dharavi&quot;&gt;Dharavi&lt;/a&gt;, one of the largest slums in the world.&lt;/small&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;After a brief stint in Mumbai, I flew back to New York with a new set of problems. So I decided to ignore them and go for a prolonged bike trip through the Pacific Northwest. Turns out that was just a different set of problems. I took the &lt;a href=&quot;https://en.wikipedia.org/wiki/Amtrak_Cascades&quot;&gt;Amtrak Cascades&lt;/a&gt; from Seattle to Vancouver, rented a bike there, packed my backpack, and headed for Alaska.&lt;/p&gt;

&lt;p&gt;After several near-death collisions, I gave up and settled for Whistler. If you sit at a desk for twelve hours a day, don’t try to peddle a bike 80 miles uphill the next one. Thank me later. But Whistler has fresh air, LTE, and skiing in May, so I was happy. I watched the seaplanes take off over Green Lake and wondered what I was doing with my life. Such are the problems we have in the first world.&lt;/p&gt;

&lt;figure&gt;
&lt;img src=&quot;https://imgur.com/TLCTbYX.jpg&quot; /&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;small&gt;Seaplanes take off from Whistler, carrying passengers and cargo to Vancouver.&lt;/small&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;After taking stock of the situation, I decided to pursue the full-time occupation of chasing a girl halfway around the planet. That was a pretty good idea in hindsight. We met in Vancouver, in Austin, in New York, in Boston and Portland and most places in between. You name it and we were probably there for some event or meetup this May or June.&lt;/p&gt;

&lt;p&gt;It was my first time visiting Portland. We went there for &lt;a href=&quot;http://opensourcebridge.org/&quot;&gt;Open Source Bridge&lt;/a&gt;, spent some time exploring Washington Park, and saw a spectacular &lt;a href=&quot;http://japanesegarden.com/&quot;&gt;Japanese Garden&lt;/a&gt;, recently restored and beautifully manicured, with a traveling bonsai exhibit. They have a &lt;a href=&quot;https://en.wikipedia.org/wiki/Pittock_Mansion&quot;&gt;Gilded Era mansion&lt;/a&gt; on the hill which is well-worth the visit, if just for the view. We also saw an extraordinary production of &lt;a href=&quot;http://www.oregonlive.com/art/index.ssf/2016/05/a_streetcar_named_desire_portl.html&quot;&gt;A Streetcar Named Desire&lt;/a&gt; at Portland Center Stage.&lt;/p&gt;

&lt;p&gt;Planes. Trains. Automobiles. Every week was somewhere new. The daily milieu of new faces and scenes provided a welcome diversion to the reality of my situation. I chatted with &lt;a href=&quot;http://farzadsbarbershop.com/&quot;&gt;Iranian barbers&lt;/a&gt; in Vancouver, brunched with captive bears on Grouse Mountain, had &lt;a href=&quot;http://ramendanbo.com/&quot;&gt;good ramen&lt;/a&gt; on Robson, explored castaway &lt;a href=&quot;http://www.cbc.ca/news/canada/british-columbia/city-of-vancouver-may-need-to-pay-for-removal-of-boat-1.3582300&quot;&gt;shipwrecks&lt;/a&gt; on False Creek, sat on the &lt;a href=&quot;https://backofhouse.s3.amazonaws.com/uploads/ckeditor/pictures/834/content_clift-BOH-chair-1.jpg&quot;&gt;largest chair&lt;/a&gt; in San Fransisco, tested the &lt;a href=&quot;http://www.nytimes.com/2016/07/22/arts/design/testing-new-york-citys-longest-slide-on-governors-island.html&quot;&gt;longest slide&lt;/a&gt; in New York.&lt;/p&gt;

&lt;figure&gt;
&lt;img src=&quot;https://imgur.com/SRIwoCf.jpg&quot; /&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;small&gt;The Cheng-Shi. Her captain was &lt;a href=&quot;https://www.facebook.com/motormontyb&quot;&gt;&quot;A sailor of the mind&quot;&lt;/a&gt;. &lt;a href=&quot;https://www.gofundme.com/riseagain&quot;&gt;Sadly&lt;/a&gt;, not a sailor of the sea.&lt;/small&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;How does one afford to travel so much? The answer is, as frequent flyers will explain in hushed voices, with lots of credit cards. By the interest earned from delinquent debtors and with a little help from Uncle Sam, US banks will simply hand you fake currency, if you pay your credit card bills in a timely fashion, that may be used at various airlines and hotel chains.&lt;/p&gt;

&lt;p&gt;In June, I boarded UA 149 to São Paulo International Airport with a couple hundred other Brazilians. That plane never arrived in São Paulo International Airport. Nor did any of the subsequent flights we were on. Instead, they abandoned us behind customs in Rio Galeão without food or water for eight hours. To my amazement, United Airlines did not seem to see any problem with all this. The Brazilians just shrugged and laughed.&lt;/p&gt;

&lt;p&gt;In São Paulo I had some &lt;a href=&quot;https://twitter.com/breandan/status/750761636714151936&quot;&gt;amazing milkshakes&lt;/a&gt;, ate coxinhas and churrasco. I kept watch for police as my friend flew his drone around Ibirapuera Park to much public dismay, reassured fleeing bystanders, and in general did a whole lot of chasing other people around São Paulo. I had &lt;a href=&quot;http://lamenkazu.com.br/&quot;&gt;excellent ramen&lt;/a&gt; in Liberdade. Somehow managed to give a coherent talk about machine learning. Or maybe not. English is not their first language.&lt;/p&gt;

&lt;figure&gt;
&lt;img src=&quot;https://imgur.com/dedYenP.jpg&quot; alt=&quot;Boys in the yard&quot; /&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;https://www.facebook.com/My-Oh-My-Milkshakes-319551614901766/&quot;&gt;Oh My Milkshakes&lt;/a&gt; has the best milkshake I have ever tasted. It&apos;s really, really good.&lt;/small&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;In July, I fired my dentist. In hindsight, that was probably not a good idea. He was getting on my nerves with the appointment reminders, but he was a consummate professional, through and through. Dentists are good people, and even if they are a little fanatical about oral hygiene, they have your best interests at heart. You should see one regularly.&lt;/p&gt;

&lt;p&gt;Later that month, I landed in Los Angeles. This was a big mistake. After breaking down in an antique automobile on I-15, I nearly perished from dehydration in the great suburban wasteland that lies east of LA, running to make an appointment with my father’s third ex-wife. Do not try to drive a car twice your age through the desert in summertime.&lt;/p&gt;

&lt;p&gt;In August, after surviving another bout of food poisoning, I flew from LA to Bergen, Norway, by way of Dallas and London. The plan was to meet my girlfriend in Hamburg ten days later. Plenty of time to take the train from Bergen to Oslo to Stockholm to Malmö to København to Hamburg. Or so I thought.&lt;/p&gt;

&lt;p&gt;I spent a day dodging lorries in a dodgy part of London on &lt;a href=&quot;https://tfl.gov.uk/modes/cycling/santander-cycles&quot;&gt;Santander Cycles&lt;/a&gt;, and eating &lt;a href=&quot;https://www.shoryuramen.com/stores/1-regent-street/categories&quot;&gt;mediocre ramen&lt;/a&gt; in Piccadilly Circus. After making my Heathrow connection with seconds to spare, I arrived in Bergen, still breathless, with my newly printed &lt;a href=&quot;http://www.eurail.com/&quot;&gt;Eurail pass&lt;/a&gt; proudly in hand to show the customs officer. He sighed, and stamped my passport.&lt;/p&gt;

&lt;figure&gt;
&lt;img src=&quot;https://imgur.com/BlaXOvl.jpg&quot; /&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;small&gt;The &lt;a href=&quot;https://en.wikipedia.org/wiki/Bergen_Line&quot;&gt;Bergen Line&lt;/a&gt; connects Bergen and Oslo, carrying millions of people each year.&lt;/small&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The journey from Bergen to Oslo was completely otherworldly, filled with gaping fjords, scenic vistas, glacial streams, and mountain passes. I sat next to a biologist studying seasonal migration patterns and teaching a summer seminar in Voss. I watched Norwegian villages and stations glide past my window. Norway is a strikingly gorgeous country, and I highly recommend the &lt;a href=&quot;https://www.nsb.no/en/our-destinations/our-regional-railway-lines/bergenrailway&quot;&gt;Bergen Railway&lt;/a&gt; if your travels should take you anywhere in the vicinity.&lt;/p&gt;

&lt;p&gt;Stayed with a rock band living in Oslo. They kindly loaned me their bicycle, which I put to extensive use exploring the neighboring countryside. There, I wandered into a surreal village that looked like it was from the 17th century. The townsfolk, dressed in period clothing, made pointed gestures at my bicycle while speaking Norwegian. This was confusing, as I do not speak Norwegian and seemed to be only person from the 21st century that morning. I discovered it was a &lt;a href=&quot;https://en.wikipedia.org/wiki/Norwegian_Museum_of_Cultural_History&quot;&gt;historical reenactment&lt;/a&gt;, with live actors and livestock. Nearby, is the &lt;a href=&quot;http://www.royalcourt.no/artikkel.html?tid=28703&quot;&gt;Royal farm of Norway&lt;/a&gt;, stocked with heavily armed soldiers in open pastures. I took the ferry back to Oslo and ate some delicious &lt;a href=&quot;http://punjabi-masala.no/&quot;&gt;Punjabi food&lt;/a&gt; for dinner.&lt;/p&gt;

&lt;p&gt;I arrived in Stockholm late. The host was asleep, or forgot about my arrival. After accidentally waking up her neighbor and probably the whole apartment building, we arranged to meet a nice old lady, who apologized to everyone in Swedish, made some tea and introduced me to her city. Stockholm is a big park with a city attached. You can bike alongside people horsebacking through the woods. Have &lt;a href=&quot;http://www.rosendalstradgard.se/&quot;&gt;lunch&lt;/a&gt; in the middle of green fields. Toured an &lt;a href=&quot;https://en.wikipedia.org/wiki/Vasa_(ship)&quot;&gt;old warship&lt;/a&gt; dredged up from the bottom of the sea.&lt;/p&gt;

&lt;p&gt;King of Sweden orders the largest warship ever built. Three masts. 64 guns. Topheavy, narrow-looking abomination. Two years to build the damn thing. Launches to much public fanfare. No ballast. Light breeze starts to blow in the harbor, and she sinks, killing thirty sailors. King starts an investigation. Everyone points up the chain of command, back to the King who rubber stamped the whole thing. Investigation quickly ends. Remind you of any software projects?&lt;/p&gt;

&lt;figure&gt;
&lt;img src=&quot;https://imgur.com/ZTB1hGt.jpg&quot; /&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Bergen_Line&quot;&gt;Kaknästornet&lt;/a&gt; is a tower that broadcasts television and radio signals all over Sweden.&lt;/small&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Malmö is an little city on the coast of southern Sweden. The area where I stayed had long rows of block-style housing with WWII-era bomb shelters underneath. They have a tall building called the &lt;a href=&quot;https://en.wikipedia.org/wiki/Turning_Torso&quot;&gt;Turning Torso&lt;/a&gt;, visible from any point in the city and which my host pointed out enthusiastically. Disappointingly, it did not turn. Very windy and chilly here in August. I rode to Øresund Bridge and returned for hot chocolate, then boarded the commuter train to København.&lt;/p&gt;

&lt;p&gt;In København, I stayed with the marketing director for the ESS in Sweden (apparently, big science projects need marketing people to help secure grants and so forth). He gave me directions to a pretty good &lt;a href=&quot;http://ramentobiiru.dk/&quot;&gt;ramen place&lt;/a&gt; nearby, and told me to visit a high-energy particle accelerator in Hamburg called DESY.&lt;/p&gt;

&lt;p&gt;There exists &lt;a href=&quot;https://en.wikipedia.org/wiki/Vogelfluglinie&quot;&gt;a train&lt;/a&gt; from København to Hamburg which holds the distinction (unbeknownst to me at the time) of being a &lt;a href=&quot;https://en.wikipedia.org/wiki/Boat_train&quot;&gt;boat train&lt;/a&gt;. So you can imagine my excitement to be suddenly sitting on such a train, aboard a &lt;a href=&quot;https://en.wikipedia.org/wiki/Vogelfluglinie&quot;&gt;boat&lt;/a&gt;. They even gave us the opportunity to disembark from said train onto said boat, which I availed to great satisfaction.&lt;/p&gt;

&lt;p&gt;My girlfriend met me in Hamburg. Much to her chagrin, my primary reason for visiting there was to see the &lt;a href=&quot;http://www.miniatur-wunderland.com/&quot;&gt;Miniatur Wunderland&lt;/a&gt;. To her further chagrin, the second reason was now &lt;a href=&quot;https://en.wikipedia.org/wiki/DESY&quot;&gt;DESY&lt;/a&gt;. This time, I went alone. I slipped into a small tour, lead by someone who looked important. Later I discovered the tour was in German, but by then it was too late to turn back. I nodded thoughtfully and continued to do so for the remaining three hours as we walked from one secure facility to the next. Crisis averted.&lt;/p&gt;

&lt;figure&gt;
&lt;img src=&quot;https://imgur.com/iVFY75G.jpg&quot; /&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;small&gt;Beneath a quiet suburb of Hamburg, DESY accelerates particles to 0.9999999C.&lt;/small&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;We then proceeded to visit a number of central European cities. Bonn for a week. Berlin for a few days. Potsdam for a day. Zürich for a day. Bern for a day. Lausanne for two. Zermatt and St. Moritz for a day. Salzburg for a week. Two days in Frankfurt. It was a whirlwind of trains, running to catch trains, finding our train was delayed, scrambling taxis to catch another train, etc. This required weeks of planning, but happily we made all of our scheduled connections, through careful chronological concentration.&lt;/p&gt;

&lt;p&gt;Bonn is a quaint city with a surprising amount of trivia. Once home to Beethoven and former capital of Germany, it now houses the T-Mobile headquarters, Haribo, a large &lt;a href=&quot;https://www.solarworld-usa.com/&quot;&gt;solar conglomerate&lt;/a&gt;, and has the &lt;a href=&quot;http://www.midi-bonn.de/das-midi/&quot;&gt;best scrambled eggs&lt;/a&gt; I have personally tasted. Met a geology student who wanted to visit America. I encouraged him to do so. Later, I tried &lt;a href=&quot;https://en.wikipedia.org/wiki/Club-Mate&quot;&gt;Club-Mate&lt;/a&gt; for the first time, and went to some good &lt;a href=&quot;https://media.ccc.de/c/froscon2016&quot;&gt;talks at FrOSCon&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;From what I gathered, Berlin is a very culturally diverse and hip place to be. Personally, I was more interested in the historical bits, but even if you’re not there’s a lot to take in. There is &lt;a href=&quot;https://www.google.com/search?num=100&amp;amp;q=berlin+shanghainese+food&amp;amp;npsic=0&amp;amp;rflfq=1&amp;amp;rlha=0&amp;amp;rllag=52514292,13399547,5241&amp;amp;tbm=lcl&amp;amp;ved=0ahUKEwjmtLm3qI7RAhUr6IMKHcg8CoMQtgMIIQ&amp;amp;tbs=lf_msr:-1,lf_od:-1,lf_oh:-1,lf:1,lf_ui:9,lf_pqs:EAE#rlfi=hd:;si:;mv:!1m3!1d132595.8775997734!2d13.373693812304737!3d52.492941176095016!3m2!1i860!2i655!4f13.1&quot;&gt;Shanghainese food&lt;/a&gt;, neat European bistros, foreign exchange students hopping gleefully with stories of their latest party, vast swaths of beautifully manicured parks, loads of history. You could spend weeks here. Unfortunately, I only had a few days.&lt;/p&gt;

&lt;p&gt;It was in Berlin where I began to appreciate the cultural differences between Germany and America. In the US we are outwardly warm, sometimes overtly so. Germans are outwardly cold, but inwardly warm and caring. These differences may cause some misunderstanding. You may think a German is being curt, or rude. Do not fret. Germans are very kind, once you get to know one.&lt;/p&gt;

&lt;p&gt;There is a monument in the middle of Berlin, which you should visit, called &lt;a href=&quot;https://en.wikipedia.org/wiki/Neue_Wache&quot;&gt;Neue Wache&lt;/a&gt;. On a boulevard full of pompous looking buildings, it looks like any other. But if you take a moment to step inside, it will catch you off guard. Behind iron bars and beneath a hole in the roof sits a mother cradling her dead son. There are thousands of war memorials with huge guns. Go here instead.&lt;/p&gt;

&lt;figure&gt;
&lt;img src=&quot;https://www.gstatic.com/prettyearth/assets/full/1943.jpg&quot; /&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;small&gt;The Berlin Victory Column, as seen from outer space, looks out over the Tiergarten.&lt;/small&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Potsdam is nice to visit if you like palaces and gardens. I took the S-Bahn to Potsdam, rented a bike there, and rode for hours through the park. Later, I returned to Berlin and visited the &lt;a href=&quot;https://en.wikipedia.org/wiki/Olympiastadion_(Berlin)&quot;&gt;Olympiastadion&lt;/a&gt;, a very impressive piece of architecture, accessible from the same line. But even if you’re not into stuffy old castles, you should visit Potsdam, because it is a very peaceful place indeed.&lt;/p&gt;

&lt;p&gt;After a brief episode of frantically running around Berlin, chasing down a taxi, swerving to avoid oncoming traffic, and scrambling around the station to find our platform, we leapt aboard the &lt;a href=&quot;https://en.wikipedia.org/wiki/City_Night_Line&quot;&gt;City Night Line&lt;/a&gt; to Zürich, luggage and all, as they closed their doors and whistled to beat the band. The conductor tapped on his watch crossly. It was all very &lt;a href=&quot;https://youtu.be/8Q6YqCRMwEI?t=75&quot;&gt;Wes Anderson-esque&lt;/a&gt;, except far less fun.&lt;/p&gt;

&lt;p&gt;We awoke to the Zürich sunshine in August, and quickly realized the sun can be very hot under prolonged exposure. Storing our luggage in the train station, we got Muesli for breakfast, walked around the &lt;a href=&quot;https://www.stadt-zuerich.ch/ssd/de/index/sport/schwimmen/sommerbaeder/flussbad_unterer_letten/adresse.secure.html&quot;&gt;river baths&lt;/a&gt; and had fish at Nordsee, a German fast food chain. You probably wouldn’t associate fresh fish with fast food, but it is surprisingly palatable. Then it was time to go to Bern.&lt;/p&gt;

&lt;p&gt;Bern has some &lt;a href=&quot;http://www.bindella.ch/de/kornhauskeller.html&quot;&gt;very&lt;/a&gt; &lt;a href=&quot;http://www.entrecote.ch/&quot;&gt;good&lt;/a&gt; &lt;a href=&quot;http://www.rosengarten.be/welcome/&quot;&gt;restaurants&lt;/a&gt; which I highly recommend visiting if you have the time and inclination. We toured the &lt;a href=&quot;http://www.einstein-bern.ch/&quot;&gt;Einstein House&lt;/a&gt;, strolled through the Rose Garden, peered into a bear bit, dipped our feet into the icy blue river, and did a good bit of touristy sounding things. Switzerland is a marvelous place if you have never been there before.&lt;/p&gt;

&lt;figure&gt;
&lt;img src=&quot;https://imgur.com/p54pP3f.jpg&quot; /&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;small&gt;By the bank of the Aare river. It looks calm, but swimming is actually very dangerous.&lt;/small&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Geneva is the home of CERN, which is mainly why we went there. You need to book a &lt;a href=&quot;https://visit.cern/tours/guided-tours-individuals&quot;&gt;guided tour&lt;/a&gt; two weeks in advance, which gets reserved within a few minutes of new availability each day, so be prepared to mash &lt;code&gt;F5&lt;/code&gt; 15 days before your arrival. The group self-selects for scientifically literate people, and our guide knew particle physics, so the tour is technically very educational.&lt;/p&gt;

&lt;p&gt;From Geneva, we took a train to Visp, and up to Zermatt via a special railway that clings to the mountain like a snake in a tree, between cliffside dwellings perched on dubious ledges. We avoided making any sudden movements, lest they decide to take up flight. Cancelled a similar funicular excursion just a few days earlier, due to a &lt;a href=&quot;https://en.wikipedia.org/wiki/August_2016_Central_Italy_earthquake&quot;&gt;large earthquake&lt;/a&gt; that had recently struck central Italy.&lt;/p&gt;

&lt;p&gt;The town of Zermatt is only accessible by train, which is a good thing, because we had no other way of getting up there. However this means it is inaccessible when there are slides or avalanches. Fortunately, there were no slides or avalanches, and we arrived without incident. Stayed at &lt;a href=&quot;http://www.alpenresort.com/en/welcome/&quot;&gt;Best Western&lt;/a&gt; (a great place in Switzerland) and watched the sun set over the Matterhorn.&lt;/p&gt;

&lt;figure&gt;
&lt;img src=&quot;https://imgur.com/vNMZNqh.jpg&quot; /&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;small&gt;The Matterhorn in the summer afternoon. It is one of the deadliest peaks in the world.&lt;/small&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The next morning, we left bright and early on the &lt;a href=&quot;https://en.wikipedia.org/wiki/Glacier_Express&quot;&gt;Glacier Express&lt;/a&gt;, the slowest high speed train in the world. Scenic waypoints are narrated in dulcet sing-song, like a person reading a children’s fairy tale, in English, German, Italian, French and possibly Romansh. We passed through steep mountain passes, sweeping valleys, and over trestles spanning deep gorges.&lt;/p&gt;

&lt;p&gt;Arriving in St. Moritz later that afternoon, we hauled our bags a kilometer uphill into a &lt;a href=&quot;http://www.arte-stmoritz.ch/&quot;&gt;hotel above a pizza shop&lt;/a&gt; then walked around the lake. We watched people maneuver small sailboats, and tuxedo-clad chaps &lt;a href=&quot;http://www.csistmoritz.ch/&quot;&gt;jump horses&lt;/a&gt; over fences in the late summer sunshine. It was all spectacularly European. St. Moritz is very extravagant, dripping with fur, fast cars and grand old hotels.&lt;/p&gt;

&lt;p&gt;Then we took a train to Salzburg, by way of Zürich. Salzburg was really interesting, and much more salt-of-the-earth. I grew up watching &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Sound_of_Music_(film)&quot;&gt;The Sound of Music&lt;/a&gt; every Christmas, so there was an immediate connection. To my dismay, Austrians do not typically break out in A Capella musical overtures, and frowned on my own attempts to engage them in doing so, vis-à-vis &lt;a href=&quot;https://www.youtube.com/watch?v=0IagRZBvLtw&quot;&gt;My Favorite Things&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Salzburg is a town on a river, as many European towns are prone to be. More importantly, it has an abundance of salt. &lt;a href=&quot;https://en.wikipedia.org/wiki/History_of_salt&quot;&gt;Salt&lt;/a&gt; was once the currency of the day, hence the English, &lt;em&gt;salary&lt;/em&gt;. This means that Salzburg was a very wealthy place when salt was the legal tender, and accumulated a great deal of castles and aristocratic types through the taxation and export of salt along its river.&lt;/p&gt;

&lt;p&gt;One of these was the Archbishop of Salzburg, Markus Sittikus, who by all accounts was not a very pleasant person, but hey, times were different. He built a large estate, known as &lt;a href=&quot;https://en.wikipedia.org/wiki/Hellbrunn_Palace&quot;&gt;Hellbrunn Palace&lt;/a&gt;, containing many cruel hydraulic innovations. To this day, guides use his collection to torment passing tourists.&lt;/p&gt;

&lt;center&gt;
&lt;figure&gt;
&lt;img src=&quot;https://i.imgur.com/GChzakn.gif&quot; /&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;center&gt;&lt;small&gt;Paragliders taking off from the top of Zwölferhorn Mountain in St. Gilgen, Austria.&lt;/small&gt;&lt;/center&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;&lt;/center&gt;

&lt;p&gt;After spending several pleasant days exploring the lakes and mountains of Salzburg, riding gondolas, watching people fling themselves off mountaintops on kites, catching Pokémon, concertgoing, and eating far too much &lt;a href=&quot;https://en.wikipedia.org/wiki/Mozartkugel&quot;&gt;Mozartkugel&lt;/a&gt;, we waved goodbye to Austria and made great haste for Frankfurt.&lt;/p&gt;

&lt;p&gt;I commandeered a &lt;a href=&quot;https://www.car2go.com&quot;&gt;Car2Go&lt;/a&gt; on the Frankfurt autobahn, a road with no need for speed limits, beside those required by the laws of physics. This was fortunate, as we were short on time. Unfortunately, the laws of physics have bounded Car2Go’s maximum horizontal velocity to the approximate speed of a golf cart, so it ended up taking a while. But once you finally park the thing, you’re right beside the airport check-in.&lt;/p&gt;

&lt;p&gt;Then I spent a week in San Jose at the beginning of September, and saw some great &lt;a href=&quot;http://www.datastax.com/company/events/cassandra-summit-2016-recorded-sessions-and-slides&quot;&gt;talks at Cassandra Summit&lt;/a&gt;. Cassandra is a pretty cool technology if you have truly enormous amounts of data to record. Maybe if this blog post is ever finished I will have a legitimate need for it.&lt;/p&gt;

&lt;p&gt;Rented a car on Friday and drove south for the weekend. If you have a special weekend enterprise and are looking for automotive transportation, take the &lt;a href=&quot;https://www.enterprise.com/en/car-rental/deals/weekend-specials.html&quot;&gt;Enterprise Weekend Special&lt;/a&gt;. They’ll pick you up anywhere but the airport and you’ll pay more for gas than the car itself.&lt;/p&gt;

&lt;p&gt;Monterey is the ancestral home of &lt;a href=&quot;https://en.wikipedia.org/wiki/John_Steinbeck&quot;&gt;John Steinbeck&lt;/a&gt;, and the setting for many of his novels. John is a great writer. But he doesn’t do it justice. The coastline of northern California is indescribably beautiful. You can run on warm beaches crashing with surf in the Caramel Highlands and walk through quiet stands of Coast Redwood in Big Sur. Go there, you will not regret it.&lt;/p&gt;

&lt;figure&gt;
&lt;img src=&quot;https://imgur.com/Ug7YDlX.jpg&quot; /&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;small&gt;Chrysaora quinquecirrha, or Sea Nettle, are swimming inside the Monterey Aquarium.&lt;/small&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Flew to Boston and back the next weekend for JavaOne. Taught some kids how to break ciphers with an friend from India, who lives in Utah. Kids are wicked smart. Went for a nice bike ride to Sausalito with some speakers from Switzerland, a contractor for the US Patent Office, a developer from Ireland. Took the ferry back. Had a fair &lt;a href=&quot;http://www.mensho.tokyo/&quot;&gt;bowl of ramen&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Each year, Oracle swoops into San Fransisco like Christmas in September and paints everything red and white. Flies racing yachts in by crane, blocks off city streets. The last couple years, they built a carnival complete with ferris wheel and free food, fireworks, Elton John, then bussed ten thousand people out to &lt;a href=&quot;https://en.wikipedia.org/wiki/Treasure_Island,_San_Francisco&quot;&gt;Treasure Island&lt;/a&gt; for an all-night bacchanalian celebration. This year, they were conservative and filled a baseball stadium instead.&lt;/p&gt;

&lt;p&gt;From SF, I flew to LA and back the following week, for SVCC. It rained, so I rented a car and drove into the northern Diablo Mountains. I drove into the clouds, and arrived at &lt;a href=&quot;https://en.wikipedia.org/wiki/Lick_Observatory&quot;&gt;Lick Observatory&lt;/a&gt; on Mt. Hamilton to a haunting silence. The air was still and there was no sign of humanity. I found a custodian, who showed me the telescopes. We had to be very quiet, because most astronomers are asleep during the day.&lt;/p&gt;

&lt;figure&gt;
&lt;img src=&quot;https://imgur.com/uY4AwHV.jpg&quot; /&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;small&gt;Supposedly the Mt. Hamilton Road has 365 turns, but this is a &lt;a href=&quot;https://en.wikipedia.org/wiki/Coastline_paradox&quot;&gt;coastline problem.&lt;/a&gt; &lt;/small&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Returning from the clouds, I had lunch at Sweet Tomatoes, which is my favorite restaurant in California. They have unlimited soup and salad, but not the usual buffet fare. It’s shipped in fresh from the &lt;a href=&quot;https://en.wikipedia.org/wiki/San_Joaquin_Valley#Agriculture&quot;&gt;San Joaquin&lt;/a&gt;, on produce trucks every day. The supply chain is excellent.&lt;/p&gt;

&lt;p&gt;Then I lived in Brasil for a month. I met my girlfriend in São Paulo, where we stayed for some time. Her mother cast spells in the kitchen, conjuring &lt;em&gt;comida caseira&lt;/em&gt;: each morning there was coffee, tea, and eggs. Each afternoon there was pão carteira with mortadela and cheese. Each night there was a feast of file de frango, batatas fritas, feijao com arroz, pavé.&lt;/p&gt;

&lt;p&gt;We flew to Florianopolis for &lt;a href=&quot;http://2016.pythonbrasil.org.br/&quot;&gt;Python Brasil&lt;/a&gt;, where I visited a local &lt;em&gt;faculdade&lt;/em&gt; to talk about unsupervised learning. An audience member offered me a drink of hot mate, which was high quality stuff. Floripa is a very warm and friendly place. You can walk for miles on white sand beaches, eat green pasta and &lt;a href=&quot;http://www.forneriacatarina.com.br/&quot;&gt;perfect pizza&lt;/a&gt;. It was here where I discovered a most remarkable drink, limonada suiça.&lt;/p&gt;

&lt;p&gt;Brazilians have a long tradition of making juice. Their fruit crushing and blending technology has progressed far beyond the outside world. And they have refined the science of mixing fruit beverages, with profound combinatorial breakthroughs. I will share with you one of their secret recipes. Take fresh lemonade. Carbonated water. Add ice, condensed milk and sugar. Mix to a froth. Serve immediately, with a bowl of hot spaghetti and warm bread.&lt;/p&gt;

&lt;p&gt;From Floripa, we headed to the city of &lt;a href=&quot;https://en.wikipedia.org/wiki/Foz_do_Igua%C3%A7u&quot;&gt;Foz do Iguaçu&lt;/a&gt; for Latinoware. Foz do Iguaçu is a fascinating place. Located at the confluence of three rivers, it has an important &lt;a href=&quot;https://en.wikipedia.org/wiki/Itaipu_Dam&quot;&gt;hydroelectric dam&lt;/a&gt;, an &lt;a href=&quot;http://www.visitefoz.com.br/en/attractions/buddhist-temple/&quot;&gt;enormous Buddha&lt;/a&gt;, and a vibrant Islamic community. Oh, and the largest waterfall in the world.&lt;/p&gt;

&lt;figure&gt;
&lt;img src=&quot;https://imgur.com/VWpxl2V.jpg&quot; /&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;small&gt;The Iguaçu Falls spill 1,756 m³/s, which in Imperial, is &lt;i&gt;a gargantuan amount of water&lt;/i&gt;. &lt;/small&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The Cataratas do Iguaçu, or Iguazu Falls, is an enormous chasm in the Iguaçu river, like a giant’s sunken footprint in the jungle. From the air, it looks like something from &lt;a href=&quot;https://en.wikipedia.org/wiki/Avatar_(2009_film)&quot;&gt;Avatar&lt;/a&gt;. From the ground, it’s breathtaking. There’s two sides, both heavily touristed. If you have to choose between them, go to the Argentinian side. Our guide, who spoke fluent Spanish, Portuguese and English, was a tour de force. She could lead armies.&lt;/p&gt;

&lt;p&gt;Visited the largest mosque in Foz and tried a pastry at an Islamic bakery. Tried to eat all the pastries at the bakery. I debated crossing the bridge to Ciudad del Este, but my girlfriend was convinced the Paraguayans would kidnap and sell me into slavery, which is probably not unlikely, so I decided that I was quite happy eating Islamic pastries in Brasil. On to Itajubá.&lt;/p&gt;

&lt;p&gt;Itajubá is a small city in Minas Gerais, about four hours from São Paulo by bus. Its primary attraction is the local university, one of the best in Brasil for engineering, or so I am told. I was introduced by an energetic young professor, gave a short speech to the students, then we all went out and had salgadinhos. The students were all lovely and treated me like an esteemed scholar. It was a little embarrassing, but very thoughtful and well organized.&lt;/p&gt;

&lt;figure&gt;
&lt;img src=&quot;https://imgur.com/kMGBYSz.jpg&quot; /&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;small&gt;Itajuba is home to &lt;a href=&quot;https://en.wikipedia.org/wiki/Federal_University_of_Itajub%C3%A1&quot;&gt;UNIFEI&lt;/a&gt;, the second largest university in the state of Minas Gerais.&lt;/small&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Later that day, I learned how to deliver a baby. At the invitation of my new friend the professor, we visited his laboratory. Inside, was a woman in labor. As you can imagine, this was all very difficult for me to process. But there was work to be done, so we rolled up our sleeves and prepped her for C-section.&lt;/p&gt;

&lt;p&gt;I soon learned &lt;a href=&quot;https://www.facebook.com/usabilidadeunifei/&quot;&gt;the lab&lt;/a&gt; was studying the usability of medical equipment for neonatal ICUs. To do so, they needed a test subject. This subject was me. Or rather, the version of me with a degree in gynecology. The patient was surprisingly realistic, with fake bodily fluids, breathing, vitals. It was uncanny.&lt;/p&gt;

&lt;p&gt;From São Paulo, we just barely made our Heathrow connection to Dublin. Transferring from an international flight to anywhere in the &lt;a href=&quot;https://en.wikipedia.org/wiki/Terminology_of_the_British_Isles&quot;&gt;British Isles&lt;/a&gt; requires crossing no less than three different security checkpoints. By some accident of chance, I have never missed a flight in my life, but this was the closest I have ever been. The stewardess scolded us sternly.&lt;/p&gt;

&lt;p&gt;My family picked us up in Dublin, where we all had a nice supper together. The next day, I brought the folks to &lt;a href=&quot;https://python.ie&quot;&gt;Python Ireland&lt;/a&gt;, which is an excellent conference that I highly suggest you attend. Thanks to the organizers, I was able to wheel Grannie to the front row, where she learned about machine learning with TensorFlow. It was great fun, and a very gratifying experience.&lt;/p&gt;

&lt;figure&gt;
&lt;img src=&quot;https://imgur.com/W5JzD1J.jpg&quot; /&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;small&gt;Back row: Mark (Uncle), Margaret (Mother), Breandan (yours truly). Front row: Grannie.&lt;/small&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;From Dublin, we flew to Brussels for Devoxx Belgium early Monday morning. After landing in the pouring rain, taking a train in the wrong direction, taking a trolley in the wrong direction, and running around like a madman, I arrived for my talk still dripping wet. It went okay, I probably should have spent less time delivering babies and prepared more. However I did learn a lot from &lt;a href=&quot;https://www.youtube.com/playlist?list=PLRsbF2sD7JVrP_MJaOWvaK9-OTNX2oFwB&quot;&gt;other speakers&lt;/a&gt;, saw some old friends and made new ones there.&lt;/p&gt;

&lt;p&gt;Spent a weekend in Amsterdam, where I got a haircut and had a great steaming cup of hot-chocolate, made with real chocolate chips. Then we took a train back to Brussels (Charleroi, to my frustration) and flew to Vilnius for &lt;a href=&quot;https://buildstuff16lithuania.sched.org&quot;&gt;BuildStuff Lituania&lt;/a&gt;. There are a few small conferences in the world that are extremely high quality. BuildStuff is one of them, and &lt;a href=&quot;https://twitter.com/hhariri/status/798784908353097728&quot;&gt;apparently&lt;/a&gt; the organizers donate their proceeds to charity. Go there, if you have the chance.&lt;/p&gt;

&lt;p&gt;Why else would you want to go to Vilnius? For one, they have great restaurants where you can eat well without breaking the bank. They have a pretty nice city, with good transportation. And Lithuanians are a very friendly people. It’s not Switzerland, but the Europa section is very modern and has good restaurants. My favorite one is in the &lt;a href=&quot;https://en.wikipedia.org/wiki/Vilnius_Old_Town&quot;&gt;Old Town&lt;/a&gt;, a place called &lt;a href=&quot;http://www.gusto.lt/index.php/en/&quot;&gt;Gusto blyninė&lt;/a&gt;. If it looks ridiculous, you’ll know you’re at the right place.&lt;/p&gt;

&lt;figure&gt;
&lt;img src=&quot;https://imgur.com/tDBPni5.jpg&quot; /&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Gediminas&apos;_Tower&quot;&gt;Gediminas Tower&lt;/a&gt; has overlooked Vilnius for over 600 years. It is in &lt;a href=&quot;https://www.baltictimes.com/lithuanian_cultmin_calls_for_emergency_situation_over_gediminas_hill/&quot;&gt;need of repair&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;From Vilnius I flew back to Dublin to take Grannie home, who in the meantime had acquired 200 kilograms of cast iron plates for our woodstove. How did Grannie do this? I haven’t the faintest clue. Anyhow, I got the bright idea of putting them all in my carry-on luggage. Surprisingly, this worked. Now I just needed to get them aboard the airplane, with Grannie and her wheelchair.&lt;/p&gt;

&lt;p&gt;I decided it was a problem for another day, so we drove up to Belfast to see the Titanic Museum. Instead we ended up at the Titanic Exhibition Center, which was hosting a &lt;a href=&quot;http://www.worldsnooker.com/tournaments/irish-open-2016/&quot;&gt;snooker championship&lt;/a&gt;, so we watched tuxedo-clad gentlemen sink snooker balls on an oversize pool table. Then we went to the &lt;a href=&quot;https://en.wikipedia.org/wiki/Titanic_Belfast&quot;&gt;Titanic Museum&lt;/a&gt; across the street, which was thoroughly engrossing. After wheeling Grannie halfway around Belfast, we returned to Dublin for our flight.&lt;/p&gt;

&lt;p&gt;We arrived at the airport in the early morning. Somehow made it through security and all the way to US pre-clearance with our 200 kilograms of cast iron. The Irish authorities were furious. Grannie convinced them not to arrest us all then and there (thank you, Grannie!), and even managed to get our stove parts back, but we had to check everything with special permission from the airline, US Customs, pilots, and a bunch of stern looking people at the gate.&lt;/p&gt;

&lt;figure&gt;
&lt;img src=&quot;https://imgur.com/XqAvb58.jpg&quot; /&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;small&gt;A wood stove should never be placed in your overhead bin, whether in whole or part.&lt;/small&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I made it back to Boston, dropped of Grannie, rebuilt our woodstove, got the fire going, and headed to Vancouver on a series of red-eye flights through Newark and Minneapolis. As you might expect, this was one 48-hour long nightmare. In Vancouver, I took the &lt;a href=&quot;https://en.wikipedia.org/wiki/SkyTrain_(Vancouver)&quot;&gt;SkyTrain&lt;/a&gt; downtown, planned to use Car2Go, but due to earlier shenanigans in Frankfurt, Car2Go believed I was in Germany and needed to update my license. I realized this only after purchasing a boatload of groceries. It would take 24 hours to reactivate.&lt;/p&gt;

&lt;p&gt;With groceries and luggage in hand, I ran around downtown Vancouver trying to hail a taxi. Little did I know, taxis there do not stop for grocery-toting, flailing pedestrians, nor do they accept credit cards. And I do not carry cash, or use SIM cards, because I am an idiot. Several hours later, I found a bank to withdraw cash, and boarded a bus to North Vancouver, dropped off the groceries, called Car2Go, and collapsed into a deep slumber.&lt;/p&gt;

&lt;p&gt;When I awoke it was nearly midnight. Luckily, Car2Go had resolved the license issue while I was asleep, allowing me to drive their golf carts again. So I ran half a kilometer to the nearest Car2Go and floored it all the way to the airport to meet my girlfriend, who was just then arriving from Chernobyl. On past occasions I have put Cars2Go to very effective use, however this was simply not the case in Canada.&lt;/p&gt;

&lt;p&gt;For reasons I cannot begin to explain, we were locked inside a malfunctioning Car2Go at a gas station. We were stuck in park at a busy intersection. We were fined for alleged parking violations. We had to call for help dozens of times, and spent hours troubleshooting their broken fleet of golf carts. Car-sharing is clearly a win in some places, but does not work well in Canada. End rant.&lt;/p&gt;

&lt;p&gt;I went to Vancouver for ConFoo, since I enjoyed the one in February so much. It was their first time in Vancouver, and a lovely conference, filled with lovely people. Afterwards, they bussed a few of us up to Whistler and we all went skiing for two days. Met some swell folks between runs, and we talked about science, religion and the &lt;a href=&quot;https://en.wikipedia.org/wiki/Post-truth_politics&quot;&gt;post-truth society&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;From Vancouver, we flew to Toronto and spent a few days visiting friends there. I had amazing borscht at &lt;a href=&quot;http://gayleyscafe.com/&quot;&gt;Gayleys Cafe&lt;/a&gt;. I read a great book, called the &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Three-Body_Problem&quot;&gt;The Three Body Problem&lt;/a&gt;. Then we took a train to Ottawa. Spent a few days visiting more friends, nearly dying of frostbite. Took the train to Montreal. Then I came home for the holidays and spent Christmas day in a hospital because Grannie came down with pneumonia. She’s one tough cookie. We’re hoping for good news.&lt;/p&gt;

&lt;p&gt;When all is said and done, I went to 18 countries, 64 cities, 16 conferences, and visited dozens of universities and meetups in 2016. If I had to do it all over again, I wouldn’t do everything the same way. I spent most of the time exhausted and jetlagged. But I also had some very happy memories, particularly those that did not involve nearly dying. And I got to spend time with some extraordinary people along the way. So I’ll mark it with a B+.&lt;/p&gt;

&lt;p&gt;If you made it this far, I feel compelled to leave you with some sort of message. The best tales have lessons, answers, endings. But my answers are not the ones you are seeking, and even if they were, they wouldn’t do you much good anyhow. There is a great big world outdoors, and if you have the desire to see it, then I would strongly encourage you to do so (you will not regret it). But don’t try to bring 200kg of cast iron along with you.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This story was made possible by the patience of my family. If you enjoyed reading it, please consider giving a hug to your Grannie, or someone you love.&lt;/em&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Democratizing Education in China</title>
   <link href="breandan.net/2016/04/13/equal-education-in-china/"/>
   <updated>2016-04-13T00:00:00+00:00</updated>
   <id>breandan.net/2016/04/13/equal-education-in-china</id>
   <content type="html">&lt;p&gt;In former president Hu Jintao’s address to the 17th Party Congress in 2007, he urges delegates to, “enhance our nation’s cultural soft power,”&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;  citing China’s, “5,000 Years of Culture”, an immense source of national pride for billions of Chinese people around the world. In recent comments, current Party Secretary Wang Qishan appeals to this legacy stating, “The Party’s legitimacy lies in history, its popular support and the mandate of the people.”&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;  But the strength of a great civilization is not in numbers, or how far its borders reach, but according to Ghandi, in how it treats the weakest members of society.&lt;/p&gt;

&lt;p&gt;During President Xi Jinping’s 2015 visit to the United States, he called attention to this demographic, acknowledging, “over 70 million Chinese citizens living on guaranteed minimum income, and over 85 million people with disabilities.”&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;  The Chinese Dream, a recurring theme of Xi’s presidency, emphasizes economic prosperity and military strength, but despite these promises, services for the disabled are severely lacking throughout mainland China.&lt;sup id=&quot;fnref:4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;sup&gt;,&lt;/sup&gt;&lt;sup id=&quot;fnref:5&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:5&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;  According to some statistics, 28% of disabled children lack access to basic education and over 40% of China’s disabled are illiterate.&lt;sup id=&quot;fnref:4:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;These figures are not merely provisional lapses of welfare in a developing economy, but signs of an endemic problem in mainland China. Not only are disabled citizens overlooked by government services, but many are actively discriminated by primary schools, barred from receiving higher education through mandatory physical examinations, and disqualified from certain vocations based on physical “defects”.&lt;sup id=&quot;fnref:4:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; Where special education is available, students are segregated from their peers and often forced to travel long distances for equal access.&lt;sup id=&quot;fnref:4:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; These are insurmountable obstacles for millions of rural citizens.&lt;/p&gt;

&lt;p&gt;Even if these obstacles were lifted overnight, China faces steep social and economic barriers to equal rights. But there is real hope for technological innovation in paving the road to equal opportunity. With the emergence of new digital platforms like massive online open courses (MOOCs) and the widespread accessibility of assistive technologies for digital communication, we can disrupt the crippling economic disincentive that traps millions of disabled citizens in poverty and give them tools to become contributing and valued members of society. And with the growth of telepresence software and flexible work environments, as China transitions into a service economy, mobilizing these individuals in a technology-enabled workforce will become more practical than ever before.&lt;/p&gt;

&lt;p&gt;The key to making rapid progress in disability services is by investing in technology, not politics. Today, we can give sight to the blind, subtitles to the deaf, voices to the language-impaired, and adaptive input systems to the physically handicapped, all with software that can run on a wristwatch. We can transform early childhood education through interactive speech recognition, and radically improve higher education through online learning initiatives. By investing in usability, democratizing access to a basic education, and driving down the barriers economic prosperity, we can help make the dream of a stronger, healthier China a real possibility for individuals from all walks of life.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;“…必须提高国家文化软实力…” Full text of Hu Jintao’s report at 17th Party Congress. (2007). &lt;a href=&quot;http://np.chineseembassy.org/eng/ChinaABC/t377776.htm&quot;&gt;http://np.chineseembassy.org/eng/ChinaABC/t377776.htm&lt;/a&gt; &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;“中国共产党的合法性源自于历史, 是人心向背决定的, 是人民的选择.” The Party and the World Dialogue. (2015). &lt;a href=&quot;http://news.sina.com.cn/c/2015-09-10/232332296609.shtml&quot;&gt;https://news.sina.com.cn/c/2015-09-10/232332296609.shtml&lt;/a&gt; &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;“中国城乡有7000多万低保人口, 还有8500多万残疾人.” From a speech on China-U.S. relations. (2015). &lt;a href=&quot;http://news.xinhuanet.com/english/2015-09/24/c_134653326.htm&quot;&gt;https://news.sina.com.cn/c/2015-09-10/232332296609.shtml&lt;/a&gt; &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;“Barriers to Education for Persons with Disabilities in China.” Human Rights Watch. (2013). &lt;a href=&quot;http://www.hrw.org/report/2013/07/15/long-they-let-us-stay-class/barriers-education-persons-disabilities-china&quot;&gt;https://www.hrw.org/report/2013/07/15/long-they-let-us-stay-class/barriers-education-persons-disabilities-china&lt;/a&gt; &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt; &lt;a href=&quot;#fnref:4:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; &lt;a href=&quot;#fnref:4:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt; &lt;a href=&quot;#fnref:4:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;sup&gt;4&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:5&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;“Paper commissioned for the EFA Global Monitoring Report 2006, Literacy for Life.” Ross. (2006). &lt;a href=&quot;http://unesdoc.unesco.org/images/0014/001461/146108e.pdf&quot;&gt;https://unesdoc.unesco.org/images/0014/001461/146108e.pdf&lt;/a&gt; &lt;a href=&quot;#fnref:5&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Democratizing Learning Technology</title>
   <link href="breandan.net/2015/10/11/why-education-matters/"/>
   <updated>2015-10-11T00:00:00+00:00</updated>
   <id>breandan.net/2015/10/11/why-education-matters</id>
   <content type="html">&lt;p&gt;Growing up in rural New Hampshire, the world is a small place. Our nearest neighbors lived miles away, and you could drive for hours before seeing anything like a city. My grandparents moved out of New York in the 1960s, and raised me in a single-family home thirty years later. They would stoke the fire at night and tell me stories of places where buildings rose a hundred stories tall and trains ran underground. We would read newspapers by candlelight, and day by day, the world grew a bit larger.&lt;/p&gt;

&lt;p&gt;It is a little unreal to think of how much the world has changed these last few years. Today, we have self-driving cars and information superhighways, smartphones and social networks, but in many ways we are further from our neighbors than ever before. As a computer science major, I understand the vital importance of technology in today’s connected society. As a student and software engineer traveling to developing countries like China, I have watched that same technology leave many behind. I know we can do better.&lt;/p&gt;

&lt;p&gt;Growing up with a mentally disabled person helps you appreciate the little things. Like reading. We may take it for granted, but reading is a gift that opens doors into another world, shut to those who cannot read. Yet by some estimates, over a quarter of the world’s adult population is unable to read a book. This needs to change, and quickly. We have the technology to completely eradicate adult illiteracy for children born after 2010, even without access to schools or internet. And now more than ever, we need literate citizens of the world.&lt;/p&gt;

&lt;p&gt;In the software industry, far too much talent is squandered on frivolous things like selling ads and sharing selfies. And far too much effort is spent exploiting those who do not understand technology, rather than educating the ones who need it most. In the industrial revolution, child labor grew to an all-time high, despite promises of giving young people more time to pursue an education. Likewise, today’s technology can be a tool to empower and enlighten, but is often used to persuade and preoccupy those who are most susceptible to its influence.&lt;/p&gt;

&lt;p&gt;After college, I was lucky to find fulfilling work that allowed me to repay my student loans and provide for the family who raised me. But I am often reminded of those more gifted than I, who are unable to do so for circumstances beyond their control. Who must take unfulfilling jobs to feed their families. Who lack the necessary means to attend school. Who have no one to call a family. I know that if those people could have the same opportunities I have enjoyed – if they could meet the same people I have met, the world would be a much better place.&lt;/p&gt;

&lt;p&gt;Our history is full of men and women who were at the right place and the right time. Who were given the right combination of resources and opportunity to effect lasting change. But far more, are those who were never given the opportunity to put their talents to use – held back because they could not read or marginalized by a society that could not spare the time to teach these children. It is said the true measure of a civilization is how it treats the least of its citizens. I believe today, that truth is more important than ever before.&lt;/p&gt;

&lt;p&gt;Today, we are uniquely equipped with the technology to give millions of children a world-class education – technology that can hold conversations, teach foreign languages and do simultaneous translation, with devices that fit on a child’s wrist. Today, we are standing at a turning point in human history. In &lt;a href=&quot;https://www.reddit.com/r/science/comments/3nyn5i/science_ama_series_stephen_hawking_ama_answers/cvsdmkv&quot;&gt;recent comments&lt;/a&gt;, Stephen Hawking, a physicist and distinguished beneficiary of assistive technology, predicts two possible futures. One, where society is elevated by technology - where knowledge and opportunity is abundant and freely given. But there is a second future, where only the privileged few - those endowed with the talents and resources to outrun the accelerating pace of technology can enjoy the prosperity and wellbeing it confers. We cannot allow this future to exist.&lt;/p&gt;

&lt;p&gt;We have the technology to radically transform education in developing countries, where millions of children are learning English and foreign languages. We have the ability to teach languages in a completely different way, with machine learning and speech recognition. And we have the responsibility to use these tools to help cultivate the minds of young people around the world, regardless of their intellectual abilities. Providing a quality education to the underprivileged and disabled is one of the most pressing issues of our time, and one that I am committed to solving.&lt;/p&gt;

&lt;p&gt;Further Reading&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://pdfs.semanticscholar.org/372b/826c8164dc48ef4d1f93e9cf69b8a40f137b.pdf&quot;&gt;Technology and Equity in Schooling: Deconstructing the Digital Divide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>A Short History of Shorthand</title>
   <link href="breandan.net/2015/02/01/shorthand/"/>
   <updated>2015-02-01T00:00:00+00:00</updated>
   <id>breandan.net/2015/02/01/shorthand</id>
   <content type="html">&lt;p&gt;From early recorded history, &lt;em&gt;stenography&lt;/em&gt;, or shorthand has been used to translate oral information onto paper, which was later transcribed into a legible medium for publication. This process was often a painstaking one, requiring specialized knowledge to read and translate. In the process of transcribing spoken language, conventions took root and new words emerged, giving rise to &lt;em&gt;literature&lt;/em&gt;. Today, many of the words we have at our disposal are products of stenography - yet despite its historical importance, stenography is a forgotten art.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/caoshu.jpg&quot; /&gt;&lt;/p&gt;

&lt;div class=&quot;quote&quot;&gt;&lt;blockquote&gt;&lt;b&gt;Night Mooring at Maple Bridge&lt;/b&gt; – Zhang Ji, A.D. 730-780&lt;br /&gt;
The moon is setting, a crow caws in the frosty night air&lt;br /&gt;
Beneath the river maples, fishing lanterns flicker and sway&lt;br /&gt;
And beyond these city walls, from the temple on Cold Mountain&lt;br /&gt;
The midnight bell is tolling, for me in restless slumber.&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;One of the early reasons for stenography was limited resources - primarily time, although tortoises&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; and teachers were not in steady supply. Early authors were “bandwidth limited”, forcing them to condense their vocabulary in order to efficiently refer to common phrases. Today we enjoy many of their typographical innovations, such as ampersands, acronyms, and more recently, hashtags. While these conventions may have once shared frugal origins, &lt;span class=&quot;has-pullquote&quot; data-pullquote=&quot;The ability to simplify means to eliminate the unnecessary so that the necessary may speak. —Hans Hofmann&quot;&gt;&lt;/span&gt;we are quite happy to maintain them out of familiarity - for our readers’ sake, but as we soon realized, increasingly for our own benefit as well.&lt;/p&gt;

&lt;p&gt;It turns out – perhaps unsurprisingly – as we started using more abbreviations, they began to take up permanent quarters in our own vernacular. Whereas Laser&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; and Radar&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; may have been deliberate interventions, many acronyms are more benign, eg. ASAP, A.D., B&amp;amp;B, ETA, FAQ, IQ, Q&amp;amp;A, RSVP. Some more contemporary slang can be easily deciphered based on its context and frequency, eg. AFAIK, FWIW, IMHO, IIRC. You may recall a moment of brief happiness when recognizing a new shorthand and then using it to communicate with another human being. This is not abnormal.&lt;/p&gt;

&lt;p&gt;&lt;span class=&quot;mathquote&quot;&gt;\(\begin{align}
\int_0^{10} 6x^4 dx &amp;amp;= \left.\frac{6}{5}x^5\right|_0^{10} \\
&amp;amp;=\frac{6}{5}(10)^5 \\
&amp;amp;=1.2\times10^5
\end{align}\)&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;With the advent of terabyte HDDs and modern CPUs, one might imagine the structure of text alone would become less important - if shorthand were simply a means of abbreviation, then we should have little need for it today. But all along, the goal was never really conservation of ink and parchment, but the conservation of ideas. Far too many good ideas have been lost in a sea of poor notation&lt;sup id=&quot;fnref:4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;. Notation allows us to quickly employ declarative and procedural memories with the same ease which they come to mind. By standardizing their usage, we are able to communicate more effectively.&lt;/p&gt;

&lt;p&gt;&lt;span class=&quot;mathquote&quot;&gt;\(\begin{align*}
    x \in V &amp;amp; \Rightarrow x \in \Lambda \\
    M, N \in \Lambda &amp;amp; \Rightarrow (M N) \in \Lambda \\
    M \in \Lambda,\, x \in V &amp;amp; \Rightarrow (\lambda x M) \in \Lambda
\end{align*}\)&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Notation can also change how we think. Alonzo Church’s λ-calculus is one example of notation that changed not only just nomenclature, but usage as well. In the 1930s, Church developed a notation for describing computable functions called a &lt;em&gt;lambda expression&lt;/em&gt;. Today we think of λ-expressions as a kind of shorthand for defining &lt;a href=&quot;https://en.wikipedia.org/wiki/Anonymous_function&quot;&gt;anonymous functions&lt;/a&gt;. More importantly, λ-calculus treats functions and data as the same and provides an alternative model of computation through &lt;em&gt;substitution&lt;/em&gt;. While equivalent to the procedural model, it can lead to vastly different (and often far simpler) solutions to the same problem.&lt;/p&gt;

&lt;figure&gt;
&lt;img src=&quot;/public/folding_lambda.gif&quot; /&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;small&gt;Translating a λ-expression in Java. Objects in editor are closure than they appear.&lt;/small&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Today there are many writing systems which share a number of interesting similarities with traditional stenography. For example, &lt;a href=&quot;https://docs.emmet.io/&quot;&gt;Emmet&lt;/a&gt; is a shorthand for typing HTML. IntelliJ IDEA has a similar system of &lt;a href=&quot;https://www.jetbrains.com/idea/help/live-templates.html&quot;&gt;macros&lt;/a&gt; and &lt;a href=&quot;https://www.jetbrains.com/idea/docs/IntelliJIDEA_ReferenceCard.pdf&quot;&gt;keyboard shortcuts&lt;/a&gt; for automating repetitive programming tasks. Some television subtitles are now generated with a supervised speech recognizer&lt;sup id=&quot;fnref:5&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:5&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;. And many handheld
&lt;span class=&quot;leftquote&quot;&gt;&lt;img src=&quot;/public/ime.png&quot; /&gt;&lt;small&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Character_amnesia&quot;&gt;Character amnesia&lt;/a&gt; is a growing problem in Asia.&lt;/small&gt;&lt;/span&gt;devices have predictive keyboards, which use &lt;a href=&quot;http://setosa.io/blog/2014/07/26/markov-chains/index.html&quot;&gt;Markov chains&lt;/a&gt; to suggest the next letter or word in a sentence. All of these are modern examples of stenography, yet they are radically different in form and function.&lt;/p&gt;

&lt;p&gt;This uncoupling between the creation and representation of text raises a number of intriguing questions. With the sudden ease of which we can create new abstractions and programming shorthands through macros, polymorphism and reflection, what is the appropriate level of notation required for a particular task? With the availability of code generation tools that write code, type systems for verification, and powerful IDEs to understand how it fits together, how do we differentiate between &lt;em&gt;source&lt;/em&gt; and &lt;em&gt;target&lt;/em&gt;? And who, or what, is the audience? These are not new questions&lt;sup id=&quot;fnref:6&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:6&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;, but their significance today has only become more apparent.&lt;/p&gt;

&lt;figure&gt;
&lt;img src=&quot;/public/mps.png&quot; /&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;small&gt;Some editors like MPS treat text as an intermediate format, rather than the &quot;source&quot;. This enables some degree of flexibility in the composition and presentation of code.&lt;/small&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Let us consider a few examples. Conciseness is one desirable property in language design, although achieving it while maintaining precision is often quite challenging. Even in Java, one of the most carefully guarded&lt;sup id=&quot;fnref:7&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:7&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;7&lt;/a&gt;&lt;/sup&gt; programming languages today, new language features have created the potential for ambiguous code. &lt;a href=&quot;https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.13.1&quot;&gt;Method references&lt;/a&gt; are a shorthand in Java 1.8 whose simplicity apparently outweighed the potential ambiguity.&lt;/p&gt;

&lt;figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;no&quot;&gt;R&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;foo&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;bar&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;no&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;OK&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//Prints &quot;OK&quot;&lt;/span&gt;

        &lt;span class=&quot;no&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;Foo:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;//Compile error: reference to bar is ambiguous&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;caption&gt;
&lt;small&gt;Does &lt;code&gt;Foo::bar&lt;/code&gt; refer the instance method &lt;code&gt;bar()&lt;/code&gt; or the static &lt;code&gt;bar(Foo foo)&lt;/code&gt;?&lt;/small&gt;
&lt;/caption&gt;
&lt;/figure&gt;

&lt;p&gt;In Kotlin, there are &lt;a href=&quot;https://blog.jetbrains.com/kotlin/2013/06/static-constants-in-kotlin/&quot;&gt;no static members&lt;/a&gt;, making this somewhat less of an issue. However unlike Java, which is capable of distinguishing method references based on the type signature, Kotlin does not support ambiguous method references (ie. &lt;a href=&quot;http://kotlinlang.org/docs/reference/reflection.html#function-references&quot;&gt;function references&lt;/a&gt;) to overloaded functions. It should be noted that while it is not possible to resolve ambiguous method references in Java without altering the syntax, disambiguating overloaded functions in Kotlin ought to be relatively straightforward.&lt;/p&gt;

&lt;figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot; data-lang=&quot;kotlin&quot;&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;bar&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;f1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)}&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;invoke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;OK&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//Prints &quot;OK&quot;&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;f2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//Compile error: Overload resolution ambiguity&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;caption&gt;
&lt;small&gt;Does &lt;code&gt;::foo&lt;/code&gt; refer to the &lt;a href=&quot;https://en.wiktionary.org/wiki/niladic&quot;&gt;niladic&lt;/a&gt; or monadic &lt;code&gt;foo&lt;/code&gt;? The λ parameter gives us a clue.&lt;/small&gt;
&lt;/caption&gt;
&lt;/figure&gt;

&lt;p&gt;We can see how removing certain elements of notation may occasionally lead to  ambiguity. Likewise, by adding notation we can also gain additional expressiveness and precision. For example, &lt;em&gt;annotations&lt;/em&gt; in Java 1.5&lt;sup id=&quot;fnref:8&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:8&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;. Java has added a small number of language features and keywords since its inception, including &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enum&lt;/code&gt;&lt;sup id=&quot;fnref:9&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:9&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;9&lt;/a&gt;&lt;/sup&gt;. But perhaps one of the best examples of this can be found in a typesetting language called \(\TeX\).&lt;/p&gt;

&lt;figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-tex&quot; data-lang=&quot;tex&quot;&gt;&lt;span class=&quot;k&quot;&gt;\overbrace&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;  (r&lt;span class=&quot;p&quot;&gt;_&lt;/span&gt;1 + r&lt;span class=&quot;p&quot;&gt;_&lt;/span&gt;2  + &lt;span class=&quot;k&quot;&gt;\cdots&lt;/span&gt; + r&lt;span class=&quot;p&quot;&gt;_&lt;/span&gt;w)&lt;span class=&quot;p&quot;&gt;^&lt;/span&gt;v =   &lt;span class=&quot;p&quot;&gt;}^{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\text&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;1&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\underbrace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;\sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;_{&lt;/span&gt;k&lt;span class=&quot;p&quot;&gt;_&lt;/span&gt;1 + k&lt;span class=&quot;p&quot;&gt;_&lt;/span&gt;2 + &lt;span class=&quot;k&quot;&gt;\cdots&lt;/span&gt; + k&lt;span class=&quot;p&quot;&gt;_&lt;/span&gt;w=v&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}_{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\text&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;2&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\overbrace&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;  v &lt;span class=&quot;k&quot;&gt;\choose&lt;/span&gt; k&lt;span class=&quot;p&quot;&gt;_&lt;/span&gt;1, k&lt;span class=&quot;p&quot;&gt;_&lt;/span&gt;2, &lt;span class=&quot;k&quot;&gt;\ldots&lt;/span&gt;, k&lt;span class=&quot;p&quot;&gt;_&lt;/span&gt;w   &lt;span class=&quot;p&quot;&gt;}^{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\text&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;3&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\underbrace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;\prod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;_{&lt;/span&gt;1&lt;span class=&quot;k&quot;&gt;\le&lt;/span&gt; t&lt;span class=&quot;k&quot;&gt;\le&lt;/span&gt; w&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;r&lt;span class=&quot;p&quot;&gt;_{&lt;/span&gt;t&lt;span class=&quot;p&quot;&gt;}^{&lt;/span&gt;k&lt;span class=&quot;p&quot;&gt;_{&lt;/span&gt;t&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;}_{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\text&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;4&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;caption&gt;
$$
\overbrace {  (r_1 + r_2  + \cdots + r_w)^v =   }^{\text  {1}}
\underbrace{  \sum_{k_1 + k_2 + \cdots + k_w=v} }_{\text  {2}}
\overbrace {  v \choose k_1, k_2, \ldots, k_w   }^{\text  {3}}
\underbrace{  \prod_{1\le t\le w}r_{t}^{k_{t}}  }_{\text  {4}}
$$
&lt;/caption&gt;
&lt;/figure&gt;

&lt;p&gt;\(\TeX\) was conceived in the late 1970s by Donald Knuth&lt;sup id=&quot;fnref:10&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:10&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;10&lt;/a&gt;&lt;/sup&gt;, prior to the era of IDEs and modern text editors. It consists of a set of commands that exactly specify the visual arrangement of text on a page, and has been used for this purpose in academic circles for nearly four decades. Despite its popularity, \(\TeX\)has remained largely unchanged over that time, owing in part to a flexible system of macros&lt;sup id=&quot;fnref:11&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:11&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;11&lt;/a&gt;&lt;/sup&gt;. Macros (short for &lt;a href=&quot;https://en.wikipedia.org/wiki/Macro_instruction&quot;&gt;macro instructions&lt;/a&gt;), are a substitution rule for replacing text, which in \(\TeX\)’s case, occurs during compilation.&lt;/p&gt;

&lt;figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-tex&quot; data-lang=&quot;tex&quot;&gt;&lt;span class=&quot;k&quot;&gt;\def\smz&lt;/span&gt;#1#2&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;  #1&lt;span class=&quot;p&quot;&gt;_&lt;/span&gt;1 + #1&lt;span class=&quot;p&quot;&gt;_&lt;/span&gt;2 + &lt;span class=&quot;k&quot;&gt;\cdots&lt;/span&gt; + #1&lt;span class=&quot;p&quot;&gt;_&lt;/span&gt;#2  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\def\sqt&lt;/span&gt;#1#2&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;  #1&lt;span class=&quot;p&quot;&gt;_&lt;/span&gt;1,  #1&lt;span class=&quot;p&quot;&gt;_&lt;/span&gt;2,  &lt;span class=&quot;k&quot;&gt;\ldots&lt;/span&gt;,  #1&lt;span class=&quot;p&quot;&gt;_&lt;/span&gt;#2  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\def\pdx&lt;/span&gt;#1#2&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;\prod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;_{&lt;/span&gt; 1 &lt;span class=&quot;k&quot;&gt;\le&lt;/span&gt; #1&lt;span class=&quot;k&quot;&gt;\le\ &lt;/span&gt;#2 &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;     &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\overbrace&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;         (  &lt;span class=&quot;k&quot;&gt;\smz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;r&lt;span class=&quot;p&quot;&gt;}{&lt;/span&gt;w&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;  )&lt;span class=&quot;p&quot;&gt;^&lt;/span&gt;v =  &lt;span class=&quot;p&quot;&gt;}^{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\text&lt;/span&gt;       &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;1&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\underbrace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;\sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;_{&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;\smz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;k&lt;span class=&quot;p&quot;&gt;}{&lt;/span&gt;w&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;=v  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;}_{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\text&lt;/span&gt;       &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;2&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\overbrace&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;  v &lt;span class=&quot;k&quot;&gt;\choose&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;\sqt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;k&lt;span class=&quot;p&quot;&gt;}{&lt;/span&gt;w&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;         &lt;span class=&quot;p&quot;&gt;}^{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\text&lt;/span&gt;       &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;3&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\underbrace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;\pdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;t&lt;span class=&quot;p&quot;&gt;}{&lt;/span&gt;w&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; r&lt;span class=&quot;p&quot;&gt;_{&lt;/span&gt;t&lt;span class=&quot;p&quot;&gt;}^{&lt;/span&gt; k&lt;span class=&quot;p&quot;&gt;_{&lt;/span&gt;t&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;}_{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\text&lt;/span&gt;       &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;4&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;caption&gt;
$$
\def\smz#1#2{  #1_1 + #1_2 + \cdots + #1_#2  }
\def\sqt#1#2{  #1_1,  #1_2,  \ldots,  #1_#2  }
\def\pdx#1#2{  \prod_{ 1 \le #1\le\ #2 }     }

\overbrace {         (  \smz{r}{w}  )^v =  }^{\text       {1}}
\underbrace{    \sum_{  \smz{k}{w}=v  }    }_{\text       {2}}
\overbrace {  v \choose \sqt{k}{w}         }^{\text       {3}}
\underbrace{  \pdx{t}{w} r_{t}^{ k_{t} }   }_{\text       {4}}
$$
&lt;/caption&gt;
&lt;/figure&gt;

&lt;p&gt;In &lt;a href=&quot;https://en.wikipedia.org/wiki/Automatic_programming&quot;&gt;automatic programming&lt;/a&gt;, macros are not an uncommon feature - the C preprocessor performs lexical substitution prior to compilation. IDEs and text editors offer increasingly sophisticated keyboard macros under various names (eg. templates, macros, autocorrection). And many build tools incorporate &lt;a href=&quot;http://maven.apache.org/plugins/maven-javadoc-plugin/&quot;&gt;document generators&lt;/a&gt; and &lt;a href=&quot;https://gradle.org/docs/current/javadoc/org/gradle/api/tasks/AbstractCopyTask.html#expand(java.util.Map)&quot;&gt;string expansions&lt;/a&gt; that substitute and rewrite portions of source code. &lt;span class=&quot;has-pullquote&quot; data-pullquote=&quot;Programs must be written for people to read, and only incidentally for machines to execute. -Harold Abelson&quot;&gt;&lt;/span&gt;In a way, this gives programmers the ability to take notation into their own hands. It is unclear whether this is a good idea.&lt;/p&gt;

&lt;p&gt;The key, it seems, to make automatic programming work is readability. In a perfect world, we might never have to write a single line of code twice. But perhaps what we should really be working towards, is not necessarily the conservation of keystrokes, but rather the conservation of ideas through effective notation. For all the time we spend writing code, albeit plenty, is dwarfed by the amount of time others spend trying to understand it (and failing to do so, spin off their own version with the same reckless abandon we poured into the first).&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;Did you know?&lt;/em&gt; Frank Liang spent five years&lt;sup id=&quot;fnref:12&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:12&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;12&lt;/a&gt;&lt;/sup&gt; studying a better hyphenation algorithm for \(\TeX\)&lt;sup id=&quot;fnref:13&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:13&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;13&lt;/a&gt;&lt;/sup&gt;. Assuming Liang’s Algorithm has saved two minutes per year for each of a million readers (in academic journals, textbooks and CVs), Liang has singlehandedly saved over a century.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While the process of rapidly writing code is well-attended, the limiting factor in developer productivity is not the bandwidth of our fingertips on keys, but rather the attention span it takes to process their collective output. This is evident on a large scale in commercial code reviews, but also on an individual level, in the time it takes to effectively learn a new language or framework. It is not unreasonable to imagine how an upfront investment in readability could result in a hundredfold savings in time spread over a large userbase.&lt;/p&gt;

&lt;p&gt;With this in mind, we should think of programming as an exercise in good notation. Notation matters - but not because it is easier for us to write. It is often convenient to choose a notation that our team is most familiar with, or with the most votes votes on HN. But if we succeed, we will not be the only ones maintaining it in ten years. So experiment. And when you have a good idea, spare no effort to make it plain.&lt;/p&gt;

&lt;h3 id=&quot;further-reading&quot;&gt;Further Reading&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Ye, Katherine. (2016, July 22). &lt;a href=&quot;https://github.com/hypotext/notation&quot;&gt;Notes on notation and thought&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h3&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Oracle bone script. (2015, January 17). Wikipedia, The Free Encyclopedia. &lt;a href=&quot;https://en.wikipedia.org/w/index.php?title=Oracle_bone_script&amp;amp;oldid=642840965&quot;&gt;https://en.wikipedia.org/w/index.php?title=Oracle_bone_script&lt;/a&gt;. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Gould, R. Gordon (1959). “The LASER, Light Amplification by Stimulated Emission of Radiation”. In Franken, P.A. and Sands, R.H. (Eds.). The Ann Arbor Conference on Optical Pumping, the University of Michigan, 15 June through 18 June 1959. p. 128. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Radar. (2015, January 30). Wikipedia, The Free Encyclopedia. &lt;a href=&quot;https://en.wikipedia.org/w/index.php?title=Radar&amp;amp;oldid=644873164&quot;&gt;https://en.wikipedia.org/w/index.php?title=Radar&lt;/a&gt;. &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Although even average ones have stayed afloat with good notation. &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:5&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Imai, Toru. (2012). “&lt;a href=&quot;https://www.nhk.or.jp/strl/publica/bt/en/fe0048-2.pdf&quot;&gt;Speech Recognition for Real-time Closed Captioning&lt;/a&gt;,” Broadcast Technology No. 48, pp.1-9. &lt;a href=&quot;#fnref:5&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:6&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Wesch, M. (2007, January 31). Web 2.0. The machine is us/ing us [Video file]. Retrieved from &lt;a href=&quot;https://www.youtube.com/watch?v=NLlGopyXT_g&quot;&gt;https://www.youtube.com/watch?v=NLlGopyXT_g&lt;/a&gt;. &lt;a href=&quot;#fnref:6&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:7&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Goetz, B. (2007, January 31). Stewardship: The sobering parts [Video file]. Retrieved from &lt;a href=&quot;https://www.youtube.com/watch?v=2y5Pv4yN0b0&quot;&gt;https://www.youtube.com/watch?v=2y5Pv4yN0b0&lt;/a&gt;. &lt;a href=&quot;#fnref:7&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:8&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Java annotation (History). (2015, January 20). Wikipedia, The Free Encyclopedia. &lt;a href=&quot;https://en.wikipedia.org/wiki/Java_annotation#History&quot;&gt;https://en.wikipedia.org/wiki/Java_annotation#History&lt;/a&gt;. &lt;a href=&quot;#fnref:8&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:9&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Java language keywords. Oracle Corporation. &lt;a href=&quot;http://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html&quot;&gt;https://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html&lt;/a&gt; &lt;a href=&quot;#fnref:9&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:10&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Author and computer scientist at Stanford University, more famously known for writing &lt;em&gt;&lt;a href=&quot;https://www-cs-faculty.stanford.edu/~uno/taocp.html&quot;&gt;The Art of Computer Programming&lt;/a&gt;&lt;/em&gt;. &lt;a href=&quot;#fnref:10&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:11&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Knuth, D. E. (1986). Definitions (also called Macros). The TeXbook. &lt;a href=&quot;http://www.ctex.org/documents/shredder/src/texbook.pdf&quot;&gt;https://web.mit.edu/jgross/www/LaTeX/texbook.pdf&lt;/a&gt;. &lt;a href=&quot;#fnref:11&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:12&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Liang, F. M. (2010). Interview. &lt;a href=&quot;http://tug.org/interviews/liang.pdf&quot;&gt;http://tug.org/interviews/liang.pdf&lt;/a&gt;. &lt;a href=&quot;#fnref:12&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:13&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Liang, F. M. (1983). Word Hy-phen-a-tion by Com-put-er (Doctoral dissertation, Stanford University). &lt;a href=&quot;https://www.tug.org/docs/liang/liang-thesis.pdf&quot;&gt;https://www.tug.org/docs/liang/liang-thesis.pdf&lt;/a&gt; &lt;a href=&quot;#fnref:13&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>IntelliJ IDEA on Linux</title>
   <link href="breandan.net/2014/08/18/shell-script/"/>
   <updated>2014-08-18T00:00:00+00:00</updated>
   <id>breandan.net/2014/08/18/shell-script</id>
   <content type="html">&lt;p&gt;The following script installs a JetBrains IDE on any &lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_Linux_distributions#Debian-based&quot;&gt;Debian based Linux distro&lt;/a&gt;. To download it, simply run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wget z.ndan.co/jetbrains-install.sh&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/sh&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# We need root to install&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;0&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Elevating to root...&quot;&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;exec sudo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$@&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Prompt for edition&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;while &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
   &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Please select from one of the following choices:
   [1] IntelliJ IDEA Community Edition
   [2] IntelliJ IDEA Ultimate Edition
   [3] PyCharm Community Edition
   [4] PyCharm Professional Edition
   [5] CLion
   [6] WebStorm
   [7] RubyMine
   [8] PhpStorm
   [9] DataGrip
  &amp;gt; &quot;&lt;/span&gt; CODE
   &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CODE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in
       &lt;/span&gt;1 &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;CODE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;IIC&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;IDE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;idea&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
       2 &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;CODE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;IIU&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;IDE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;idea&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
       3 &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;CODE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;PCC&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;IDE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;pycharm&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
       4 &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;CODE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;PCP&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;IDE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;pycharm&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
       5 &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;CODE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;CL&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;nv&quot;&gt;IDE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;clion&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
       6 &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;CODE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;WS&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;nv&quot;&gt;IDE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;webstorm&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
       7 &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;CODE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;RM&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;nv&quot;&gt;IDE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;rubymine&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
       8 &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;CODE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;PS&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;nv&quot;&gt;IDE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;phpstorm&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
       9 &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;CODE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;DG&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;nv&quot;&gt;IDE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;datagrip&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;esac&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;done

&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Installing &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IDE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;...&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Prepend base URL for download&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://data.services.jetbrains.com/products/download?platform=linux&amp;amp;code=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$CODE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Get location header for file URL&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;HEADERS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;wget &lt;span class=&quot;nt&quot;&gt;-qS&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--max-redirect&lt;/span&gt; 0 &lt;span class=&quot;nt&quot;&gt;--spider&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$URL&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; 2&amp;gt;&amp;amp;1&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;LOCATION&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HEADERS&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;tac&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; 1 &lt;span class=&quot;s2&quot;&gt;&quot;Location: &quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;FILE_URL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$LOCATION&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/.*Location: //&apos;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;VERSION&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FILE_URL&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-En&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/.*\/(.*).tar.gz/\1/p&apos;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;File to be downloaded: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FILE_URL&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Latest stable version: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$VERSION&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Set install directory&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;INSTALL_DIR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/opt/&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$VERSION&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Check if latest version has been installed&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$INSTALL_DIR&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
   &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Found an existing install directory: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$INSTALL_DIR&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$VERSION&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; may have previously been installed.&quot;&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;while &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
       &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Would you like to reinstall? (Y/N) &amp;gt; &quot;&lt;/span&gt; REPLY
       &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$REPLY&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
           &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;yY] &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Reinstalling &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$VERSION&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;...&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
           &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;nN] &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Aborted install.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;1&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
       &lt;span class=&quot;k&quot;&gt;esac&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;done
fi&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Set download directory&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;DEST_DIR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mktemp&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Download binary&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Downloading &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$VERSION&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; from &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FILE_URL&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; to &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$DEST_DIR&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
wget &lt;span class=&quot;nt&quot;&gt;-cO&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DEST_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;FILE_URL&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--read-timeout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;5 &lt;span class=&quot;nt&quot;&gt;--tries&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Download complete.&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Overwrite installation directory if it exists&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$INSTALL_DIR&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
   &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Removing existing installation in &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$INSTALL_DIR&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;INSTALL_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Untar file&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;INSTALL_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
   &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Extracting &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$DEST_DIR&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; to &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$INSTALL_DIR&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
   &lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-xzf&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DEST_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;INSTALL_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--strip-components&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Grab executable folder&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;BIN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;INSTALL_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/bin

&lt;span class=&quot;c&quot;&gt;# Add permissions to install directory&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Adding permissions to &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$INSTALL_DIR&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;chmod&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; +rwx &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;INSTALL_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Enable to add desktop shortcut&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# DESK=/usr/share/applications/${IDE}.desktop&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# echo &quot;[Desktop Entry]\nEncoding=UTF-8\nName=${IDE}\nComment=${IDE}\nExec=${BIN}/${IDE}.sh\nIcon=${BIN}/${IDE}.png\nTerminal=false\nStartupNotify=true\nType=Application&quot; -e &amp;gt; ${DESK}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Create symlink entry&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;TARGET&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BIN&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IDE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;.sh
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Placing symbolic link to &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$TARGET&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; in /usr/local/bin/&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;ln&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-sf&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;TARGET&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; /usr/local/bin/&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IDE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Prompt to launch newly installed IDE&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;while &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
   &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Installation complete. To launch &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IDE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, run: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IDE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;
   Would you like to launch &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$IDE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; right now? (Y/N) &amp;gt; &quot;&lt;/span&gt; REPLY
   &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$REPLY&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
       &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;yY] &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IDE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
       &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;nN] &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Done.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;esac&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Next, run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chmod 755 jetbrains-install.sh &amp;amp;&amp;amp; ./jetbrains-install.sh&lt;/code&gt; and follow the instructions. Once the chosen IDE has launched, one issue you may encounter is &lt;a href=&quot;https://youtrack.jetbrains.com/issue/IDEA-57233&quot;&gt;poor font rendering&lt;/a&gt;, which can occur on certain Linuxes when running Swing applications, resulting in jagged or broken fonts in the UI and Editor. Here, the best course of action is to use a different font. You can switch your default font in Settings, under the ‘Appearance’ menu.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/override_font.jpg&quot; alt=&quot;Override default font&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you would like to see further support for IntelliJ IDEA, PyCharm, WebStorm, PhpStorm, Clion, RubyMine, DataGrip, et al. on Linux, one way you can contribute is by &lt;a href=&quot;https://youtrack.jetbrains.com/issues/IDEA?q=linux+sort+by%3A+votes+desc+%23Open#issueid=IDEA-22750&quot;&gt;reporting issues&lt;/a&gt; that you encounter on Linux. There is a small but growing community of Linux users, and by reporting issues, you will improve the IDE for everyone. Thanks for reading, and if you have feedback on the install script, please &lt;a href=&quot;https://twitter.com/breandan&quot;&gt;reach out to me&lt;/a&gt;!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Inspections, Instructions & Intensions</title>
   <link href="breandan.net/2014/04/20/intellij-inspections/"/>
   <updated>2014-04-20T00:00:00+00:00</updated>
   <id>breandan.net/2014/04/20/intellij-inspections</id>
   <content type="html">&lt;p&gt;IntelliJ IDEA offers a formidable &lt;a href=&quot;https://www.jetbrains.com/idea/documentation/inspections.jsp&quot;&gt;array of inspections&lt;/a&gt; (632 and counting), each thoughtfully crafted to help you deliver clean, bug-free code. One which recently caught my attention, &lt;a href=&quot;http://www.jetbrains.com/idea/documentation/inspections/SuspiciousNameCombination.html&quot;&gt;Suspicious Name Combination&lt;/a&gt;, is an inspection that detects “suspicious” argument-parameter assignments by analyzing lexical tokens in the method signature. This frequently occurs in dyads such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setSize(width, height)&lt;/code&gt;, or triads like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assertEquals(message, actual, expected)&lt;/code&gt; where the order of shared-type parameters can be easily confused and will often slip through static type-checks unnoticed. For example, IntelliJ will alert you when passing a variable named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;btnHeight&lt;/code&gt; into a parameter named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;width&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/suspiciousNameCombination.jpg&quot; alt=&quot;Wow. How smart. Such insight.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you think about it, this is a Non. Trivial. Inspection. Writing good inspections is a fairly delicate process to begin with due to the tradeoff between &lt;a href=&quot;https://en.wikipedia.org/wiki/Sensitivity_and_specificity&quot;&gt;sensitivity and specificity&lt;/a&gt;. If an inspection is too specific, it will lack adequate coverage - if it is too general, then you’ll end up supporting a bunch of &lt;a href=&quot;http://youtrack.jetbrains.com/issue/IDEA-117814&quot;&gt;exceptions&lt;/a&gt; to handle the &lt;a href=&quot;http://youtrack.jetbrains.com/issue/IDEA-72145&quot;&gt;edge cases&lt;/a&gt;. In many ways, this is the same dilemma faced by diagnostic tests for cancer and other medical conditions. Taking the analogy a bit further, if software is the patient, bugs are the cancer and inspections are the diagnostics. So how exactly does IntelliJ Suspicion work? It’s either very ad-hoc or very clever. Let’s go to the &lt;a href=&quot;http://git.jetbrains.org/?p=idea/community.git;a=blob_plain;f=java/java-analysis-impl/src/com/intellij/codeInspection/suspiciousNameCombination/SuspiciousNameCombinationInspectionBase.java;h=e12f10cdbc53198f6e6c44da096aae78dcbe89c8;hb=15777aa6ca7cbe239dec62d255b9735a44ef25a3&quot;&gt;source&lt;/a&gt; for a closer look. The first thing we notice is that identifiers are grouped by similarity into so-called name groups.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt; &lt;span class=&quot;kd&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myNameGroups&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;();&lt;/span&gt;
 &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myWordToGroupMap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HashMap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;();&lt;/span&gt;

 &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;SuspiciousNameCombinationInspectionBase&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;addNameGroup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;x,width,left,right&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;addNameGroup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;y,height,top,bottom&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

 &lt;span class=&quot;kd&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addNameGroup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@NonNls&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;myNameGroups&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;words&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StringUtil&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;,&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;word:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;words&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;myWordToGroupMap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;word&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It looks like they’re building a data structure to detect set membership or something. Let’s go a little further. There are three areas of suspicion: at the assignment, call site, and &lt;a href=&quot;https://devnet.jetbrains.com/message/5228648#5228648&quot;&gt;return statement&lt;/a&gt; (nice). We’ll focus on the call site, since that’s the most general case.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;visitCallExpression&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;PsiCallExpression&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PsiMethod&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;psiMethod&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;resolveMethod&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PsiExpressionList&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getArgumentList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;psiMethod&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PsiExpression&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getExpressions&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PsiParameter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parameters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;psiMethod&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getParameterList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getParameters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parameters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PsiReferenceExpression&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// PsiParameter.getName() can be expensive for compiled class files, so check reference name before&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// fetching parameter name&lt;/span&gt;
            &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;refName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;PsiReferenceExpression&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getReferenceName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;findNameGroup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;refName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;checkCombination&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parameters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;refName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;suspicious.name.parameter&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Forget about what a PSI is for now (it’s something like XPath for ASTs with built-in reflection, you can almost get a feel for it here), this method basically iterates through an argument list. If the argument in question belongs to an existing name group, then it matches that argument name &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;refName&lt;/code&gt; to its respective parameter’s name &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;parameters[i].getName()&lt;/code&gt;, from the method signature and performs some sort of check.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;checkCombination&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PsiElement&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                                  &lt;span class=&quot;nd&quot;&gt;@Nullable&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                                  &lt;span class=&quot;nd&quot;&gt;@Nullable&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;referenceName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                                  &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nameGroup1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findNameGroup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nameGroup2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findNameGroup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;referenceName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nameGroup1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nameGroup2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nameGroup1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nameGroup2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;myProblemsHolder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;registerProblem&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;JavaErrorMessages&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;referenceName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now if the parameter’s name group &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;findNameGroup(name)&lt;/code&gt; doesn’t match the argument’s name group &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;findNameGroup(referenceName)&lt;/code&gt; then we have a problem. There is a semantic contradiction. So far we’re just peeling back the implementation layers. The heart of our algorithm lies in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;findNameGroup(String name)&lt;/code&gt;. Let’s take a look.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@Nullable&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;findNameGroup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@Nullable&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;words&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;NameUtil&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;splitNameIntoWords&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;word:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;words&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myWordToGroupMap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;word&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Tokenize and scan the name for salient keywords, with a &lt;a href=&quot;https://en.wikipedia.org/wiki/Sentinel_value&quot;&gt;sentinel value&lt;/a&gt;: an inconsistent group. Here’s the catch. Not immediately obvious here, but it’s a precaution against false positives! Someone was worried about ambiguous names like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bottomRight&lt;/code&gt; being flagged for suspicion. If and only if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name&lt;/code&gt; belongs to exactly one name group then return that group, otherwise return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;null&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;All things considered, this is a very modest heuristic, accomplishing just what it sets out to do. If it were any more ambitious it might attempt to solve a longest common substring against neighboring parameter name groups, and it might also fail twice as often. The truth is difficult to escape: there is no sure substitute for writing clean code. IntelliJ will catch a limited subset of specific name substitutions, but will not prevent a misplaced argument in an arbitrary function with consecutive, order-dependent, shared-type parameters. Until telepathic connectivity is fully supported, best favor monadic functions, use the &lt;a href=&quot;https://en.wikipedia.org/wiki/Builder_pattern&quot;&gt;builder pattern&lt;/a&gt;, and name variables intelligibly.&lt;/p&gt;

&lt;p&gt;Further Reading&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Martin, Robert C. (2009) “&lt;a href=&quot;https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882&quot;&gt;Clean Code, A Handbook of Agile Software Craftsmanship&lt;/a&gt;.” Chapter 3, pp. 40-43. Function Arguments.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://confluence.jetbrains.com/display/IDEADEV/IntelliJ+IDEA+Architectural+Overview#IntelliJIDEAArchitecturalOverview-PsiElements&quot;&gt;IntelliJ IDEA Architectural Overview - PSI Elements&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://www.cse.buffalo.edu/~rapaport/intensional.html&quot;&gt;Intension vs. Intention&lt;/a&gt;, or, “What you must know in order to determine the reference of an expression,” &lt;a href=&quot;http://wordnetweb.princeton.edu/perl/webwn?s=intension&quot;&gt;Wordnet&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>On Static Imports in Java</title>
   <link href="breandan.net/2014/04/11/on-static-imports-in-java/"/>
   <updated>2014-04-11T00:00:00+00:00</updated>
   <id>breandan.net/2014/04/11/on-static-imports-in-java</id>
   <content type="html">&lt;p&gt;Recently someone asked me, “Breandan, why do I need to write &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;import static org.junit.Assert.*;&lt;/code&gt; in order to use JUnit assertions?” I did not immediately have a good answer, besides the tautology that static imports were used to access static members, and made things generally more readable. What I did not realize, is that there is a very explicit reason why &lt;a href=&quot;https://en.wikipedia.org/wiki/Fluent_interface#Java&quot;&gt;fluent interfaces&lt;/a&gt; such as jOOQ, Mockito, TestNG and JUnit4 have all chosen to adopt this &lt;a href=&quot;https://www.jcp.org/aboutJava/communityprocess/review/jsr201/&quot;&gt;language feature&lt;/a&gt;, and that reason is &lt;a href=&quot;http://books.google.com/books?id=ka2VUBqHiWkC&amp;amp;pg=PA98&amp;amp;lpg=PA98&amp;amp;dq=Constant+Interface+Antipattern+effective+java&amp;amp;source=bl&amp;amp;ots=yYLmKlrZP2&amp;amp;sig=ilYBLq82LEMiWXijRBlcVNyqTK4&amp;amp;hl=en&amp;amp;sa=X&amp;amp;ei=tbVIU8vqB-fn2wW3voHIBA&amp;amp;ved=0CEcQ6AEwAw#v=onepage&amp;amp;q=Constant%20Interface%20Antipattern%20effective%20java&amp;amp;f=false&quot;&gt;The Constant Interface Antipattern&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Prior to JUnit4, test classes would inherit the static members of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;junit.framework.Assert&lt;/code&gt; by extending &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;junit.framework.TestCase&lt;/code&gt;. &lt;a href=&quot;http://junit.sourceforge.net/junit3.8.1/javadoc/junit/framework/TestCase.html#methods_inherited_from_class_junit.framework.Assert&quot;&gt;TestCase&lt;/a&gt; was the parent test class, and by extending it, we had access to a standard set of assertions. Now you might say, “Well Breandan, what does this have to do with The Constant Interface Antipattern? This is a perfectly canonical use of inheritance.” It turns out that by forcing test classes to inherit from TestCase, users are restricted from building more natural test hierarchies and must reimplmenent common functionality or resort to interfaces and utility classes to access a static member. So there must be a better way.&lt;/p&gt;

&lt;p&gt;Enter static imports. There is a &lt;a href=&quot;https://docs.oracle.com/javase/1.5.0/docs/guide/language/static-import.html&quot;&gt;selective use case&lt;/a&gt; here. We must be careful not to pollute the namespace with ambiguous member functions, yet would still like to have some measure of brevity for DSLs and commonly used functions. We would prefer composition over inheritance and allowing the user the flexibility to write standalone test cases. Static imports are appealing for number of reasons: tests use assertions, but assertions ‘belong’ no more to test cases than exceptions belong to a handler. Assertions are frequently used, but seldom all at once (test cases should be short and concise), thereby encouraging users to think carefully about what types of assertions are being used. And &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assertEquals(...)&lt;/code&gt; is simple and recognizable, reducing boilerplate.&lt;/p&gt;

&lt;p&gt;You might be curious how to start writing your own tests in IntelliJ with just a few keystrokes. You can simply press [CTRL+SHIFT+T] within the class you would like to cover, select JUnit4 within the wizard (import the library if prompted), and immeadiately begin writing your unit test (don’t forget to annotate with @Test). Once you are ready to assert a result, type assert[CTRL+ALT+SPACE] and navigate to the desired assertion, then press [ALT+ENTER] and statically import the assertion method for maximum typing efficiency.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/staticImport.gif&quot; alt=&quot;Screenshot&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Further Reading&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://marxsoftware.blogspot.com/2012/04/are-static-imports-becoming.html&quot;&gt;Are Static Imports Becoming Increasingly Accepted in Java?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.doublecloud.org/2013/08/unit-testing-with-junit-4-in-java-quick-introduction-and-simple-samples/&quot;&gt;Unit Testing with JUnit 4 in Java&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>The End of Illiteracy</title>
   <link href="breandan.net/2014/02/09/the-end-of-illiteracy/"/>
   <updated>2014-02-09T00:00:00+00:00</updated>
   <id>breandan.net/2014/02/09/the-end-of-illiteracy</id>
   <content type="html">&lt;p&gt;Reading. It’s something we must all do, and millions of hours are spent each day, passing on that ability to our children. Reciting nursery rhymes, reading children’s books, sounding out each and every syllable for the untrained eye and ear. It’s not something we often think about unless we have children of our own, yet is an inseparable part of our daily life. It is how we learn to write, share, and relive, some have said a path to immortality itself - by inheriting and sharing just a bit of our inner world with the one outside us. Yet some children have no one to teach them, and many more can barely read at a functional level, lacking the education, resources and time. Even those of us lucky enough to receive a college education, most can only read one language. All of that is about to change.&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;In the next few years, there will be a breakthrough in speech recognition technology. There is a quiet revolution already taking place in the speech recognition community, and one that will change the way we learn to read and communicate forever. It is an engineering solution years in the making, on its way to tremendous fruition. With recent breakthroughs in &lt;a href=&quot;https://en.wikipedia.org/wiki/Deep_learning&quot;&gt;deep learning&lt;/a&gt; using &lt;a href=&quot;https://en.wikipedia.org/wiki/Restricted_Boltzmann_machine&quot;&gt;restricted Boltzman machines&lt;/a&gt;, the availability of enormous data sets, and a few more steps of &lt;a href=&quot;https://en.wikipedia.org/wiki/Moore%27s_law&quot;&gt;Moore’s Law&lt;/a&gt;, we will have real-time, native-level speech recognition for the English language. What does this all mean? It means that without a powerful supercomputer, on my smartphone or wristwatch even, and no internet connection whatsoever, I will be able to hold a conversation with a deaf person, using just my voice.&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Some say that with the advent of speech recognition and machine translation, we will no longer need to learn new languages and they will all eventually converge into one, I’m not so sure. What I do know, is that we will never be able to upload a language directly into grey matter. Natural language is acquired, reading is not. It requires effort, and constant practice - there is no &lt;a href=&quot;https://en.wikipedia.org/wiki/Broca&apos;s_area&quot;&gt;Broca’s area&lt;/a&gt; for reading, at least not yet. Here is where machine learning comes in - we have all the necessary tools to eradicate illiteracy in the next century. And I do not mean reduce illiteracy to ten or one percent, I mean eradicate it, like smallpox - where every single person with the functional ability to read, can read Tolstoy and Hemingway. Where every person above the age of fifteen can learn to become an astronaut or test the speed of light, write stories and teach new ideas to one another. And all this is possible (here is where you will object) to an orphan without access to school or even a single adult.&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;How is this possible, you may ask? With (1) &lt;a href=&quot;https://en.wikipedia.org/wiki/Spaced_repetition&quot;&gt;spaced repetition&lt;/a&gt;, (2) &lt;a href=&quot;https://en.wikipedia.org/wiki/Text-To-Speech&quot;&gt;speech synthesis&lt;/a&gt;, (3) &lt;a href=&quot;https://en.wikipedia.org/wiki/Speech_verification&quot;&gt;speech verification&lt;/a&gt;, and (4) ubiquitous &lt;a href=&quot;https://en.wikipedia.org/wiki/Closed_captioning&quot;&gt;closed captioning&lt;/a&gt;, in precisely increasing order of difficulty. The first is easy, but not as easy as you might think. At its heart, is a simple scheduling algorithm, which can be found in plenty of existing flashcard systems, including &lt;a href=&quot;https://ankisrs.net/&quot;&gt;Anki&lt;/a&gt; and &lt;a href=&quot;https://mnemosyne-proj.org/&quot;&gt;Mnemosyne&lt;/a&gt;. In order to do it well, we need a few simple machine learning techniques to customize the results. The second is more difficult in general, but can be faked for pre-recorded learning materials, such as audio books. The third is a &lt;a href=&quot;https://en.wikipedia.org/wiki/Fuzzy_concept&quot;&gt;boundary value problem&lt;/a&gt;, but entirely possible at the moment, and several orders of magnitude simpler than speech recognition. If the second is done well, we can achieve the objective of the third without needing perfect accuracy. Finally, automatic speech recognition is the capstone - the crowning achievement, but if we are ever even remotely successful at speech recognition, speech verification is securely within our reach. We only need three.&lt;/p&gt;
</content>
 </entry>
 

</feed>
