69
Loom and Graphs in Clojure github.com/aysylu/loom Aysylu Greenberg @aysylu22; http://aysy.lu March 25 th 2014

Loom at Clojure/West

Embed Size (px)

DESCRIPTION

Slides from the talk on Loom and Graphs in Clojure by Aysylu Greenberg at Clojure/West.

Citation preview

Page 1: Loom at Clojure/West

Loom and Graphs in Clojure

github.com/aysylu/loom

Aysylu Greenberg

@aysylu22; http://aysy.lu March 25th 2014

Page 2: Loom at Clojure/West

Graphs

Page 3: Loom at Clojure/West

Loom

Graph Algorithms + Visualization

Page 4: Loom at Clojure/West

In this Talk

Loom Overview

Loom’s Graph

API

Functional Graph

Algorithms Your

Graphs in Loom

Page 5: Loom at Clojure/West

In this Talk

Loom Overview

Loom’s Graph

API

Functional Graph

Algorithms Your

Graphs in Loom

Page 6: Loom at Clojure/West

Loom Overview: Supported Graphs

•  Undirected Graph •  Directed Graph (Digraph) •  Weighted Graph •  FlyGraph o  nodes + successors edges o  successors + start nodes + edges

Page 7: Loom at Clojure/West

Loom Overview: Graph Algorithms

• DFS/BFS (+ bidirectional)

Page 8: Loom at Clojure/West

Loom Overview: Graph Algorithms

• DFS/BFS (+ bidirectional) • Topological Sort

Page 9: Loom at Clojure/West

Loom Overview: Graph Algorithms

• DFS/BFS (+ bidirectional) • Topological Sort • Single Source Shortest Path (Dijkstra,

Bellman-Ford)

Page 10: Loom at Clojure/West

Loom Overview: Graph Algorithms

• DFS/BFS (+ bidirectional) • Topological Sort • Single Source Shortest Path (Dijkstra,

Bellman-Ford) • Strongly Connected Components (Kosaraju)

Page 11: Loom at Clojure/West

Loom Overview: Graph Algorithms

• DFS/BFS (+ bidirectional) • Topological Sort • Single Source Shortest Path (Dijkstra,

Bellman-Ford) • Strongly Connected Components (Kosaraju) • Density (edges/nodes) • Loner Nodes

• DFS/BFS (+ bidirectional) • Topological Sort • Single Source Shortest Path (Dijkstra,

Bellman-Ford) • Strongly Connected Components (Kosaraju)

Page 12: Loom at Clojure/West

Loom Overview: Graph Algorithms

• DFS/BFS (+ bidirectional) • Topological Sort • Single Source Shortest Path (Dijkstra,

Bellman-Ford) • Strongly Connected Components (Kosaraju) • Density (edges/nodes) • Loner Nodes • Two Coloring

Page 13: Loom at Clojure/West

Loom Overview: Graph Algorithms

• DFS/BFS (+ bidirectional) • Topological Sort • Single Source Shortest Path (Dijkstra,

Bellman-Ford) • Strongly Connected Components (Kosaraju) • Density (edges/nodes) • Loner Nodes • Two Coloring • Max-Flow (Edmonds-Karp)

Page 14: Loom at Clojure/West

Loom Overview: Visualizing Graphs

Page 15: Loom at Clojure/West

In this Talk

Loom Overview

Loom’s Graph

API

Functional Graph

Algorithms Your

Graphs in Loom

Page 16: Loom at Clojure/West

Graph API: Representations

Page 17: Loom at Clojure/West

Graph API: Representations

• Adjacency List {A: [B], B: [C, D], C: [], …}

Page 18: Loom at Clojure/West

Graph API: Representations

• Adjacency List •  Incidence List {A: [e1], B: [e2, e3], …, e1: [A, B], e2: [B, C], …}

Page 19: Loom at Clojure/West

Graph API: Representations

• Adjacency List •  Incidence List • Adjacency Matrix Source Destination

A B … E A 0 1 … ∞ B ∞ 0 … ∞ … … … … … E ∞ 1 … 0

Page 20: Loom at Clojure/West

Graph API: Representations

• Adjacency List •  Incidence List • Adjacency Matrix •  Incidence Matrix

Nodes Edges e1 e2 .. e5

A S N … N B D S … D … … … … … E N N … S

Page 21: Loom at Clojure/West

Graph API: Representations

• Adjacency List sparse graphs •  Incidence List • Adjacency Matrix dense graphs •  Incidence Matrix

Page 22: Loom at Clojure/West

Graph API: Graph (defprotocol Graph! (nodes [g])! (edges [g])! (has-node? [g node])! (has-edge? [g n1 n2])! (successors [g] [g node])! (out-degree [g node]))!

Page 23: Loom at Clojure/West

Graph API: Digraph (defprotocol Digraph! (predecessors [g] [g node])! (in-degree [g node])! (transpose [g]))

Page 24: Loom at Clojure/West

Graph API: WeightedGraph (defprotocol WeightedGraph! (weight [g] [g n1 n2]))

Page 25: Loom at Clojure/West

Graph API: EditableGraph (defprotocol EditableGraph! (add-nodes* [g nodes])! (add-edges* [g edges])! (remove-nodes* [g nodes])! (remove-edges* [g edges])! (remove-all [g]))

Page 26: Loom at Clojure/West

Graph API: Complex Graphs

How to create basic editable digraph? (defrecord BasicEditableDigraph! [nodes succs preds])!

Page 27: Loom at Clojure/West

Graph API: Complex Graphs

How to create basic editable digraph? (defrecord BasicEditableDigraph! [nodes succs preds])!(extend BasicEditableDigraph! Graph …! Digraph …! EditableGraph …)!

Page 28: Loom at Clojure/West

Graph API: Complex Graphs

How to create basic editable digraph? (defrecord BasicEditableDigraph! [nodes succs preds])!(extend BasicEditableDigraph! Graph!!!!!)!

(nodes [g])!(edges [g])!(has-node? [g node])!(has-edge? [g n1 n2])!(successors [g] [g node])!(out-degree [g node])

Protocol definition (not valid code!)

Page 29: Loom at Clojure/West

Graph API: Complex Graphs

How to create basic editable digraph? (defrecord BasicEditableDigraph! [nodes succs preds])!(extend BasicEditableDigraph! Graph default-graph-impl! Digraph …! EditableGraph …)!

Page 30: Loom at Clojure/West

Graph API: Complex Graphs (def default-graph-impl! {:edges! (fn [g]! (for [n1 (nodes g)! n2 (successors g n1)]! [n1 n2]))! :nodes (fn [g] ...)! ...})!

(nodes [g])!(edges [g])!(has-node? [g node])!(has-edge? [g n1 n2])!(successors [g] [g node])!(out-degree [g node])

Page 31: Loom at Clojure/West

Graph API: Complex Graphs

How to create basic editable digraph? (defrecord BasicEditableDigraph! [nodes succs preds])!(extend BasicEditableDigraph! Graph default-graph-impl! Digraph …! EditableGraph …)!

Page 32: Loom at Clojure/West

Graph API: Complex Graphs

How to create basic editable digraph? (defrecord BasicEditableDigraph! [nodes succs preds])!(extend BasicEditableDigraph! Graph default-graph-impl! Digraph default-digraph-impl! EditableGraph …)!

Page 33: Loom at Clojure/West

Graph API: Complex Graphs

(def default-digraph-impl! {:transpose! (fn [g]! (assoc g! :succs (:preds g)! :preds (:succs g)))! …})

(predecessors [g]!! ! [g node])!

(in-degree [g node])!(transpose [g])

Page 34: Loom at Clojure/West

Graph API: Complex Graphs

How to create basic editable digraph? (defrecord BasicEditableDigraph! [nodes succs preds])!(extend BasicEditableDigraph! Graph default-graph-impl! Digraph default-digraph-impl! EditableGraph …)!

Page 35: Loom at Clojure/West

Graph API: Complex Graphs

How to create basic editable digraph? (defrecord BasicEditableDigraph! [nodes succs preds])!(extend BasicEditableDigraph! Graph default-graph-impl! Digraph default-digraph-impl! EditableGraph editable-graph-impl)!

Page 36: Loom at Clojure/West

In this Talk

Loom Overview

Loom’s Graph

API

Functional Graph

Algorithms Your

Graphs in Loom

Page 37: Loom at Clojure/West

Functional Graph Algorithms: Bellman-Ford

Page 38: Loom at Clojure/West

Functional Graph Algorithms: Bellman-Ford

CLRS Introduction to Algorithms

Page 39: Loom at Clojure/West

Functional Graph Algorithms: Bellman-Ford

CLRS Introduction to Algorithms

Page 40: Loom at Clojure/West

Functional Graph Algorithms: Bellman-Ford

(defn- init-estimates! [graph start]! (let [nodes (disj (nodes graph) start)! costs (interleave nodes! (repeat 1e999M))! paths (interleave nodes (repeat nil))]! [(apply assoc {start 0} costs)! (apply assoc {start nil} paths)]))

Page 41: Loom at Clojure/West

Functional Graph Algorithms: Bellman-Ford

Page 42: Loom at Clojure/West

Functional Graph Algorithms: Bellman-Ford

Page 43: Loom at Clojure/West

Functional Graph Algorithms: Bellman-Ford

(defn- can-relax-edge?! [[u v :as edge] edge-cost costs]! (let [vd (get costs v)! ud (get costs u)! sum (+ ud edge-cost)]! (> vd sum)))

Page 44: Loom at Clojure/West

Functional Graph Algorithms: Bellman-Ford

(defn- relax-edge! [[u v :as edge]! uvcost! [costs paths :as estimates]]! (let [ud (get costs u)! sum (+ ud uvcost)]! (if (can-relax-edge? edge uvcost costs)! [(assoc costs v sum)! (assoc paths v u)]! estimates)))

Page 45: Loom at Clojure/West

Functional Graph Algorithms: Bellman-Ford

Page 46: Loom at Clojure/West

Functional Graph Algorithms: Bellman-Ford

(defn- relax-edges! [g start estimates]! (reduce (fn [estimates [u v :as edge]]! (relax-edge! edge! (weight g u v)!

! estimates))! estimates! (edges g)))!

Page 47: Loom at Clojure/West

Functional Graph Algorithms: Bellman-Ford

(defn 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)]!

(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))))!

{}))])))

Page 48: Loom at Clojure/West

Functional Graph Algorithms: Bellman-Ford

(defn 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)]!

Page 49: Loom at Clojure/West

Functional Graph Algorithms: Bellman-Ford

(if (some (fn [[u v :as edge]]! (can-relax-edge? edge!

! ! ! ! ! (weight g u v)!! ! ! ! ! costs))!! ! edges)!

false!! !;;; return paths))) !

Page 50: Loom at Clojure/West

Functional Graph Algorithms: loom.alg-generic

• No knowledge of graph representation • Requires only successors

o + start for DFS/BFS, topological sort, Dijkstra o + end for BFS path

Page 51: Loom at Clojure/West

In this Talk

Loom Overview

Loom’s Graph

API

Functional Graph

Algorithms Your

Graphs in Loom

Page 52: Loom at Clojure/West

Your Graphs in Loom

core.async Single Static Assignment Form

Titanium-Loom

Github

And more!

Page 53: Loom at Clojure/West

Your Graphs in Loom

core.async Single Static Assignment Form

Titanium-Loom

Github

And more!

Page 54: Loom at Clojure/West

SSA Loom

•  Single Static Assignment (SSA) form produced by core.async

•  Generated by parse-to-state-machine function

Page 55: Loom at Clojure/West

SSA Loom

(parse-to-state-machine! '[(if (> (+ 1 2 x y) 0)! (+ x 1)! (+ x 2))])

{76 [{:value :clojure.core.async.impl.ioc-macros/

value, :id inst_4937} {:value inst_4937, :id inst_4938}], 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}]}}]

Page 56: Loom at Clojure/West

SSA Loom (view (ssa->loom ssa ssa-node-fn ssa-edges-fn))

if (> (+ 1 2 x y) 0)!

V (+ x 1)!V (+ x 2)

V!

Page 57: Loom at Clojure/West

SSA Loom (view (ssa->loom ssa ssa-node-fn ssa-edges-fn))!!

(defn ssa->loom! ([ssa get-nodes get-edges]!

Page 58: Loom at Clojure/West

SSA Loom (view (ssa->loom ssa ssa-nodes-fn ssa-edges-fn))!!

(reify! Graph! (nodes [g] (get-nodes ssa))! …! (successors [g node]! (->> edges! (filter (fn [[n1 n2]]! (= n1 node)))! (map second)))! …!

Page 59: Loom at Clojure/West

SSA Loom (view (ssa->loom ssa ssa-nodes-fn ssa-edges-fn))!!

Digraph! (predecessors [g node]! (->> edges! (filter (fn [[n1 n2]]! (= n2 node)))! (map first)))! …))

Page 60: Loom at Clojure/West

Your Graphs in Loom

core.async Single Static Assignment Form

Titanium-Loom

Github

And more!

Page 61: Loom at Clojure/West

Titanium Loom

•  Titanium by Clojurewerkz (titanium.clojurewerkz.org)

•  Built on top of Aurelius Titan (thinkaurelius.github.com/titan)

•  Storage backends: Cassandra, HBase, BerkeleyDB Java Edition

•  No graph visualization

Page 62: Loom at Clojure/West

Titanium Loom (let [in-mem-graph! (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 b)! e2 (edges/connect! b c)! e3 (edges/connect! c a)]))! (titanium->loom in-mem-graph))

Page 63: Loom at Clojure/West

Titanium Loom (view graph)

Page 64: Loom at Clojure/West

Your Graphs in Loom

Titanium-Loom

core.async Single Static Assignment Form

Github

And more!

Page 65: Loom at Clojure/West

Data Flow Analysis Framework

• Liveness analysis (dead code elimination) • Constant propagation • Taint analysis • Clojure Repos + Relationships

Page 66: Loom at Clojure/West

Github: Clojure Repos + Relations

•  For each Clojure project, solve system of equations until reaching fixed point:

Page 67: Loom at Clojure/West

Github: Clojure Repos + Relations

Quil

math.numeric-tower

Page 68: Loom at Clojure/West

Github: Clojure Repos + Relations

core.async

clojure-ring

clout > compojure

core.match

Page 69: Loom at Clojure/West

Loom’s Vision

The Graph Library in Clojure

github.com/aysylu/loom