SlideShare ist ein Scribd-Unternehmen logo
1 von 86
Downloaden Sie, um offline zu lesen
Loom and Graphs
in Clojure
github.com/aysylu/loom
Aysylu Greenberg
@aysylu22; http://aysy.lu
LispNYC, August 13th 2013
Overview
•  Loom's Graph API
•  Graph Algorithms in Loom
•  Titanium Loom
•  Single Static Assignment (SSA) Loom
Overview
•  Loom's Graph API
•  Graph Algorithms in Loom
•  Titanium Loom
•  SSA Loom
Loom's Graph API
•  Graph, Digraph, Weighted Graph
Loom's Graph API
•  Graph, Digraph, Weighted Graph
•  FlyGraph
Loom's Graph API
•  Graph, Digraph, Weighted Graph
•  FlyGraph
o  read-only, ad-hoc
Loom's Graph API
•  Graph, Digraph, Weighted Graph
•  FlyGraph
o  read-only, ad-hoc
o  edges from nodes + successors
Loom's Graph API
•  Graph, Digraph, Weighted Graph
•  FlyGraph
o  read-only, ad-hoc
o  edges from nodes + successors
o  nodes and edges from successors + start
Loom's Graph API
•  Uses Clojure protocols
(clojure.org/protocols)
Loom's Graph API
•  Uses Clojure protocols
(clojure.org/protocols)
o  specification only, no implementation
Loom's Graph API
•  Uses Clojure protocols
(clojure.org/protocols)
o  specification only, no implementation
o  single type can implement multiple
protocols
Loom's Graph API
•  Uses Clojure protocols
(clojure.org/protocols)
o  specification only, no implementation
o  single type can implement multiple
protocols
o  interfaces: design-time choice of the type
author, protocols: can be added to a type
at runtime
Loom's Graph API
(defprotocol Graph
(add-nodes* [g nodes] "Add nodes to graph g. See add-nodes”
(add-edges* [g edges] "Add edges to graph g. See add-edges")
Loom's Graph API
(defprotocol Graph
(add-nodes* [g nodes] "Add nodes to graph g. See add-nodes”
(add-edges* [g edges] "Add edges to graph g. See add-edges”)
(remove-nodes* [g nodes] "Remove nodes from graph g. See
remove-nodes”)
(remove-edges* [g edges] "Removes edges from graph g. See
remove-edges”)
(remove-all [g] "Removes all nodes and edges from graph g")
Loom's Graph API
(defprotocol Graph
(add-nodes* [g nodes] "Add nodes to graph g. See add-nodes”
(add-edges* [g edges] "Add edges to graph g. See add-edges”
(remove-nodes* [g nodes] "Remove nodes from graph g. See
remove-nodes”)
(remove-edges* [g edges] "Removes edges from graph g. See
remove-edges”)
(remove-all [g] "Removes all nodes and edges from graph g”
(nodes [g] "Return a collection of the nodes in graph g”)
(edges [g] "Edges in g. May return each edge twice in an undirected
graph")
Loom's Graph API
(defprotocol Graph
(add-nodes* [g nodes] "Add nodes to graph g. See add-nodes”
(add-edges* [g edges] "Add edges to graph g. See add-edges”
(remove-nodes* [g nodes] "Remove nodes from graph g. See
remove-nodes”)
(remove-edges* [g edges] "Removes edges from graph g. See
remove-edges”)
(remove-all [g] "Removes all nodes and edges from graph g”
(nodes [g] "Return a collection of the nodes in graph g”)
(edges [g] "Edges in g. May return each edge twice in an undirected
graph”)
(has-node? [g node] "Return true when node is in g”)
(has-edge? [g n1 n2] "Return true when edge [n1 n2] is in g")
Loom's Graph API
(defprotocol Graph
(add-nodes* [g nodes] "Add nodes to graph g. See add-nodes”
(add-edges* [g edges] "Add edges to graph g. See add-edges”
(remove-nodes* [g nodes] "Remove nodes from graph g. See
remove-nodes”)
(remove-edges* [g edges] "Removes edges from graph g. See
remove-edges”)
(remove-all [g] "Removes all nodes and edges from graph g”
(nodes [g] "Return a collection of the nodes in graph g”)
(edges [g] "Edges in g. May return each edge twice in an undirected
graph”)
(has-node? [g node] "Return true when node is in g”)
(has-edge? [g n1 n2] "Return true when edge [n1 n2] is in g”)
(successors [g] [g node] "Return direct successors of node, or
(partial successors g)”)
(out-degree [g node] "Return the number of direct successors of
node"))
Loom's Graph API
(defprotocol Digraph
(predecessors [g] [g node] "Return direct
predecessors of node, or (partial predecessors g)”)
(in-degree [g node] "Return the number direct
predecessors to node")
Loom's Graph API
(defprotocol Digraph
(predecessors [g] [g node] "Return direct
predecessors of node, or (partial predecessors g)”)
(in-degree [g node] "Return the number direct
predecessors to node”)
(transpose [g] "Return a graph with all edges
reversed"))
Loom's Graph API
(defprotocol WeightedGraph
(weight [g] [g n1 n2] "Return weight of edge [n1 n2]
or (partial weight g)"))
Overview
•  Loom's Graph API
•  Graph Algorithms in Loom
•  Titanium Loom
•  SSA Loom
Graph Algorithms in Loom
•  DFS/BFS (+ bidirectional)
Graph Algorithms in Loom
•  DFS/BFS (+ bidirectional)
•  Topological Sort
Graph Algorithms in Loom
•  DFS/BFS (+ bidirectional)
•  Topological Sort
•  Single Source Shortest Path (Dijkstra, Bellman-Ford)
Graph Algorithms in Loom
•  DFS/BFS (+ bidirectional)
•  Topological Sort
•  Single Source Shortest Path (Dijkstra, Bellman-Ford)
•  Strongly Connected Components (Kosaraju)
Graph Algorithms in Loom
•  DFS/BFS (+ bidirectional)
•  Topological Sort
•  Single Source Shortest Path (Dijkstra, Bellman-Ford)
•  Strongly Connected Components (Kosaraju)
•  Density (edges/nodes)
Graph Algorithms in Loom
•  DFS/BFS (+ bidirectional)
•  Topological Sort
•  Single Source Shortest Path (Dijkstra, Bellman-Ford)
•  Strongly Connected Components (Kosaraju)
•  Density (edges/nodes)
•  Loner nodes
Graph Algorithms in Loom
•  DFS/BFS (+ bidirectional)
•  Topological Sort
•  Single Source Shortest Path (Dijkstra, Bellman-Ford)
•  Strongly Connected Components (Kosaraju)
•  Density (edges/nodes)
•  Loner nodes
•  2 coloring
Graph Algorithms in Loom
•  DFS/BFS (+ bidirectional)
•  Topological Sort
•  Single Source Shortest Path (Dijkstra, Bellman-Ford)
•  Strongly Connected Components (Kosaraju)
•  Density (edges/nodes)
•  Loner nodes
•  2 coloring
•  Max-Flow (Edmonds-Karp)
Graph Algorithms in Loom
•  DFS/BFS (+ bidirectional)
•  Topological Sort
•  Single Source Shortest Path (Dijkstra, Bellman-Ford)
•  Strongly Connected Components (Kosaraju)
•  Density (edges/nodes)
•  Loner nodes
•  2 coloring
•  Max-Flow (Edmonds-Karp)
•  alg-generic requires only successors + start (where
appropriate)
Graph Algorithms: Bellman-Ford
A B C
D E
3 4
5
2
-8
Graph Algorithms: Bellman-Ford
CLRS Introduction to Algorithms
Graph Algorithms: Bellman-Ford
CLRS Introduction to Algorithms
Graph Algorithms: Bellman-Ford
(defn- init-estimates
"Initializes path cost estimates and paths from source to all vertices, for
Bellman-Ford algorithm”
[graph start]
(let [nodes (disj (nodes graph) start)
path-costs {start 0}
paths {start nil}
infinities (repeat Double/POSITIVE_INFINITY)
nils (repeat nil)
init-costs (interleave nodes infinities)
init-paths (interleave nodes nils)]
[(apply assoc path-costs init-costs)
(apply assoc paths init-paths)]))
Graph Algorithms: Bellman-Ford
Graph Algorithms: Bellman-Ford
Graph Algorithms: Bellman-Ford
(defn- can-relax-edge?
"Test for whether we can improve the shortest path to v found so far by
going through u.”
[[u v :as edge] weight costs]
(let [vd (get costs v)
ud (get costs u)
sum (+ ud weight)]
(> vd sum)))
Graph Algorithms: Bellman-Ford
(defn- relax-edge
"If there's a shorter path from s to v via u, update our map of
estimated path costs and map of paths from source to vertex v”
[[u v :as edge] weight [costs paths :as estimates]]
(let [ud (get costs u)
sum (+ ud weight)]
(if (can-relax-edge? edge weight costs)
[(assoc costs v sum) (assoc paths v u)]
estimates)))
Graph Algorithms: Bellman-Ford
Graph Algorithms: Bellman-Ford
(defn- relax-edges
"Performs edge relaxation on all edges in weighted directed graph”
[g start estimates]
(->> (edges g)
(reduce (fn [estimates [u v :as edge]]
(relax-edge edge (wt g u v) estimates))
estimates)))
Graph Algorithms: Bellman-Ford
(defn bellman-ford
"Given a weighted, directed graph G = (V, E) with source start, the Bellman-Ford algorithm produces map of single source shortest paths and their
costs if no negative-weight cycle that is reachable from the source exits, and false otherwise, indicating that no solution exists."
[g start]
(let [initial-estimates (init-estimates g start)
;relax-edges is calculated for all edges V-1 times
[costs paths] (reduce (fn [estimates _]
(relax-edges g start estimates))
initial-estimates
(-> g nodes count dec range))
edges (edges g)]
(if (some
(fn [[u v :as edge]]
(can-relax-edge? edge (wt g u v) costs))
edges)
false
[costs
(->> (keys paths)
;remove vertices that are unreachable from source
(remove #(= Double/POSITIVE_INFINITY (get costs %)))
(reduce
(fn [final-paths v]
(assoc final-paths v
; follows the parent pointers
; to construct path from source to node v
(loop [node v
path ()]
(if node
(recur (get paths node) (cons node path))
path))))
{}))])))
Graph Algorithms: Bellman-Ford
(defn bellman-ford
"Given a weighted, directed graph G = (V, E) with source start,
the Bellman-Ford algorithm produces map of single source
shortest paths and their costs if no negative-weight cycle that is
reachable from the source exits, and false otherwise, indicating
that no solution exists."
Graph Algorithms: Bellman-Ford
[g start]
(let [initial-estimates (init-estimates g start)
;relax-edges is calculated for all edges V-1 times
[costs paths] (reduce (fn [estimates _]
(relax-edges g start estimates))
initial-estimates
(->> g (nodes) (count) (dec) (range)))
edges (edges g)]
Graph Algorithms: Bellman-Ford
[g start]
(let [initial-estimates (init-estimates g start)
;relax-edges is calculated for all edges V-1 times
[costs paths] (reduce (fn [estimates _]
(relax-edges g start estimates))
initial-estimates
(->> g (nodes) (count) (dec) (range)))
edges (edges g)]
Graph Algorithms: Bellman-Ford
(if (some (fn [[u v :as edge]]
(can-relax-edge? edge (wt g u v) costs))
edges)
false
Graph Algorithms: Bellman-Ford
[costs
(->> (keys paths)
;remove vertices that are unreachable from source
(remove
#(= Double/POSITIVE_INFINITY (get costs %)))
Graph Algorithms: Bellman-Ford
[costs
(->> (keys paths)
;remove vertices that are unreachable from source
(remove
#(= Double/POSITIVE_INFINITY (get costs %)))
(reduce
(fn [final-paths v]
(assoc final-paths v
; follows the parent pointers
; to construct path from source to node v
(loop [node v path ()]
(if node
(recur (get paths node) (cons node path))
path))))
{}))])))
Overview
•  Loom's Graph API
•  Graph Algorithms
•  Titanium Loom
•  SSA Loom
Titanium Loom
•  Titanium by Clojurewerkz
(titanium.clojurewerkz.org)
Titanium Loom
•  Titanium by Clojurewerkz
(titanium.clojurewerkz.org)
•  Clojure graph library built on top of Aurelius
Titan (thinkaurelius.github.com/titan)
Titanium Loom
•  Titanium by Clojurewerkz
(titanium.clojurewerkz.org)
•  Clojure graph library built on top of Aurelius
Titan (thinkaurelius.github.com/titan)
•  Various storage backends: Cassandra,
HBase, BerkeleyDB Java Edition
Titanium Loom
•  Titanium by Clojurewerkz
(titanium.clojurewerkz.org)
•  Clojure graph library built on top of Aurelius
Titan (thinkaurelius.github.com/titan)
•  Various storage backends: Cassandra,
HBase, BerkeleyDB Java Edition
•  No graph visualization
Titanium Loom
(let [in-mem-graph (tg/open {"storage.backend" "inmemory"})]
(tg/transact!
(let [
a (nodes/create! {:name "Node A"})
b (nodes/create! {:name "Node B"})
c (nodes/create! {:name "Node C"})
Titanium Loom
(let [in-mem-graph (tg/open {"storage.backend" "inmemory"})]
(tg/transact!
(let [
a (nodes/create! {:name "Node A"})
b (nodes/create! {:name "Node B"})
c (nodes/create! {:name "Node C"})
e1 (edges/connect! a "edge A->B" b)
e2 (edges/connect! b "edge B->C" c)
e3 (edges/connect! c "edge C->A” a)
graph (titanium->loom in-mem-graph)])
Titanium Loom
(view graph)
Titanium Loom
(defn titanium->loom
"Converts titanium graph into Loom representation”
([titanium-graph &
{:keys [node-fn edge-fn weight-fn]
:or {node-fn (nodes/get-all-vertices)
edge-fn (map (juxt edges/tail-vertex
edges/head-vertex)
(edges/get-all-edges))
weight-fn (constantly 1)}}]
(let [nodes-set (set node-fn)
edges-set (set edge-fn)]
Titanium Loom
(reify
Graph
(nodes [_] nodes-set)
(edges [_] edges-set)
(has-node? [g node] (contains? (nodes g) node))
(has-edge? [g n1 n2] (contains? (edges g) [n1 n2]))
(successors [g] (partial successors g))
(successors [g node] (filter (nodes g)
(seq (nodes/connected-out-vertices node))))
(out-degree [g node] (count (successors g node)))
Titanium Loom
(reify
Graph
(nodes [_] nodes-set)
(edges [_] edges-set)
(has-node? [g node] (contains? (nodes g) node))
(has-edge? [g n1 n2] (contains? (edges g) [n1 n2]))
(successors [g] (partial successors g))
(successors [g node] (filter (nodes g)
(seq (nodes/connected-out-vertices node))))
(out-degree [g node] (count (successors g node)))
Digraph
(predecessors [g] (partial predecessors g))
(predecessors [g node] (filter (nodes g)
(seq (nodes/connected-in-vertices node))))
(in-degree [g node] (count (predecessors g node)))
WeightedGraph
(weight [g] (partial weight g))
(weight [g n1 n2] (weight-fn n1 n2))))))
Overview
•  Loom's Graph API
•  Graph Algorithms
•  Titanium Loom
•  SSA Loom
SSA Loom
•  Single Static Assignment (SSA) form
produced by core.async
SSA Loom
•  Single Static Assignment (SSA) form
produced by core.async
•  Generated by parse-to-state-machine
function
SSA Loom
(parse-to-state-machine
'[(if (> (+ x 1 2 y) 0)
(+ x 1)
(+ x 2))])
SSA Loom
(parse-to-state-machine
'[(if (> (+ x 1 2 y) 0)
(+ x 1)
(+ x 2))])
[inst_4938
{:current-block 76,
:start-block 73,
:block-catches {76 nil, 75 nil, 74 nil, 73 nil},
:blocks
{76
[{:value :clojure.core.async.impl.ioc-macros/value, :id
inst_4937}
{:value inst_4937, :id inst_4938}],
75
[{:refs [clojure.core/+ x 2], :id inst_4935}
{:value inst_4935, :block 76, :id inst_4936}],
74
[{:refs [clojure.core/+ x 1], :id inst_4933}
{:value inst_4933, :block 76, :id inst_4934}],
73
[{:refs [clojure.core/+ x 1 2 y], :id inst_4930}
{:refs [clojure.core/> inst_4930 0], :id inst_4931}
{:test inst_4931, :then-block 74, :else-block 75, :id
inst_4932}]}}]
SSA Loom
(def ssa
(->>
(parse-to-state-machine
'[(if (> (+ x 1 2 y) 0)
(+ x 1)
(+ x 2))])
second
:blocks))
SSA Loom
{76
[{:value :clojure.core.async.impl.ioc-macros/
value, :id inst_4937}
{:value inst_4937, :id inst_4938}],
75
[{:refs [clojure.core/+ x 2], :id inst_4935}
{:value inst_4935, :block 76, :id inst_4936}],
74
[{:refs [clojure.core/+ x 1], :id inst_4933}
{:value inst_4933, :block 76, :id inst_4934}],
73
[{:refs [clojure.core/+ x 1 2 y], :id inst_4930}
{:refs [clojure.core/> inst_4930 0], :id
inst_4931}
{:test inst_4931, :then-block 74, :else-block
75, :id inst_4932}]}}]
(def ssa
(->>
(parse-to-state-machine
'[(if (> (+ x 1 2 y) 0)
(+ x 1)
(+ x 2))])
second
:blocks))
SSA Loom
(view (ssa->loom ssa ssa-nodes-fn ssa-edges-fn))
SSA Loom
(view (ssa->loom ssa ssa-nodes-fn ssa-edges-fn))
SSA Loom
(view (ssa->loom ssa ssa-nodes-fn ssa-edges-fn))
(defn ssa->loom
"Converts the SSA form generated by core.async into Loom
representation.”
([ssa node-fn edge-fn]
(let [nodes (delay (node-fn ssa))
edges (delay (edge-fn ssa))]
SSA Loom
(view (ssa->loom ssa ssa-nodes-fn ssa-edges-fn))
{:graph (reify
Graph
(nodes [g] @nodes)
(edges [g] @edges)
(has-node? [g node] (contains? @nodes node))
(has-edge? [g n1 n2] (contains? @edges [n1 n2]))
(successors [g] (partial successors g))
(successors [g node]
(->> @edges
(filter (fn [[n1 n2]] (= n1 node)))
(map second)))
(out-degree [g node] (count (successors g node)))
SSA Loom
(view (ssa->loom ssa ssa-nodes-fn ssa-edges-fn))
Digraph
(predecessors [g] (partial predecessors g))
(predecessors [g node]
(->> @edges
(filter (fn [[n1 n2]] (= n2 node)))
(map first)))
(in-degree [g node] (count (predecessors g node))))
:data ssa})))
SSA Loom: Dataflow Analysis
•  For each basic block, solve system of
equations until reaching fixed point:
•  Use worklist approach
SSA Loom: Dataflow Analysis
(defn dataflow-analysis
"Performs dataflow analysis. Nodes have value nil initially.”
[& {:keys [start graph join transfer]}]
(let [start (cond
(set? start) start
(coll? start) (set start)
:else #{start})]
SSA Loom: Dataflow Analysis
(loop [out-values {}
[node & worklist]
(into clojure.lang.PersistentQueue/EMPTY start)
(let [in-value (join
(mapv out-values (predecessors graph node)))
out (transfer node in-value)
update? (not= out (get out-values node))
out-values (if update?
(assoc out-values node out)
out-values)
worklist (if update?
(into worklist (successors graph node))
worklist)]
SSA Loom: Dataflow Analysis
(loop [out-values {}
[node & worklist]
(into clojure.lang.PersistentQueue/EMPTY start
(let [in-value (join
(mapv out-values (predecessors graph node)))
out (transfer node in-value)
update? (not= out (get out-values node))
out-values (if update?
(assoc out-values node out)
out-values)
worklist (if update?
(into worklist (successors graph node))
worklist)]
(if (seq worklist)
(recur out-values worklist)
out-values)))))
SSA Loom: Global Availability
(defn global-cse
[ssa]
(let [{graph :graph node-data :data}
(ssa->loom (:blocks ssa) ssa-nodes-fn ssa-edges-fn)
start (:start-block ssa)]
(letfn [(pure? [instr] (contains? instr :refs))
(global-cse-join
[values]
(if (seq values)
(apply set/intersection values)
#{}))
(global-cse-transfer
[node in-value]
(into in-value
(map :refs (filter pure? (node-data node)))))]
SSA Loom: Global Availability
(defn global-cse
[ssa]
(let [{graph :graph node-data :data}
(ssa->loom (:blocks ssa) ssa-nodes-fn ssa-edges-fn)
start (:start-block ssa)]
(letfn [(pure? [instr] (contains? instr :refs))
(global-cse-join
[values]
(if (seq values)
(apply set/intersection values)
#{}))
(global-cse-transfer
[node in-value]
(into in-value
(map :refs (filter pure? (node-data node)))))]
(dataflow-analysis :start start :graph graph
:join global-cse-join
:transfer global-cse-transfer))))
SSA Loom: Dataflow Analysis
• Reaching definitions
SSA Loom: Dataflow Analysis
• Reaching definitions
• Liveness analysis (dead code elimination)
SSA Loom: Dataflow Analysis
• Reaching definitions
• Liveness analysis (dead code elimination)
• Available expressions
SSA Loom: Dataflow Analysis
• Reaching definitions
• Liveness analysis (dead code elimination)
• Available expressions
• Constant propagation
SSA Loom: Dataflow Analysis
• Reaching definitions
• Liveness analysis (dead code elimination)
• Available expressions
• Constant propagation
• Other Applications:
SSA Loom: Dataflow Analysis
• Reaching definitions
• Liveness analysis (dead code elimination)
• Available expressions
• Constant propagation
• Other Applications:
o  Erdős number
SSA Loom: Dataflow Analysis
• Reaching definitions
• Liveness analysis (dead code elimination)
• Available expressions
• Constant propagation
• Other Applications:
o  Erdős number
o  Spread of information in systems (e.g. taint)
My Experience
• Intuitive way to implement algorithms
functionally
• Some mental overhead of transforming data
structures
Open Questions
• How general should a graph API be?
Open Questions
• How general should a graph API be?
• How feature-rich should a graph API be?

Weitere ähnliche Inhalte

Was ist angesagt?

Crystal Ball Event Prediction and Log Analysis with Hadoop MapReduce and Spark
Crystal Ball Event Prediction and Log Analysis with Hadoop MapReduce and SparkCrystal Ball Event Prediction and Log Analysis with Hadoop MapReduce and Spark
Crystal Ball Event Prediction and Log Analysis with Hadoop MapReduce and SparkJivan Nepali
 
Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Philip Schwarz
 
Value objects in JS - an ES7 work in progress
Value objects in JS - an ES7 work in progressValue objects in JS - an ES7 work in progress
Value objects in JS - an ES7 work in progressBrendan Eich
 
Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...Piotr Paradziński
 
JS Responsibilities
JS ResponsibilitiesJS Responsibilities
JS ResponsibilitiesBrendan Eich
 
Building Enigma with State Monad & Lens
Building Enigma with State Monad & LensBuilding Enigma with State Monad & Lens
Building Enigma with State Monad & LensTimothy Perrett
 
lecture 6
lecture 6lecture 6
lecture 6sajinsc
 
Configurable Pattern Matching Semantics in openCypher: Defining Levels of Nod...
Configurable Pattern Matching Semantics in openCypher: Defining Levels of Nod...Configurable Pattern Matching Semantics in openCypher: Defining Levels of Nod...
Configurable Pattern Matching Semantics in openCypher: Defining Levels of Nod...openCypher
 
Audio chord recognition using deep neural networks
Audio chord recognition using deep neural networksAudio chord recognition using deep neural networks
Audio chord recognition using deep neural networksbzamecnik
 
Mathematical preliminaries in Automata
Mathematical preliminaries in AutomataMathematical preliminaries in Automata
Mathematical preliminaries in AutomataMobeen Mustafa
 
Graph x pregel
Graph x pregelGraph x pregel
Graph x pregelSigmoid
 
Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021
Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021
Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021Peng Cheng
 
RUSTing -- Partially Ordered Rust Programming Ruminations
RUSTing -- Partially Ordered Rust Programming RuminationsRUSTing -- Partially Ordered Rust Programming Ruminations
RUSTing -- Partially Ordered Rust Programming RuminationsAngelo Corsaro
 
Sequence and Traverse - Part 3
Sequence and Traverse - Part 3Sequence and Traverse - Part 3
Sequence and Traverse - Part 3Philip Schwarz
 
Computer graphics practical(jainam)
Computer graphics practical(jainam)Computer graphics practical(jainam)
Computer graphics practical(jainam)JAINAM KAPADIYA
 
Functional IO and Effects
Functional IO and EffectsFunctional IO and Effects
Functional IO and EffectsDylan Forciea
 

Was ist angesagt? (17)

20180722 pyro
20180722 pyro20180722 pyro
20180722 pyro
 
Crystal Ball Event Prediction and Log Analysis with Hadoop MapReduce and Spark
Crystal Ball Event Prediction and Log Analysis with Hadoop MapReduce and SparkCrystal Ball Event Prediction and Log Analysis with Hadoop MapReduce and Spark
Crystal Ball Event Prediction and Log Analysis with Hadoop MapReduce and Spark
 
Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Sequence and Traverse - Part 1
Sequence and Traverse - Part 1
 
Value objects in JS - an ES7 work in progress
Value objects in JS - an ES7 work in progressValue objects in JS - an ES7 work in progress
Value objects in JS - an ES7 work in progress
 
Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...
 
JS Responsibilities
JS ResponsibilitiesJS Responsibilities
JS Responsibilities
 
Building Enigma with State Monad & Lens
Building Enigma with State Monad & LensBuilding Enigma with State Monad & Lens
Building Enigma with State Monad & Lens
 
lecture 6
lecture 6lecture 6
lecture 6
 
Configurable Pattern Matching Semantics in openCypher: Defining Levels of Nod...
Configurable Pattern Matching Semantics in openCypher: Defining Levels of Nod...Configurable Pattern Matching Semantics in openCypher: Defining Levels of Nod...
Configurable Pattern Matching Semantics in openCypher: Defining Levels of Nod...
 
Audio chord recognition using deep neural networks
Audio chord recognition using deep neural networksAudio chord recognition using deep neural networks
Audio chord recognition using deep neural networks
 
Mathematical preliminaries in Automata
Mathematical preliminaries in AutomataMathematical preliminaries in Automata
Mathematical preliminaries in Automata
 
Graph x pregel
Graph x pregelGraph x pregel
Graph x pregel
 
Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021
Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021
Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021
 
RUSTing -- Partially Ordered Rust Programming Ruminations
RUSTing -- Partially Ordered Rust Programming RuminationsRUSTing -- Partially Ordered Rust Programming Ruminations
RUSTing -- Partially Ordered Rust Programming Ruminations
 
Sequence and Traverse - Part 3
Sequence and Traverse - Part 3Sequence and Traverse - Part 3
Sequence and Traverse - Part 3
 
Computer graphics practical(jainam)
Computer graphics practical(jainam)Computer graphics practical(jainam)
Computer graphics practical(jainam)
 
Functional IO and Effects
Functional IO and EffectsFunctional IO and Effects
Functional IO and Effects
 

Ähnlich wie Loom and Graphs in Clojure

Loom & Functional Graphs in Clojure @ LambdaConf 2015
Loom & Functional Graphs in Clojure @ LambdaConf 2015Loom & Functional Graphs in Clojure @ LambdaConf 2015
Loom & Functional Graphs in Clojure @ LambdaConf 2015Aysylu Greenberg
 
ABSTRACT GRAPH MACHINE: MODELING ORDERINGS IN ASYNCHRONOUS DISTRIBUTED-MEMORY...
ABSTRACT GRAPH MACHINE: MODELING ORDERINGS IN ASYNCHRONOUS DISTRIBUTED-MEMORY...ABSTRACT GRAPH MACHINE: MODELING ORDERINGS IN ASYNCHRONOUS DISTRIBUTED-MEMORY...
ABSTRACT GRAPH MACHINE: MODELING ORDERINGS IN ASYNCHRONOUS DISTRIBUTED-MEMORY...Thejaka Amila Kanewala, Ph.D.
 
[系列活動] Data exploration with modern R
[系列活動] Data exploration with modern R[系列活動] Data exploration with modern R
[系列活動] Data exploration with modern R台灣資料科學年會
 
DrawingML Subject: Shape Properties & Effects
DrawingML Subject: Shape Properties & EffectsDrawingML Subject: Shape Properties & Effects
DrawingML Subject: Shape Properties & EffectsShawn Villaron
 
A walk in graph databases v1.0
A walk in graph databases v1.0A walk in graph databases v1.0
A walk in graph databases v1.0Pierre De Wilde
 
141222 graphulo ingraphblas
141222 graphulo ingraphblas141222 graphulo ingraphblas
141222 graphulo ingraphblasMIT
 
141205 graphulo ingraphblas
141205 graphulo ingraphblas141205 graphulo ingraphblas
141205 graphulo ingraphblasgraphulo
 
La R Users Group Survey Of R Graphics
La R Users Group Survey Of R GraphicsLa R Users Group Survey Of R Graphics
La R Users Group Survey Of R Graphicsguest43ed8709
 
IGraph a tool to analyze your network
IGraph a tool to analyze your networkIGraph a tool to analyze your network
IGraph a tool to analyze your networkPushpendra Tiwari
 
Introductionto fp with groovy
Introductionto fp with groovyIntroductionto fp with groovy
Introductionto fp with groovyIsuru Samaraweera
 
Tech talk ggplot2
Tech talk   ggplot2Tech talk   ggplot2
Tech talk ggplot2jalle6
 
PART 4: GEOGRAPHIC SCRIPTING
PART 4: GEOGRAPHIC SCRIPTINGPART 4: GEOGRAPHIC SCRIPTING
PART 4: GEOGRAPHIC SCRIPTINGAndrea Antonello
 
[Let'Swift 2019] 실용적인 함수형 프로그래밍 워크샵
[Let'Swift 2019] 실용적인 함수형 프로그래밍 워크샵[Let'Swift 2019] 실용적인 함수형 프로그래밍 워크샵
[Let'Swift 2019] 실용적인 함수형 프로그래밍 워크샵Wanbok Choi
 

Ähnlich wie Loom and Graphs in Clojure (20)

Loom & Functional Graphs in Clojure @ LambdaConf 2015
Loom & Functional Graphs in Clojure @ LambdaConf 2015Loom & Functional Graphs in Clojure @ LambdaConf 2015
Loom & Functional Graphs in Clojure @ LambdaConf 2015
 
Loom at Clojure/West
Loom at Clojure/WestLoom at Clojure/West
Loom at Clojure/West
 
ABSTRACT GRAPH MACHINE: MODELING ORDERINGS IN ASYNCHRONOUS DISTRIBUTED-MEMORY...
ABSTRACT GRAPH MACHINE: MODELING ORDERINGS IN ASYNCHRONOUS DISTRIBUTED-MEMORY...ABSTRACT GRAPH MACHINE: MODELING ORDERINGS IN ASYNCHRONOUS DISTRIBUTED-MEMORY...
ABSTRACT GRAPH MACHINE: MODELING ORDERINGS IN ASYNCHRONOUS DISTRIBUTED-MEMORY...
 
[系列活動] Data exploration with modern R
[系列活動] Data exploration with modern R[系列活動] Data exploration with modern R
[系列活動] Data exploration with modern R
 
Twopi.1
Twopi.1Twopi.1
Twopi.1
 
DrawingML Subject: Shape Properties & Effects
DrawingML Subject: Shape Properties & EffectsDrawingML Subject: Shape Properties & Effects
DrawingML Subject: Shape Properties & Effects
 
A walk in graph databases v1.0
A walk in graph databases v1.0A walk in graph databases v1.0
A walk in graph databases v1.0
 
141222 graphulo ingraphblas
141222 graphulo ingraphblas141222 graphulo ingraphblas
141222 graphulo ingraphblas
 
141205 graphulo ingraphblas
141205 graphulo ingraphblas141205 graphulo ingraphblas
141205 graphulo ingraphblas
 
Groovy
GroovyGroovy
Groovy
 
8150.graphs
8150.graphs8150.graphs
8150.graphs
 
Algorithms Design Assignment Help
Algorithms Design Assignment HelpAlgorithms Design Assignment Help
Algorithms Design Assignment Help
 
La R Users Group Survey Of R Graphics
La R Users Group Survey Of R GraphicsLa R Users Group Survey Of R Graphics
La R Users Group Survey Of R Graphics
 
Algorithms Design Exam Help
Algorithms Design Exam HelpAlgorithms Design Exam Help
Algorithms Design Exam Help
 
AfterGlow
AfterGlowAfterGlow
AfterGlow
 
IGraph a tool to analyze your network
IGraph a tool to analyze your networkIGraph a tool to analyze your network
IGraph a tool to analyze your network
 
Introductionto fp with groovy
Introductionto fp with groovyIntroductionto fp with groovy
Introductionto fp with groovy
 
Tech talk ggplot2
Tech talk   ggplot2Tech talk   ggplot2
Tech talk ggplot2
 
PART 4: GEOGRAPHIC SCRIPTING
PART 4: GEOGRAPHIC SCRIPTINGPART 4: GEOGRAPHIC SCRIPTING
PART 4: GEOGRAPHIC SCRIPTING
 
[Let'Swift 2019] 실용적인 함수형 프로그래밍 워크샵
[Let'Swift 2019] 실용적인 함수형 프로그래밍 워크샵[Let'Swift 2019] 실용적인 함수형 프로그래밍 워크샵
[Let'Swift 2019] 실용적인 함수형 프로그래밍 워크샵
 

Mehr von Aysylu Greenberg

Software Supply Chains for DevOps @ InfoQ Live 2021
Software Supply Chains for DevOps @ InfoQ Live 2021Software Supply Chains for DevOps @ InfoQ Live 2021
Software Supply Chains for DevOps @ InfoQ Live 2021Aysylu Greenberg
 
Binary Authorization in Kubernetes
Binary Authorization in KubernetesBinary Authorization in Kubernetes
Binary Authorization in KubernetesAysylu Greenberg
 
Software Supply Chain Management with Grafeas and Kritis
Software Supply Chain Management with Grafeas and KritisSoftware Supply Chain Management with Grafeas and Kritis
Software Supply Chain Management with Grafeas and KritisAysylu Greenberg
 
Software Supply Chain Observability with Grafeas and Kritis
Software Supply Chain Observability with Grafeas and KritisSoftware Supply Chain Observability with Grafeas and Kritis
Software Supply Chain Observability with Grafeas and KritisAysylu Greenberg
 
Software Supply Chain Management with Grafeas and Kritis
Software Supply Chain Management with Grafeas and KritisSoftware Supply Chain Management with Grafeas and Kritis
Software Supply Chain Management with Grafeas and KritisAysylu Greenberg
 
Zero Downtime Migrations at Scale
Zero Downtime Migrations at ScaleZero Downtime Migrations at Scale
Zero Downtime Migrations at ScaleAysylu Greenberg
 
Distributed systems in practice, in theory (ScaleConf Colombia)
Distributed systems in practice, in theory (ScaleConf Colombia)Distributed systems in practice, in theory (ScaleConf Colombia)
Distributed systems in practice, in theory (ScaleConf Colombia)Aysylu Greenberg
 
MesosCon Asia Keynote: Replacing a Jet Engine Mid-flight
MesosCon Asia Keynote: Replacing a Jet Engine Mid-flightMesosCon Asia Keynote: Replacing a Jet Engine Mid-flight
MesosCon Asia Keynote: Replacing a Jet Engine Mid-flightAysylu Greenberg
 
Distributed systems in practice, in theory (JAX London)
Distributed systems in practice, in theory (JAX London)Distributed systems in practice, in theory (JAX London)
Distributed systems in practice, in theory (JAX London)Aysylu Greenberg
 
Building A Distributed Build System at Google Scale (StrangeLoop 2016)
Building A Distributed Build System at Google Scale (StrangeLoop 2016)Building A Distributed Build System at Google Scale (StrangeLoop 2016)
Building A Distributed Build System at Google Scale (StrangeLoop 2016)Aysylu Greenberg
 
QCon NYC: Distributed systems in practice, in theory
QCon NYC: Distributed systems in practice, in theoryQCon NYC: Distributed systems in practice, in theory
QCon NYC: Distributed systems in practice, in theoryAysylu Greenberg
 
Building a Distributed Build System at Google Scale
Building a Distributed Build System at Google ScaleBuilding a Distributed Build System at Google Scale
Building a Distributed Build System at Google ScaleAysylu Greenberg
 
Distributed systems in practice, in theory
Distributed systems in practice, in theoryDistributed systems in practice, in theory
Distributed systems in practice, in theoryAysylu Greenberg
 
Probabilistic Accuracy Bounds @ Papers We Love SF
Probabilistic Accuracy Bounds @ Papers We Love SFProbabilistic Accuracy Bounds @ Papers We Love SF
Probabilistic Accuracy Bounds @ Papers We Love SFAysylu Greenberg
 
Benchmarking (JAXLondon 2015)
Benchmarking (JAXLondon 2015)Benchmarking (JAXLondon 2015)
Benchmarking (JAXLondon 2015)Aysylu Greenberg
 
Benchmarking (DevNexus 2015)
Benchmarking (DevNexus 2015)Benchmarking (DevNexus 2015)
Benchmarking (DevNexus 2015)Aysylu Greenberg
 

Mehr von Aysylu Greenberg (20)

Software Supply Chains for DevOps @ InfoQ Live 2021
Software Supply Chains for DevOps @ InfoQ Live 2021Software Supply Chains for DevOps @ InfoQ Live 2021
Software Supply Chains for DevOps @ InfoQ Live 2021
 
Binary Authorization in Kubernetes
Binary Authorization in KubernetesBinary Authorization in Kubernetes
Binary Authorization in Kubernetes
 
Software Supply Chain Management with Grafeas and Kritis
Software Supply Chain Management with Grafeas and KritisSoftware Supply Chain Management with Grafeas and Kritis
Software Supply Chain Management with Grafeas and Kritis
 
Software Supply Chain Observability with Grafeas and Kritis
Software Supply Chain Observability with Grafeas and KritisSoftware Supply Chain Observability with Grafeas and Kritis
Software Supply Chain Observability with Grafeas and Kritis
 
Software Supply Chain Management with Grafeas and Kritis
Software Supply Chain Management with Grafeas and KritisSoftware Supply Chain Management with Grafeas and Kritis
Software Supply Chain Management with Grafeas and Kritis
 
Zero Downtime Migrations at Scale
Zero Downtime Migrations at ScaleZero Downtime Migrations at Scale
Zero Downtime Migrations at Scale
 
Zero Downtime Migration
Zero Downtime MigrationZero Downtime Migration
Zero Downtime Migration
 
PWL Denver: Copysets
PWL Denver: CopysetsPWL Denver: Copysets
PWL Denver: Copysets
 
Distributed systems in practice, in theory (ScaleConf Colombia)
Distributed systems in practice, in theory (ScaleConf Colombia)Distributed systems in practice, in theory (ScaleConf Colombia)
Distributed systems in practice, in theory (ScaleConf Colombia)
 
MesosCon Asia Keynote: Replacing a Jet Engine Mid-flight
MesosCon Asia Keynote: Replacing a Jet Engine Mid-flightMesosCon Asia Keynote: Replacing a Jet Engine Mid-flight
MesosCon Asia Keynote: Replacing a Jet Engine Mid-flight
 
Distributed systems in practice, in theory (JAX London)
Distributed systems in practice, in theory (JAX London)Distributed systems in practice, in theory (JAX London)
Distributed systems in practice, in theory (JAX London)
 
Building A Distributed Build System at Google Scale (StrangeLoop 2016)
Building A Distributed Build System at Google Scale (StrangeLoop 2016)Building A Distributed Build System at Google Scale (StrangeLoop 2016)
Building A Distributed Build System at Google Scale (StrangeLoop 2016)
 
QCon NYC: Distributed systems in practice, in theory
QCon NYC: Distributed systems in practice, in theoryQCon NYC: Distributed systems in practice, in theory
QCon NYC: Distributed systems in practice, in theory
 
Building a Distributed Build System at Google Scale
Building a Distributed Build System at Google ScaleBuilding a Distributed Build System at Google Scale
Building a Distributed Build System at Google Scale
 
(+ Loom (years 2))
(+ Loom (years 2))(+ Loom (years 2))
(+ Loom (years 2))
 
Distributed systems in practice, in theory
Distributed systems in practice, in theoryDistributed systems in practice, in theory
Distributed systems in practice, in theory
 
Probabilistic Accuracy Bounds @ Papers We Love SF
Probabilistic Accuracy Bounds @ Papers We Love SFProbabilistic Accuracy Bounds @ Papers We Love SF
Probabilistic Accuracy Bounds @ Papers We Love SF
 
Benchmarking (JAXLondon 2015)
Benchmarking (JAXLondon 2015)Benchmarking (JAXLondon 2015)
Benchmarking (JAXLondon 2015)
 
Benchmarking (DevNexus 2015)
Benchmarking (DevNexus 2015)Benchmarking (DevNexus 2015)
Benchmarking (DevNexus 2015)
 
Benchmarking (RICON 2014)
Benchmarking (RICON 2014)Benchmarking (RICON 2014)
Benchmarking (RICON 2014)
 

Kürzlich hochgeladen

What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfhans926745
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 

Kürzlich hochgeladen (20)

What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 

Loom and Graphs in Clojure

  • 1. Loom and Graphs in Clojure github.com/aysylu/loom Aysylu Greenberg @aysylu22; http://aysy.lu LispNYC, August 13th 2013
  • 2. Overview •  Loom's Graph API •  Graph Algorithms in Loom •  Titanium Loom •  Single Static Assignment (SSA) Loom
  • 3. Overview •  Loom's Graph API •  Graph Algorithms in Loom •  Titanium Loom •  SSA Loom
  • 4. Loom's Graph API •  Graph, Digraph, Weighted Graph
  • 5. Loom's Graph API •  Graph, Digraph, Weighted Graph •  FlyGraph
  • 6. Loom's Graph API •  Graph, Digraph, Weighted Graph •  FlyGraph o  read-only, ad-hoc
  • 7. Loom's Graph API •  Graph, Digraph, Weighted Graph •  FlyGraph o  read-only, ad-hoc o  edges from nodes + successors
  • 8. Loom's Graph API •  Graph, Digraph, Weighted Graph •  FlyGraph o  read-only, ad-hoc o  edges from nodes + successors o  nodes and edges from successors + start
  • 9. Loom's Graph API •  Uses Clojure protocols (clojure.org/protocols)
  • 10. Loom's Graph API •  Uses Clojure protocols (clojure.org/protocols) o  specification only, no implementation
  • 11. Loom's Graph API •  Uses Clojure protocols (clojure.org/protocols) o  specification only, no implementation o  single type can implement multiple protocols
  • 12. Loom's Graph API •  Uses Clojure protocols (clojure.org/protocols) o  specification only, no implementation o  single type can implement multiple protocols o  interfaces: design-time choice of the type author, protocols: can be added to a type at runtime
  • 13. Loom's Graph API (defprotocol Graph (add-nodes* [g nodes] "Add nodes to graph g. See add-nodes” (add-edges* [g edges] "Add edges to graph g. See add-edges")
  • 14. Loom's Graph API (defprotocol Graph (add-nodes* [g nodes] "Add nodes to graph g. See add-nodes” (add-edges* [g edges] "Add edges to graph g. See add-edges”) (remove-nodes* [g nodes] "Remove nodes from graph g. See remove-nodes”) (remove-edges* [g edges] "Removes edges from graph g. See remove-edges”) (remove-all [g] "Removes all nodes and edges from graph g")
  • 15. Loom's Graph API (defprotocol Graph (add-nodes* [g nodes] "Add nodes to graph g. See add-nodes” (add-edges* [g edges] "Add edges to graph g. See add-edges” (remove-nodes* [g nodes] "Remove nodes from graph g. See remove-nodes”) (remove-edges* [g edges] "Removes edges from graph g. See remove-edges”) (remove-all [g] "Removes all nodes and edges from graph g” (nodes [g] "Return a collection of the nodes in graph g”) (edges [g] "Edges in g. May return each edge twice in an undirected graph")
  • 16. Loom's Graph API (defprotocol Graph (add-nodes* [g nodes] "Add nodes to graph g. See add-nodes” (add-edges* [g edges] "Add edges to graph g. See add-edges” (remove-nodes* [g nodes] "Remove nodes from graph g. See remove-nodes”) (remove-edges* [g edges] "Removes edges from graph g. See remove-edges”) (remove-all [g] "Removes all nodes and edges from graph g” (nodes [g] "Return a collection of the nodes in graph g”) (edges [g] "Edges in g. May return each edge twice in an undirected graph”) (has-node? [g node] "Return true when node is in g”) (has-edge? [g n1 n2] "Return true when edge [n1 n2] is in g")
  • 17. Loom's Graph API (defprotocol Graph (add-nodes* [g nodes] "Add nodes to graph g. See add-nodes” (add-edges* [g edges] "Add edges to graph g. See add-edges” (remove-nodes* [g nodes] "Remove nodes from graph g. See remove-nodes”) (remove-edges* [g edges] "Removes edges from graph g. See remove-edges”) (remove-all [g] "Removes all nodes and edges from graph g” (nodes [g] "Return a collection of the nodes in graph g”) (edges [g] "Edges in g. May return each edge twice in an undirected graph”) (has-node? [g node] "Return true when node is in g”) (has-edge? [g n1 n2] "Return true when edge [n1 n2] is in g”) (successors [g] [g node] "Return direct successors of node, or (partial successors g)”) (out-degree [g node] "Return the number of direct successors of node"))
  • 18. Loom's Graph API (defprotocol Digraph (predecessors [g] [g node] "Return direct predecessors of node, or (partial predecessors g)”) (in-degree [g node] "Return the number direct predecessors to node")
  • 19. Loom's Graph API (defprotocol Digraph (predecessors [g] [g node] "Return direct predecessors of node, or (partial predecessors g)”) (in-degree [g node] "Return the number direct predecessors to node”) (transpose [g] "Return a graph with all edges reversed"))
  • 20. Loom's Graph API (defprotocol WeightedGraph (weight [g] [g n1 n2] "Return weight of edge [n1 n2] or (partial weight g)"))
  • 21. Overview •  Loom's Graph API •  Graph Algorithms in Loom •  Titanium Loom •  SSA Loom
  • 22. Graph Algorithms in Loom •  DFS/BFS (+ bidirectional)
  • 23. Graph Algorithms in Loom •  DFS/BFS (+ bidirectional) •  Topological Sort
  • 24. Graph Algorithms in Loom •  DFS/BFS (+ bidirectional) •  Topological Sort •  Single Source Shortest Path (Dijkstra, Bellman-Ford)
  • 25. Graph Algorithms in Loom •  DFS/BFS (+ bidirectional) •  Topological Sort •  Single Source Shortest Path (Dijkstra, Bellman-Ford) •  Strongly Connected Components (Kosaraju)
  • 26. Graph Algorithms in Loom •  DFS/BFS (+ bidirectional) •  Topological Sort •  Single Source Shortest Path (Dijkstra, Bellman-Ford) •  Strongly Connected Components (Kosaraju) •  Density (edges/nodes)
  • 27. Graph Algorithms in Loom •  DFS/BFS (+ bidirectional) •  Topological Sort •  Single Source Shortest Path (Dijkstra, Bellman-Ford) •  Strongly Connected Components (Kosaraju) •  Density (edges/nodes) •  Loner nodes
  • 28. Graph Algorithms in Loom •  DFS/BFS (+ bidirectional) •  Topological Sort •  Single Source Shortest Path (Dijkstra, Bellman-Ford) •  Strongly Connected Components (Kosaraju) •  Density (edges/nodes) •  Loner nodes •  2 coloring
  • 29. Graph Algorithms in Loom •  DFS/BFS (+ bidirectional) •  Topological Sort •  Single Source Shortest Path (Dijkstra, Bellman-Ford) •  Strongly Connected Components (Kosaraju) •  Density (edges/nodes) •  Loner nodes •  2 coloring •  Max-Flow (Edmonds-Karp)
  • 30. Graph Algorithms in Loom •  DFS/BFS (+ bidirectional) •  Topological Sort •  Single Source Shortest Path (Dijkstra, Bellman-Ford) •  Strongly Connected Components (Kosaraju) •  Density (edges/nodes) •  Loner nodes •  2 coloring •  Max-Flow (Edmonds-Karp) •  alg-generic requires only successors + start (where appropriate)
  • 31. Graph Algorithms: Bellman-Ford A B C D E 3 4 5 2 -8
  • 32. Graph Algorithms: Bellman-Ford CLRS Introduction to Algorithms
  • 33. Graph Algorithms: Bellman-Ford CLRS Introduction to Algorithms
  • 34. Graph Algorithms: Bellman-Ford (defn- init-estimates "Initializes path cost estimates and paths from source to all vertices, for Bellman-Ford algorithm” [graph start] (let [nodes (disj (nodes graph) start) path-costs {start 0} paths {start nil} infinities (repeat Double/POSITIVE_INFINITY) nils (repeat nil) init-costs (interleave nodes infinities) init-paths (interleave nodes nils)] [(apply assoc path-costs init-costs) (apply assoc paths init-paths)]))
  • 37. Graph Algorithms: Bellman-Ford (defn- can-relax-edge? "Test for whether we can improve the shortest path to v found so far by going through u.” [[u v :as edge] weight costs] (let [vd (get costs v) ud (get costs u) sum (+ ud weight)] (> vd sum)))
  • 38. Graph Algorithms: Bellman-Ford (defn- relax-edge "If there's a shorter path from s to v via u, update our map of estimated path costs and map of paths from source to vertex v” [[u v :as edge] weight [costs paths :as estimates]] (let [ud (get costs u) sum (+ ud weight)] (if (can-relax-edge? edge weight costs) [(assoc costs v sum) (assoc paths v u)] estimates)))
  • 40. Graph Algorithms: Bellman-Ford (defn- relax-edges "Performs edge relaxation on all edges in weighted directed graph” [g start estimates] (->> (edges g) (reduce (fn [estimates [u v :as edge]] (relax-edge edge (wt g u v) estimates)) estimates)))
  • 41. Graph Algorithms: Bellman-Ford (defn bellman-ford "Given a weighted, directed graph G = (V, E) with source start, the Bellman-Ford algorithm produces map of single source shortest paths and their costs if no negative-weight cycle that is reachable from the source exits, and false otherwise, indicating that no solution exists." [g start] (let [initial-estimates (init-estimates g start) ;relax-edges is calculated for all edges V-1 times [costs paths] (reduce (fn [estimates _] (relax-edges g start estimates)) initial-estimates (-> g nodes count dec range)) edges (edges g)] (if (some (fn [[u v :as edge]] (can-relax-edge? edge (wt g u v) costs)) edges) false [costs (->> (keys paths) ;remove vertices that are unreachable from source (remove #(= Double/POSITIVE_INFINITY (get costs %))) (reduce (fn [final-paths v] (assoc final-paths v ; follows the parent pointers ; to construct path from source to node v (loop [node v path ()] (if node (recur (get paths node) (cons node path)) path)))) {}))])))
  • 42. Graph Algorithms: Bellman-Ford (defn bellman-ford "Given a weighted, directed graph G = (V, E) with source start, the Bellman-Ford algorithm produces map of single source shortest paths and their costs if no negative-weight cycle that is reachable from the source exits, and false otherwise, indicating that no solution exists."
  • 43. Graph Algorithms: Bellman-Ford [g start] (let [initial-estimates (init-estimates g start) ;relax-edges is calculated for all edges V-1 times [costs paths] (reduce (fn [estimates _] (relax-edges g start estimates)) initial-estimates (->> g (nodes) (count) (dec) (range))) edges (edges g)]
  • 44. Graph Algorithms: Bellman-Ford [g start] (let [initial-estimates (init-estimates g start) ;relax-edges is calculated for all edges V-1 times [costs paths] (reduce (fn [estimates _] (relax-edges g start estimates)) initial-estimates (->> g (nodes) (count) (dec) (range))) edges (edges g)]
  • 45. Graph Algorithms: Bellman-Ford (if (some (fn [[u v :as edge]] (can-relax-edge? edge (wt g u v) costs)) edges) false
  • 46. Graph Algorithms: Bellman-Ford [costs (->> (keys paths) ;remove vertices that are unreachable from source (remove #(= Double/POSITIVE_INFINITY (get costs %)))
  • 47. Graph Algorithms: Bellman-Ford [costs (->> (keys paths) ;remove vertices that are unreachable from source (remove #(= Double/POSITIVE_INFINITY (get costs %))) (reduce (fn [final-paths v] (assoc final-paths v ; follows the parent pointers ; to construct path from source to node v (loop [node v path ()] (if node (recur (get paths node) (cons node path)) path)))) {}))])))
  • 48. Overview •  Loom's Graph API •  Graph Algorithms •  Titanium Loom •  SSA Loom
  • 49. Titanium Loom •  Titanium by Clojurewerkz (titanium.clojurewerkz.org)
  • 50. Titanium Loom •  Titanium by Clojurewerkz (titanium.clojurewerkz.org) •  Clojure graph library built on top of Aurelius Titan (thinkaurelius.github.com/titan)
  • 51. Titanium Loom •  Titanium by Clojurewerkz (titanium.clojurewerkz.org) •  Clojure graph library built on top of Aurelius Titan (thinkaurelius.github.com/titan) •  Various storage backends: Cassandra, HBase, BerkeleyDB Java Edition
  • 52. Titanium Loom •  Titanium by Clojurewerkz (titanium.clojurewerkz.org) •  Clojure graph library built on top of Aurelius Titan (thinkaurelius.github.com/titan) •  Various storage backends: Cassandra, HBase, BerkeleyDB Java Edition •  No graph visualization
  • 53. Titanium Loom (let [in-mem-graph (tg/open {"storage.backend" "inmemory"})] (tg/transact! (let [ a (nodes/create! {:name "Node A"}) b (nodes/create! {:name "Node B"}) c (nodes/create! {:name "Node C"})
  • 54. Titanium Loom (let [in-mem-graph (tg/open {"storage.backend" "inmemory"})] (tg/transact! (let [ a (nodes/create! {:name "Node A"}) b (nodes/create! {:name "Node B"}) c (nodes/create! {:name "Node C"}) e1 (edges/connect! a "edge A->B" b) e2 (edges/connect! b "edge B->C" c) e3 (edges/connect! c "edge C->A” a) graph (titanium->loom in-mem-graph)])
  • 56. Titanium Loom (defn titanium->loom "Converts titanium graph into Loom representation” ([titanium-graph & {:keys [node-fn edge-fn weight-fn] :or {node-fn (nodes/get-all-vertices) edge-fn (map (juxt edges/tail-vertex edges/head-vertex) (edges/get-all-edges)) weight-fn (constantly 1)}}] (let [nodes-set (set node-fn) edges-set (set edge-fn)]
  • 57. Titanium Loom (reify Graph (nodes [_] nodes-set) (edges [_] edges-set) (has-node? [g node] (contains? (nodes g) node)) (has-edge? [g n1 n2] (contains? (edges g) [n1 n2])) (successors [g] (partial successors g)) (successors [g node] (filter (nodes g) (seq (nodes/connected-out-vertices node)))) (out-degree [g node] (count (successors g node)))
  • 58. Titanium Loom (reify Graph (nodes [_] nodes-set) (edges [_] edges-set) (has-node? [g node] (contains? (nodes g) node)) (has-edge? [g n1 n2] (contains? (edges g) [n1 n2])) (successors [g] (partial successors g)) (successors [g node] (filter (nodes g) (seq (nodes/connected-out-vertices node)))) (out-degree [g node] (count (successors g node))) Digraph (predecessors [g] (partial predecessors g)) (predecessors [g node] (filter (nodes g) (seq (nodes/connected-in-vertices node)))) (in-degree [g node] (count (predecessors g node))) WeightedGraph (weight [g] (partial weight g)) (weight [g n1 n2] (weight-fn n1 n2))))))
  • 59. Overview •  Loom's Graph API •  Graph Algorithms •  Titanium Loom •  SSA Loom
  • 60. SSA Loom •  Single Static Assignment (SSA) form produced by core.async
  • 61. SSA Loom •  Single Static Assignment (SSA) form produced by core.async •  Generated by parse-to-state-machine function
  • 62. SSA Loom (parse-to-state-machine '[(if (> (+ x 1 2 y) 0) (+ x 1) (+ x 2))])
  • 63. SSA Loom (parse-to-state-machine '[(if (> (+ x 1 2 y) 0) (+ x 1) (+ x 2))]) [inst_4938 {:current-block 76, :start-block 73, :block-catches {76 nil, 75 nil, 74 nil, 73 nil}, :blocks {76 [{:value :clojure.core.async.impl.ioc-macros/value, :id inst_4937} {:value inst_4937, :id inst_4938}], 75 [{:refs [clojure.core/+ x 2], :id inst_4935} {:value inst_4935, :block 76, :id inst_4936}], 74 [{:refs [clojure.core/+ x 1], :id inst_4933} {:value inst_4933, :block 76, :id inst_4934}], 73 [{:refs [clojure.core/+ x 1 2 y], :id inst_4930} {:refs [clojure.core/> inst_4930 0], :id inst_4931} {:test inst_4931, :then-block 74, :else-block 75, :id inst_4932}]}}]
  • 64. SSA Loom (def ssa (->> (parse-to-state-machine '[(if (> (+ x 1 2 y) 0) (+ x 1) (+ x 2))]) second :blocks))
  • 65. SSA Loom {76 [{:value :clojure.core.async.impl.ioc-macros/ value, :id inst_4937} {:value inst_4937, :id inst_4938}], 75 [{:refs [clojure.core/+ x 2], :id inst_4935} {:value inst_4935, :block 76, :id inst_4936}], 74 [{:refs [clojure.core/+ x 1], :id inst_4933} {:value inst_4933, :block 76, :id inst_4934}], 73 [{:refs [clojure.core/+ x 1 2 y], :id inst_4930} {:refs [clojure.core/> inst_4930 0], :id inst_4931} {:test inst_4931, :then-block 74, :else-block 75, :id inst_4932}]}}] (def ssa (->> (parse-to-state-machine '[(if (> (+ x 1 2 y) 0) (+ x 1) (+ x 2))]) second :blocks))
  • 66. SSA Loom (view (ssa->loom ssa ssa-nodes-fn ssa-edges-fn))
  • 67. SSA Loom (view (ssa->loom ssa ssa-nodes-fn ssa-edges-fn))
  • 68. SSA Loom (view (ssa->loom ssa ssa-nodes-fn ssa-edges-fn)) (defn ssa->loom "Converts the SSA form generated by core.async into Loom representation.” ([ssa node-fn edge-fn] (let [nodes (delay (node-fn ssa)) edges (delay (edge-fn ssa))]
  • 69. SSA Loom (view (ssa->loom ssa ssa-nodes-fn ssa-edges-fn)) {:graph (reify Graph (nodes [g] @nodes) (edges [g] @edges) (has-node? [g node] (contains? @nodes node)) (has-edge? [g n1 n2] (contains? @edges [n1 n2])) (successors [g] (partial successors g)) (successors [g node] (->> @edges (filter (fn [[n1 n2]] (= n1 node))) (map second))) (out-degree [g node] (count (successors g node)))
  • 70. SSA Loom (view (ssa->loom ssa ssa-nodes-fn ssa-edges-fn)) Digraph (predecessors [g] (partial predecessors g)) (predecessors [g node] (->> @edges (filter (fn [[n1 n2]] (= n2 node))) (map first))) (in-degree [g node] (count (predecessors g node)))) :data ssa})))
  • 71. SSA Loom: Dataflow Analysis •  For each basic block, solve system of equations until reaching fixed point: •  Use worklist approach
  • 72. SSA Loom: Dataflow Analysis (defn dataflow-analysis "Performs dataflow analysis. Nodes have value nil initially.” [& {:keys [start graph join transfer]}] (let [start (cond (set? start) start (coll? start) (set start) :else #{start})]
  • 73. SSA Loom: Dataflow Analysis (loop [out-values {} [node & worklist] (into clojure.lang.PersistentQueue/EMPTY start) (let [in-value (join (mapv out-values (predecessors graph node))) out (transfer node in-value) update? (not= out (get out-values node)) out-values (if update? (assoc out-values node out) out-values) worklist (if update? (into worklist (successors graph node)) worklist)]
  • 74. SSA Loom: Dataflow Analysis (loop [out-values {} [node & worklist] (into clojure.lang.PersistentQueue/EMPTY start (let [in-value (join (mapv out-values (predecessors graph node))) out (transfer node in-value) update? (not= out (get out-values node)) out-values (if update? (assoc out-values node out) out-values) worklist (if update? (into worklist (successors graph node)) worklist)] (if (seq worklist) (recur out-values worklist) out-values)))))
  • 75. SSA Loom: Global Availability (defn global-cse [ssa] (let [{graph :graph node-data :data} (ssa->loom (:blocks ssa) ssa-nodes-fn ssa-edges-fn) start (:start-block ssa)] (letfn [(pure? [instr] (contains? instr :refs)) (global-cse-join [values] (if (seq values) (apply set/intersection values) #{})) (global-cse-transfer [node in-value] (into in-value (map :refs (filter pure? (node-data node)))))]
  • 76. SSA Loom: Global Availability (defn global-cse [ssa] (let [{graph :graph node-data :data} (ssa->loom (:blocks ssa) ssa-nodes-fn ssa-edges-fn) start (:start-block ssa)] (letfn [(pure? [instr] (contains? instr :refs)) (global-cse-join [values] (if (seq values) (apply set/intersection values) #{})) (global-cse-transfer [node in-value] (into in-value (map :refs (filter pure? (node-data node)))))] (dataflow-analysis :start start :graph graph :join global-cse-join :transfer global-cse-transfer))))
  • 77. SSA Loom: Dataflow Analysis • Reaching definitions
  • 78. SSA Loom: Dataflow Analysis • Reaching definitions • Liveness analysis (dead code elimination)
  • 79. SSA Loom: Dataflow Analysis • Reaching definitions • Liveness analysis (dead code elimination) • Available expressions
  • 80. SSA Loom: Dataflow Analysis • Reaching definitions • Liveness analysis (dead code elimination) • Available expressions • Constant propagation
  • 81. SSA Loom: Dataflow Analysis • Reaching definitions • Liveness analysis (dead code elimination) • Available expressions • Constant propagation • Other Applications:
  • 82. SSA Loom: Dataflow Analysis • Reaching definitions • Liveness analysis (dead code elimination) • Available expressions • Constant propagation • Other Applications: o  Erdős number
  • 83. SSA Loom: Dataflow Analysis • Reaching definitions • Liveness analysis (dead code elimination) • Available expressions • Constant propagation • Other Applications: o  Erdős number o  Spread of information in systems (e.g. taint)
  • 84. My Experience • Intuitive way to implement algorithms functionally • Some mental overhead of transforming data structures
  • 85. Open Questions • How general should a graph API be?
  • 86. Open Questions • How general should a graph API be? • How feature-rich should a graph API be?