graph-data-structure
Version:
A graph data structure with topological sort.
3 lines (2 loc) • 6.25 kB
JavaScript
function e(e,t){if(!1===e||null==e)throw console.warn("Test invariant failed:",t),new Error(t)}class t{nodes=new Set;edges=new Map;edgeWeights=new Map;edgeProperties=new Map;addNode(e){return this.nodes.has(e)||this.nodes.add(e),this.edges.has(e)||this.edges.set(e,new Set),this}removeNode(e){this.edges.delete(e),this.nodes.delete(e);for(const t of this.edges.values())t.delete(e);return this}adjacent(e){return this.edges.get(e)}setEdgeWeight(t,r,o){this.edgeWeights.has(t)||this.edgeWeights.set(t,new Map);const n=this.edgeWeights.get(t);return e(n),n.set(r,o),this}getEdgeWeight(e,t){return this.edgeWeights.get(e)?.get(t)??1}setEdgeProperties(t,r,o){this.edgeProperties.has(t)||this.edgeProperties.set(t,new Map);const n=this.edgeProperties.get(t);return e(n),n.set(r,o),this}getEdgeProperties(e,t){return this.edgeProperties.get(e)?.get(t)}addEdge(t,r,...o){let n,s;const d=o[0];"number"==typeof d&&(n=d),"object"==typeof d&&(n=d.weight,d&&(s=Object.prototype.hasOwnProperty.call(d,"props")?d.props:void 0)),this.addNode(t),this.addNode(r);const i=this.adjacent(t);return e(i),i.add(r),void 0!==n&&this.setEdgeWeight(t,r,n),void 0!==s&&this.setEdgeProperties(t,r,s),this}removeEdge(e,t){return this.edges.get(e)?.delete(t),this.edgeProperties.get(e)?.delete(t),this}hasEdge(e,t){return this.edges.get(e)?.has(t)??!1}}class r extends Error{constructor(e){super(e),Object.setPrototypeOf(this,r.prototype)}}function o(e,t,n,s,d,i){const{errorOnCycle:g=!1,shouldFollow:h}=i;if(s.has(d)&&g)throw new r("Cycle found");n.has(d)||(n.add(d),s.add(d),e.adjacent(d)?.forEach((r=>{(void 0===h||h({source:d,target:r,graph:e,props:e.getEdgeProperties(d,r)}))&&o(e,t,n,s,r,i)})),s.delete(d),t.push(d))}function n(e,t={}){const{sourceNodes:r=Array.from(e.nodes),includeSourceNodes:n=!0}=t,s=new Set,d=new Set,i=[];if(n){for(let n=0;n<r.length;n++){const g=r[n];g&&o(e,i,s,d,g,t)}return i}for(let e=0;e<r.length;e++){const t=r[e];t&&s.add(t)}for(let n=0;n<r.length;n++){const g=r[n];g&&e.adjacent(g)?.forEach((r=>o(e,i,s,d,r,t)))}return i}function s(e){let t,r=1/0;const{d:o,q:n}=e;return n.forEach((e=>{const n=o.get(e)??1/0;n<r&&(r=n,t=e)})),void 0===t?(n.clear(),null):(n.delete(t),t)}function d(t,r,o,n){const{d:s,p:d}=r,i=t.getEdgeWeight(o,n),g=s.get(o),h=s.get(n);e(g,"Missing source distance"),e(h,"Missing target distance"),h>g+i&&(s.set(n,g+i),d.set(n,o))}function i(e,t,r,o){const n=e.nodes,{q:i}=t;for(!function(e,{d:t},r,o){if(e.forEach((e=>{t.set(e,1/0)})),t.get(r)!==1/0)throw new Error("Source node is not in the graph");if(t.get(o)!==1/0)throw new Error("Destination node is not in the graph");t.set(r,0)}(n,t,r,o),function(e,{q:t}){e.forEach((e=>{t.add(e)}))}(n,t);0!==i.size;){const r=s(t);if(null===r)return;e.adjacent(r)?.forEach((o=>{d(e,t,r,o)}))}}function g(e){return void 0===e.currentPathWeight?e.edgeWeight:e.edgeWeight+e.currentPathWeight}function h(t,r,o,n=g){const s={d:new Map,p:new Map,q:new Set};return i(t,s,r,o),function(t,r,o,n,s=g){const{p:d}=r,i=[];let h,c=n;for(;d.has(c);){const e=d.get(c);i.push(c),c=e}if(c!==o)throw new Error("No path found");i.push(c),i.reverse(),e(i.length>=2,"The path should have a least two nodes");for(let e=1;e<i.length;e++){const r=i[e-1],o=i[e],n=t.getEdgeWeight(r,o),d=t.getEdgeProperties(r,o);h=s({edgeWeight:n,currentPathWeight:h,hop:e,graph:t,path:i,previousNode:r,currentNode:o,props:d})}return{nodes:i,weight:h}}(t,s,r,o,n)}function c(e,t,r){let o=h(e,t,r);const n=[o],s=o.weight,d=[];for(;o.weight;){const i=o.nodes[0],g=o.nodes[1];e.hasEdge(i,g)&&(d.push({u:i,v:g,weight:e.getEdgeWeight(i,g),props:e.getEdgeProperties(i,g)}),e.removeEdge(i,g)),e.hasEdge(g,i)&&(d.push({u:g,v:i,weight:e.getEdgeWeight(g,i),props:e.getEdgeProperties(g,i)}),e.removeEdge(g,i));try{if(o=h(e,t,r),!o.weight||!s||s<o.weight)break;n.push(o)}catch(e){break}}for(const{u:t,v:r,weight:o,props:n}of d)e.addEdge(t,r,o,n);return n}function a(e,t={}){return n(e,{...t,errorOnCycle:!0}).reverse()}function u(e,t,r){const o=[],n=[];return f(e,o,n,new Set,t,r)&&p(e,o,n,new Set,r),n}function f(e,t,r,o,n,s){return!!o.has(n)||(o.add(n),t.push(n),n==s?(r.push(n),!1):Array.from(e.adjacent(n)??[]).every((n=>f(e,t,r,o,n,s))))}function p(e,t,r,o,n){o.has(n)||(o.add(n),t.indexOf(n)>=0?r.push(n):0==r.length&&e.adjacent(n)?.forEach((n=>{p(e,t,r,o,n)})))}function l(e,t){let r=0;for(const o of e.edges.values())for(let e of o)e===t&&r++;return r}function w(e,t){return e.edges.get(t)?.size??0}function E(e){const r=new t;for(let[t,o]of e.edges.entries())o.forEach((o=>{r.addEdge.apply(r,[t,o]);const n=e.edgeWeights.get(t)?.get(o);n&&r.setEdgeWeight(t,o,n);const s=e.getEdgeProperties(t,o);s&&r.setEdgeProperties(t,o,s)}));return r}function v(e,t){try{return n(e,{...t,includeSourceNodes:!0,errorOnCycle:!0}),!1}catch(e){if(e instanceof r)return!0;throw e}}function W(e,...t){const r="function"==typeof t[0]?t[0]:void 0,o="function"==typeof t[0]?t[1]:t[0],{includeDefaultWeight:n=!1}=o??{},s={nodes:Array.from(e.nodes),links:[]},d=new Map;return s.nodes.forEach((t=>{const o=t;e.adjacent(o)?.forEach((t=>{const i=e.getEdgeWeight(o,t),g=e.getEdgeProperties(o,t);r&&!d.has(o)&&d.set(o,r(o)),r&&!d.has(t)&&d.set(t,r(t));const h={source:d.get(o)??o,target:d.get(t)??t};(1!=i||n)&&(h.weight=i),g&&(h.props=g),s.links.push(h)}))})),s}function y(...e){const[r,o]=e,n=new t,s=new Map;return r.nodes.forEach((e=>{n.addNode(e),o&&s.set(o(e),e)})),r.links.forEach((e=>{if(!o)return void n.addEdge.apply(n,[e.source,e.target,e.weight,e.props]);const t=s.get(o(e.source))??e.source,r=s.get(o(e.target))??e.target;n.addEdge.apply(n,[t,r,e.weight,e.props])})),n}function P(e,t){const r=[];return e.nodes.forEach((e=>{t(e)&&r.push(e)})),r}function N(e,t){const r=[];for(const o of e.nodes)t(o)&&r.push(o);if(0===r.length)throw new Error("Node not found.");if(r.length>1)throw new Error("More than one node found.");return r[0]}function M(e,t){for(const r of e.nodes)if(t(r))return r;throw new Error("Node not found.")}export{r as CycleError,t as Graph,E as cloneGraph,n as depthFirstSearch,y as deserializeGraph,P as findNodes,M as getFirstNode,N as getNode,v as hasCycle,l as indegree,u as lowestCommonAncestors,w as outdegree,W as serializeGraph,h as shortestPath,c as shortestPaths,a as topologicalSort};
//# sourceMappingURL=index.mjs.map