graph-curry
Version:
a Map based implementation of canonical graph data algorithms
226 lines (156 loc) • 9.46 kB
HTML
<html>
<head>
<title>search.js</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
<link rel="stylesheet" media="all" href="docco.css" />
</head>
<body>
<div id="container">
<div id="background"></div>
<ul id="jump_to">
<li>
<a class="large" href="javascript:void(0);">Jump To …</a>
<a class="small" href="javascript:void(0);">+</a>
<div id="jump_wrapper">
<div id="jump_page_wrapper">
<div id="jump_page">
<a class="source" href="components.html">
components.js
</a>
<a class="source" href="contract.html">
contract.js
</a>
<a class="source" href="cut.html">
cut.js
</a>
<a class="source" href="graph.html">
graph.js
</a>
<a class="source" href="index.html">
index.js
</a>
<a class="source" href="path.html">
path.js
</a>
<a class="source" href="reducers.html">
reducers.js
</a>
<a class="source" href="search.html">
search.js
</a>
<a class="source" href="show.html">
show.js
</a>
<a class="source" href="tree.html">
tree.js
</a>
</div>
</div>
</li>
</ul>
<ul class="sections">
<li id="title">
<div class="annotation">
<h1>search.js</h1>
</div>
</li>
<li id="section-1">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-1">¶</a>
</div>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">import</span> { addBinSet, asSet, get, hasK, lastK, mapDiff, popFirst, spread, spreadK, } <span class="hljs-keyword">from</span> <span class="hljs-string">'fenugreek-collections'</span>;
<span class="hljs-keyword">import</span> { initPath, nextPath, } <span class="hljs-keyword">from</span> <span class="hljs-string">'./path'</span>;
<span class="hljs-keyword">import</span> { components, } <span class="hljs-keyword">from</span> <span class="hljs-string">'./components'</span>;</pre></div></div>
</li>
<li id="section-2">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">¶</a>
</div>
<p><strong>dfs</strong> <code>:: Map<edge> -> node -> Map<pathEntry></code>
depth first traversal</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> dfs = <span class="hljs-function"><span class="hljs-params">edges</span> =></span> (src) => {</pre></div></div>
</li>
<li id="section-3">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">¶</a>
</div>
<blockquote>
<p><strong>dfs.trav</strong> <code>:: Map<pathEntry> -> [node, w] -> Map<pathEntry></code>
depth first traversal</p>
</blockquote>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">const</span> trav = <span class="hljs-function">(<span class="hljs-params">path = initPath(src</span>), [ <span class="hljs-params">n</span>, <span class="hljs-params">w</span> ] = [ <span class="hljs-params">lastK</span>(<span class="hljs-params">path</span>), 0 ]) =></span>
spread(mapDiff(edges.get(n))(path)).reduce(trav, nextPath(path, [ n, w ]));
<span class="hljs-keyword">return</span> trav(initPath(src));
};</pre></div></div>
</li>
<li id="section-4">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">¶</a>
</div>
<p><strong>bfs</strong> <code>:: Map<edge> -> node -> Map<pathEntry></code>
breadth first traversal</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> bfs = <span class="hljs-function"><span class="hljs-params">edges</span> =></span> (iNode) => {
<span class="hljs-keyword">const</span> bVisit = <span class="hljs-function"><span class="hljs-params">bPath</span> =></span> (bQueue) => {
<span class="hljs-keyword">const</span> pred = popFirst(bQueue);
<span class="hljs-keyword">const</span> nextNabes = mapDiff(edges.get(pred))(bPath);
spread(nextNabes).reduce(nextPath, bPath);
spreadK(nextNabes).reduce(addBinSet, bQueue);
<span class="hljs-keyword">return</span> bQueue.size > <span class="hljs-number">0</span> ? bVisit(bPath)(bQueue) : bPath;
};
<span class="hljs-keyword">return</span> bVisit(initPath(iNode))(asSet([ iNode ]));
};</pre></div></div>
</li>
<li id="section-5">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">¶</a>
</div>
<p><strong>dijkstra</strong> <code>:: Map<edge> -> node -> Map<pathEntry></code>
finds shortest paths from a source node to all node reachable from that node</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> dijkstra = <span class="hljs-function"><span class="hljs-params">edges</span> =></span> (iNode) => {
<span class="hljs-keyword">const</span> reachables = bfs(edges)(iNode);
<span class="hljs-keyword">const</span> inspectQueue = asSet([ iNode ]);
<span class="hljs-keyword">const</span> solutionSet = initPath(iNode);
<span class="hljs-keyword">while</span> (inspectQueue.size > <span class="hljs-number">0</span>) {
<span class="hljs-keyword">const</span> pred = popFirst(inspectQueue);
<span class="hljs-keyword">const</span> nextNabes = edges.get(pred);
<span class="hljs-keyword">const</span> { <span class="hljs-attr">length</span>: dCount, <span class="hljs-attr">weight</span>: dWeight } = solutionSet.get(pred);
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> [ nabe, nWeight ] <span class="hljs-keyword">of</span> nextNabes) {
<span class="hljs-keyword">const</span> prevMap = reachables.get(nabe) || { <span class="hljs-attr">length</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">weight</span>: <span class="hljs-number">0</span> };
<span class="hljs-keyword">const</span> { <span class="hljs-attr">length</span>: rCount, <span class="hljs-attr">weight</span>: rWeight } = prevMap;
<span class="hljs-keyword">const</span> dMap = { pred, <span class="hljs-attr">length</span>: dCount + <span class="hljs-number">1</span>, <span class="hljs-attr">weight</span>: dWeight + nWeight, };
<span class="hljs-keyword">const</span> sMap = ((dWeight + nWeight) < rWeight) ? dMap : prevMap;
<span class="hljs-keyword">if</span> (!solutionSet.has(nabe)) {
inspectQueue.add(nabe);
solutionSet.set(nabe, sMap);
}
}
}
<span class="hljs-keyword">return</span> solutionSet;
};</pre></div></div>
</li>
<li id="section-6">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">¶</a>
</div>
<p><strong>pathBetween</strong> <code>:: Map<edge> -> node -> node -> Boolean</code>
checks for a path between two nodes</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> pathBetween = <span class="hljs-function"><span class="hljs-params">e</span> =></span> n0 => <span class="hljs-function"><span class="hljs-params">n1</span> =></span> hasK(get(components(e))(n0))(n1);</pre></div></div>
</li>
</ul>
</div>
</body>
</html>