-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c407cfe
commit 77ac213
Showing
37 changed files
with
925 additions
and
3,612 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,83 +1,257 @@ | ||
import { AdjacencyList, AdjacencyMatrix, EdgeList } from './src/index.ts'; | ||
import Graph from 'graphology'; | ||
import graphologyLouvain from 'graphology-communities-louvain'; | ||
import { | ||
degreeCentrality, | ||
inDegreeCentrality, | ||
outDegreeCentrality, | ||
} from 'graphology-metrics/centrality/degree.js'; | ||
import { density } from 'graphology-metrics/graph/density.js'; | ||
|
||
console.log('---------------- AdjacencyList (number) ------------------'); | ||
import { | ||
AdjacencyList, | ||
AdjacencyMatrix, | ||
BipartiteGraph, | ||
CyclicGraph, | ||
DAG, | ||
DirectedGraph, | ||
EdgeList, | ||
Louvain, | ||
UndirectedGraph, | ||
WeightedGraph, | ||
} from './src/index.ts'; | ||
|
||
// First Example: Using Simple Strings as Vertices and Numbers as Edge Data | ||
const adjacencyList = new AdjacencyList<string, number>(); // Specify types for vertices (string) and edge data (number) | ||
console.log('---------------- AdjacencyList ------------------'); | ||
const adjacencyList = new AdjacencyList<string, number>(); | ||
adjacencyList.addEdge('A', 'B', 10); | ||
adjacencyList.addEdge('A', 'C', 15); | ||
adjacencyList.printGraph(); | ||
|
||
// Adding vertices | ||
adjacencyList.addVertex('A'); | ||
adjacencyList.addVertex('B'); | ||
adjacencyList.addVertex('C'); | ||
console.log('---------------- AdjacencyMatrix ------------------'); | ||
const adjacencyMatrix = new AdjacencyMatrix<string, number>(); | ||
adjacencyMatrix.addEdge('A', 'B', 10); | ||
adjacencyMatrix.addEdge('B', 'C', 5); | ||
adjacencyMatrix.printGraph(); | ||
|
||
// Adding edges with optional edge data (e.g., weights for edges) | ||
adjacencyList.addEdge('A', 'B', 10); // Edge A -> B with weight 10 | ||
adjacencyList.addEdge('A', 'C', 15); // Edge A -> C with weight 15 | ||
adjacencyList.addEdge('B', 'C', 5); // Edge B -> C with weight 5 | ||
console.log('---------------- EdgeList ------------------'); | ||
const edgeList = new EdgeList<string, number>(); | ||
edgeList.addEdge('A', 'B', 10); | ||
edgeList.addEdge('B', 'C', 5); | ||
edgeList.printGraph(); | ||
|
||
// Print the adjacencyList to see the current state | ||
adjacencyList.printGraph(); | ||
// Output: A → B (Edge Data: 10), C (Edge Data: 15) | B → C (Edge Data: 5) | C → | ||
console.log('---------------- DirectedGraph ------------------'); | ||
const directedGraph = new DirectedGraph<string, number>(); | ||
directedGraph.addEdge('A', 'B', 10); | ||
directedGraph.addEdge('B', 'C', 5); | ||
directedGraph.printGraph(); | ||
|
||
// Removing an edge: A -> C | ||
adjacencyList.removeEdge('A', 'C'); | ||
adjacencyList.printGraph(); | ||
// Output: A → B (Edge Data: 10) | B → C (Edge Data: 5) | C → | ||
console.log('---------------- UndirectedGraph ------------------'); | ||
const undirectedGraph = new UndirectedGraph<string, number>(); | ||
undirectedGraph.addEdge('A', 'B', 10); | ||
undirectedGraph.addEdge('B', 'C', 5); | ||
undirectedGraph.printGraph(); | ||
|
||
// Removing vertex C (this also removes its associated edges) | ||
adjacencyList.removeVertex('C'); | ||
adjacencyList.printGraph(); | ||
// Output: A → B (Edge Data: 10) | B → | ||
console.log('---------------- DAG ------------------'); | ||
const dag = new DAG<string, number>(); | ||
dag.addEdge('A', 'B', 10); | ||
dag.addEdge('B', 'C', 5); | ||
try { | ||
dag.addEdge('C', 'A', 15); // This should throw an error | ||
} catch (e) { | ||
console.error(e.message); | ||
} | ||
dag.printGraph(); | ||
|
||
// Second Example: Using Custom Objects as Vertices | ||
console.log('---------------- AdjacencyList (Object) ------------------'); | ||
console.log('---------------- CyclicGraph ------------------'); | ||
const cyclicGraph = new CyclicGraph<string, number>(); | ||
cyclicGraph.addEdge('A', 'B', 10); | ||
cyclicGraph.addEdge('B', 'C', 5); | ||
cyclicGraph.addEdge('C', 'A', 15); | ||
cyclicGraph.printGraph(); | ||
|
||
// Define a custom object type for vertices | ||
interface MyObject { | ||
id: number; | ||
name: string; | ||
console.log('---------------- BipartiteGraph ------------------'); | ||
const bipartiteGraph = new BipartiteGraph<string>(); | ||
bipartiteGraph.addVertexToSetA('A'); | ||
bipartiteGraph.addVertexToSetB('B'); | ||
bipartiteGraph.addEdge('A', 'B'); | ||
try { | ||
bipartiteGraph.addEdge('A', 'A'); // Should throw an error | ||
} catch (e) { | ||
console.error(e.message); | ||
} | ||
bipartiteGraph.printGraph(); | ||
|
||
// Create custom object vertices | ||
const obj1: MyObject = { id: 1, name: 'Node 1' }; | ||
const obj2: MyObject = { id: 2, name: 'Node 2' }; | ||
const obj3: MyObject = { id: 3, name: 'Node 3' }; | ||
console.log('---------------- WeightedGraph ------------------'); | ||
const weightedGraph = new WeightedGraph<string>(); | ||
weightedGraph.addEdge('A', 'B', 10); | ||
weightedGraph.addEdge('B', 'C', 15); | ||
weightedGraph.printGraph(); | ||
|
||
// Example usage with custom objects as vertices | ||
const adjacencyListObject = new AdjacencyList<MyObject, number>(); // Using MyObject as vertices and number as edge data | ||
console.log('================== Advanced Graph Benchmark =================='); | ||
|
||
// Adding edges between custom objects with edge data | ||
adjacencyListObject.addEdge(obj1, obj2, 10); // Edge between obj1 and obj2 with weight 10 | ||
adjacencyListObject.addEdge(obj2, obj3, 5); // Edge between obj2 and obj3 with weight 5 | ||
// | ||
// 1. AdjacencyList: Organizational Hierarchy | ||
// | ||
console.log('---------------- AdjacencyList: Organizational Hierarchy ------------------'); | ||
const orgChart = new AdjacencyList<string, string>(); | ||
orgChart.addEdge('CEO', 'VP1', 'Leads'); | ||
orgChart.addEdge('CEO', 'VP2', 'Leads'); | ||
orgChart.addEdge('VP1', 'Manager1', 'Manages'); | ||
orgChart.addEdge('VP2', 'Manager2', 'Manages'); | ||
orgChart.printGraph(); | ||
// Example: CEO → VP1 (Edge Data: Leads), VP2 (Edge Data: Leads) | ||
|
||
// Print the adjacencyList to see the custom object vertices and their relationships | ||
adjacencyListObject.printGraph(); | ||
// Output: | ||
// {"id":1,"name":"Node 1"} → {"id":2,"name":"Node 2"} | ||
// {"id":2,"name":"Node 2"} → {"id":3,"name":"Node 3"} | ||
// | ||
// 2. AdjacencyMatrix: Efficient Graph Traversal (Warshall’s Algorithm for Path Finding) | ||
// | ||
console.log('---------------- AdjacencyMatrix: Path Finding ------------------'); | ||
const warshallMatrix = new AdjacencyMatrix<string, null>(); | ||
warshallMatrix.addEdge('A', 'B'); | ||
warshallMatrix.addEdge('B', 'C'); | ||
warshallMatrix.addEdge('C', 'D'); | ||
// Compute transitive closure | ||
const vertices = warshallMatrix.getVertices(); | ||
vertices.forEach((k) => { | ||
vertices.forEach((i) => { | ||
vertices.forEach((j) => { | ||
if (warshallMatrix.getEdgeData(i, k) && warshallMatrix.getEdgeData(k, j)) { | ||
warshallMatrix.addEdge(i, j); | ||
} | ||
}); | ||
}); | ||
}); | ||
warshallMatrix.printGraph(); | ||
|
||
console.log('---------------- AdjacencyMatrix ------------------'); | ||
// | ||
// 3. EdgeList: Airline Route Optimization | ||
// | ||
console.log('---------------- EdgeList: Airline Route Optimization ------------------'); | ||
const routes = new EdgeList<string, number>(); | ||
routes.addEdge('A', 'B', 500); // Cost in dollars | ||
routes.addEdge('B', 'C', 300); | ||
routes.addEdge('C', 'A', 700); | ||
// Finding the cheapest route | ||
const cheapest = routes.getEdgeData('A', 'B'); | ||
console.log(`Cheapest route from A to B: $${cheapest}`); | ||
// Example: A → B (Edge Data: 500) | ||
|
||
const adjacencyMatrix = new AdjacencyMatrix<MyObject, number>(); // Using MyObject as vertices and number as edge data | ||
// | ||
// 4. DirectedGraph: Citation Network | ||
// | ||
console.log('---------------- DirectedGraph: Citation Network ------------------'); | ||
const citations = new DirectedGraph<string, null>(); | ||
citations.addEdge('PaperA', 'PaperB'); | ||
citations.addEdge('PaperB', 'PaperC'); | ||
// Find papers that cite "PaperA" | ||
console.log('Cited by PaperA:', citations.getNeighbors('PaperA')); | ||
|
||
adjacencyMatrix.addEdge(obj1, obj2, 10); // Edge between obj1 and obj2 with weight 10 | ||
adjacencyMatrix.addEdge(obj2, obj3, 5); // Edge between obj2 and obj3 with weight 5 | ||
// | ||
// 5. UndirectedGraph: Collaboration Network | ||
// | ||
console.log('---------------- UndirectedGraph: Collaboration Network ------------------'); | ||
const collaborations = new UndirectedGraph<string, null>(); | ||
collaborations.addEdge('Alice', 'Bob'); | ||
collaborations.addEdge('Alice', 'Charlie'); | ||
collaborations.addEdge('Bob', 'David'); | ||
// Find all collaborators of "Alice" | ||
console.log('Collaborators of Alice:', collaborations.getNeighbors('Alice')); | ||
|
||
adjacencyMatrix.printGraph(); | ||
// Output: | ||
// {"id":1,"name":"Node 1"} → {"id":2,"name":"Node 2"} (Edge Data: 10) | ||
// {"id":2,"name":"Node 2"} → {"id":3,"name":"Node 3"} (Edge Data: 5) | ||
// | ||
// 6. DAG: Build System Dependency Resolution | ||
// | ||
console.log('---------------- DAG: Build System Dependency Resolution ------------------'); | ||
const buildSystem = new DAG<string, null>(); | ||
buildSystem.addEdge('A', 'B'); // B depends on A | ||
buildSystem.addEdge('B', 'C'); // C depends on B | ||
buildSystem.addEdge('A', 'C'); // Direct dependency for optimization | ||
console.log('Build Order:'); | ||
buildSystem.getVertices().forEach((vertex) => { | ||
console.log(vertex, '->', buildSystem.getNeighbors(vertex)); | ||
}); | ||
|
||
console.log('---------------- EdgeList ------------------'); | ||
// | ||
// 7. CyclicGraph: Transaction Network with Loops | ||
// | ||
console.log('---------------- CyclicGraph: Transaction Network ------------------'); | ||
const transactions = new CyclicGraph<string, number>(); | ||
transactions.addEdge('AccountA', 'AccountB', 100); // $100 transfer | ||
transactions.addEdge('AccountB', 'AccountC', 50); | ||
transactions.addEdge('AccountC', 'AccountA', 150); // Circular flow | ||
transactions.printGraph(); | ||
|
||
const edgeList = new EdgeList<MyObject, number>(); // Using MyObject as vertices and number as edge data | ||
// | ||
// 8. BipartiteGraph: Content Recommendation | ||
// | ||
console.log('---------------- BipartiteGraph: Content Recommendation ------------------'); | ||
const recommendations = new BipartiteGraph<string>(); | ||
recommendations.addVertexToSetA('User1'); | ||
recommendations.addVertexToSetA('User2'); | ||
recommendations.addVertexToSetB('MovieA'); | ||
recommendations.addVertexToSetB('MovieB'); | ||
recommendations.addEdge('User1', 'MovieA'); | ||
recommendations.addEdge('User2', 'MovieB'); | ||
// Find all movies recommended for User1 | ||
console.log('Movies for User1:', recommendations.getNeighbors('User1')); | ||
|
||
// Adding edges between custom objects with edge data (e.g., weight) | ||
edgeList.addEdge(obj1, obj2, 10); // Edge between obj1 and obj2 with weight 10 | ||
edgeList.addEdge(obj2, obj3, 5); // Edge between obj2 and obj3 with weight 5 | ||
// | ||
// 9. WeightedGraph: Shortest Path for Delivery Routes | ||
// | ||
console.log('---------------- WeightedGraph: Delivery Routes ------------------'); | ||
const deliveryRoutes = new WeightedGraph<string>(); | ||
deliveryRoutes.addEdge('Warehouse', 'Store1', 10); // Distance in miles | ||
deliveryRoutes.addEdge('Store1', 'Store2', 20); | ||
deliveryRoutes.addEdge('Warehouse', 'Store2', 25); | ||
// Find the shortest route | ||
const distance = deliveryRoutes.getEdgeData('Warehouse', 'Store1'); | ||
console.log(`Shortest route from Warehouse to Store1: ${distance} miles`); | ||
|
||
// Print the graph to see the custom object vertices and their relationships | ||
edgeList.printGraph(); | ||
// Output: | ||
// {"id":1,"name":"Node 1"} → {"id":2,"name":"Node 2"} (Edge Data: 10) | ||
// {"id":2,"name":"Node 2"} → {"id":3,"name":"Node 3"} (Edge Data: 5) | ||
console.log('---------------- Graph Algorithms (Graphology) ------------------'); | ||
|
||
const GRAPH_OPTIONS = { | ||
allowSelfLoops: true, | ||
multi: false, | ||
}; | ||
|
||
const projectGraph = new Graph.UndirectedGraph(GRAPH_OPTIONS); | ||
|
||
// Add nodes | ||
const nodes = ['A', 'B', 'C', 'D']; | ||
nodes.forEach((node) => projectGraph.addNode(node)); | ||
|
||
// Add edges with weights | ||
const edges = [ | ||
['A', 'B', 1], | ||
['B', 'C', 2], | ||
['C', 'D', 1], | ||
['A', 'D', 2], | ||
]; | ||
|
||
edges.forEach(([source, target, weight], index) => { | ||
projectGraph.addEdgeWithKey(`${source}-${target}-${index}`, source, target, { weight }); | ||
}); | ||
|
||
// Perform Louvain community detection | ||
const louvainResults = graphologyLouvain.detailed(projectGraph, { | ||
attributes: { weight: 'weight' }, | ||
}); | ||
|
||
// Output the results | ||
console.log({ | ||
modularity: louvainResults.modularity, | ||
communities: louvainResults.communities, | ||
density: density(projectGraph), | ||
degreeCentrality: degreeCentrality(projectGraph), | ||
}); | ||
|
||
console.log('---------------- Graph Algorithms (DSA Toolkit) ------------------'); | ||
|
||
const dsaGraph = new UndirectedGraph<string, number>(); | ||
dsaGraph.addEdge('A', 'B', 1); | ||
dsaGraph.addEdge('B', 'C', 2); | ||
dsaGraph.addEdge('C', 'D', 1); | ||
dsaGraph.addEdge('D', 'A', 2); | ||
|
||
const louvain = new Louvain(dsaGraph); | ||
const result = louvain.run(); | ||
|
||
console.log('Modularity:', result.modularity); | ||
console.log('Communities:', Array.from(result.communities.entries())); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.