UNPKG

@graphty/algorithms

Version:

Graph algorithms library for browser environments implemented in TypeScript

196 lines 5.51 kB
import { Graph } from "../core/graph.js"; /** * Convert Graph class to Map representation * Used by community detection and flow algorithms */ export function graphToMap(graph) { const map = new Map(); // Initialize all nodes for (const node of graph.nodes()) { map.set(String(node.id), new Map()); } // Add edges with weights for (const edge of graph.edges()) { const source = String(edge.source); const target = String(edge.target); const weight = edge.weight ?? 1; const sourceMap = map.get(source); if (sourceMap) { sourceMap.set(target, weight); } // For undirected graphs, add reverse edge if (!graph.isDirected) { const targetMap = map.get(target); if (targetMap) { targetMap.set(source, weight); } } } return map; } /** * Convert Map representation to Graph class */ export function mapToGraph(map, isDirected = true) { const graph = new Graph({ directed: isDirected }); // Add all nodes first for (const node of map.keys()) { graph.addNode(node); } // Add edges const processedEdges = new Set(); for (const [source, neighbors] of map) { for (const [target, weight] of neighbors) { const edgeKey = isDirected ? `${source}->${target}` : [source, target].sort().join("-"); // Skip if we've already processed this edge (for undirected graphs) if (!isDirected && processedEdges.has(edgeKey)) { continue; } graph.addEdge(source, target, weight); processedEdges.add(edgeKey); } } return graph; } /** * Adapter for using Graph algorithms with Map representation * Implements a subset of Graph interface methods needed by algorithms */ export class GraphAdapter { constructor(map, isDirected = true) { this.map = map; this.isDirected = isDirected; } /** * Get all nodes */ nodes() { return Array.from(this.map.keys()).map((id) => ({ id })); } /** * Get node count */ get nodeCount() { return this.map.size; } /** * Check if node exists */ hasNode(nodeId) { return this.map.has(String(nodeId)); } /** * Get neighbors of a node */ neighbors(nodeId) { const neighbors = this.map.get(String(nodeId)); if (!neighbors) { return []; } return Array.from(neighbors.keys()); } /** * Get edge between two nodes */ getEdge(source, target) { const sourceNeighbors = this.map.get(String(source)); if (!sourceNeighbors) { return null; } const weight = sourceNeighbors.get(String(target)); if (weight === undefined) { return null; } return { source, target, weight }; } /** * Check if edge exists */ hasEdge(source, target) { const sourceNeighbors = this.map.get(String(source)); if (!sourceNeighbors) { return false; } return sourceNeighbors.has(String(target)); } /** * Get all edges */ edges() { const edges = []; const processedEdges = new Set(); for (const [source, neighbors] of this.map) { for (const [target, weight] of neighbors) { const edgeKey = this.isDirected ? `${source}->${target}` : [source, target].sort().join("-"); // Skip if we've already processed this edge (for undirected graphs) if (!this.isDirected && processedEdges.has(edgeKey)) { continue; } edges.push({ source, target, weight }); processedEdges.add(edgeKey); } } return edges; } /** * Get edge count */ get edgeCount() { if (this.isDirected) { let count = 0; for (const neighbors of this.map.values()) { count += neighbors.size; } return count; } // For undirected graphs, count each edge once let count = 0; const counted = new Set(); for (const [source, neighbors] of this.map) { for (const target of neighbors.keys()) { const edgeKey = [source, target].sort().join("-"); if (!counted.has(edgeKey)) { counted.add(edgeKey); count++; } } } return count; } /** * Get node degree */ degree(nodeId) { const neighbors = this.map.get(String(nodeId)); return neighbors ? neighbors.size : 0; } /** * Get in-degree (for directed graphs) */ inDegree(nodeId) { if (!this.isDirected) { return this.degree(nodeId); } let count = 0; const targetId = String(nodeId); for (const neighbors of this.map.values()) { if (neighbors.has(targetId)) { count++; } } return count; } /** * Get out-degree (for directed graphs) */ outDegree(nodeId) { return this.degree(nodeId); } /** * Get underlying map representation */ getMap() { return this.map; } } //# sourceMappingURL=graph-converters.js.map