UNPKG

graph-curry

Version:

a Map based implementation of canonical graph data algorithms

226 lines (156 loc) 9.46 kB
<!DOCTYPE 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 &hellip;</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">&#182;</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">&#182;</a> </div> <p><strong>dfs</strong> <code>:: Map&lt;edge&gt; -&gt; node -&gt; Map&lt;pathEntry&gt;</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> =&gt;</span> (src) =&gt; {</pre></div></div> </li> <li id="section-3"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-3">&#182;</a> </div> <blockquote> <p><strong>dfs.trav</strong> <code>:: Map&lt;pathEntry&gt; -&gt; [node, w] -&gt; Map&lt;pathEntry&gt;</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 ]) =&gt;</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">&#182;</a> </div> <p><strong>bfs</strong> <code>:: Map&lt;edge&gt; -&gt; node -&gt; Map&lt;pathEntry&gt;</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> =&gt;</span> (iNode) =&gt; { <span class="hljs-keyword">const</span> bVisit = <span class="hljs-function"><span class="hljs-params">bPath</span> =&gt;</span> (bQueue) =&gt; { <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 &gt; <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">&#182;</a> </div> <p><strong>dijkstra</strong> <code>:: Map&lt;edge&gt; -&gt; node -&gt; Map&lt;pathEntry&gt;</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> =&gt;</span> (iNode) =&gt; { <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 &gt; <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) &lt; 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">&#182;</a> </div> <p><strong>pathBetween</strong> <code>:: Map&lt;edge&gt; -&gt; node -&gt; node -&gt; 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> =&gt;</span> n0 =&gt; <span class="hljs-function"><span class="hljs-params">n1</span> =&gt;</span> hasK(get(components(e))(n0))(n1);</pre></div></div> </li> </ul> </div> </body> </html>