mirror of
https://github.com/ruvnet/RuView
synced 2026-08-11 20:41:44 +00:00
feat: vendor midstream and sublinear-time-solver libraries
Add ruvnet/midstream (AIMDS real-time inference) and ruvnet/sublinear-time-solver (sublinear optimization algorithms) as vendored dependencies under vendor/. Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
@@ -0,0 +1,857 @@
|
||||
# BMSSP API Integration Strategy
|
||||
|
||||
## 🔗 Integration Architecture
|
||||
|
||||
### Current Sublinear Solver Architecture
|
||||
```
|
||||
src/
|
||||
├── core/
|
||||
│ ├── solver.ts # SublinearSolver class
|
||||
│ ├── matrix.ts # MatrixOperations
|
||||
│ ├── types.ts # Core interfaces
|
||||
│ └── utils.ts # VectorOperations, utilities
|
||||
├── mcp/tools/
|
||||
│ ├── solver.ts # MCP solver tools
|
||||
│ ├── graph.ts # GraphTools for PageRank/centrality
|
||||
│ └── matrix.ts # Matrix analysis tools
|
||||
└── index.ts # Main exports
|
||||
```
|
||||
|
||||
### BMSSP Integration Points
|
||||
```typescript
|
||||
// @ruvnet/bmssp exports
|
||||
import {
|
||||
WasmGraph, // Basic graph pathfinding
|
||||
WasmNeuralBMSSP, // Neural/semantic pathfinding
|
||||
InitOutput // WASM initialization
|
||||
} from '@ruvnet/bmssp';
|
||||
```
|
||||
|
||||
## 🛠 Core Integration Strategy
|
||||
|
||||
### 1. BMSSP Wrapper Class
|
||||
|
||||
**File**: `src/core/bmssp-wrapper.ts`
|
||||
```typescript
|
||||
import { WasmGraph, WasmNeuralBMSSP } from '@ruvnet/bmssp';
|
||||
import { Matrix, Vector, SolverError, ErrorCodes } from './types.js';
|
||||
|
||||
export class BMSSPWrapper {
|
||||
private wasmGraph?: WasmGraph;
|
||||
private neuralBMSSP?: WasmNeuralBMSSP;
|
||||
private isInitialized = false;
|
||||
|
||||
constructor(
|
||||
private vertices: number,
|
||||
private enableNeural = false,
|
||||
private embeddingDim = 128
|
||||
) {}
|
||||
|
||||
async initialize(): Promise<void> {
|
||||
try {
|
||||
// Initialize basic graph
|
||||
this.wasmGraph = new WasmGraph(this.vertices, true);
|
||||
|
||||
// Initialize neural BMSSP if enabled
|
||||
if (this.enableNeural) {
|
||||
this.neuralBMSSP = new WasmNeuralBMSSP(this.vertices, this.embeddingDim);
|
||||
}
|
||||
|
||||
this.isInitialized = true;
|
||||
} catch (error) {
|
||||
throw new SolverError(
|
||||
`Failed to initialize BMSSP: ${error}`,
|
||||
ErrorCodes.INVALID_PARAMETERS
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
addEdge(from: number, to: number, weight: number): boolean {
|
||||
this.ensureInitialized();
|
||||
return this.wasmGraph!.add_edge(from, to, weight);
|
||||
}
|
||||
|
||||
computeShortestPaths(source: number): Float64Array {
|
||||
this.ensureInitialized();
|
||||
return this.wasmGraph!.compute_shortest_paths(source);
|
||||
}
|
||||
|
||||
// Neural methods
|
||||
setEmbedding(node: number, embedding: Float64Array): boolean {
|
||||
if (!this.neuralBMSSP) {
|
||||
throw new SolverError('Neural BMSSP not initialized', ErrorCodes.INVALID_PARAMETERS);
|
||||
}
|
||||
return this.neuralBMSSP.set_embedding(node, embedding);
|
||||
}
|
||||
|
||||
addSemanticEdge(from: number, to: number, alpha: number): void {
|
||||
if (!this.neuralBMSSP) {
|
||||
throw new SolverError('Neural BMSSP not initialized', ErrorCodes.INVALID_PARAMETERS);
|
||||
}
|
||||
this.neuralBMSSP.add_semantic_edge(from, to, alpha);
|
||||
}
|
||||
|
||||
computeNeuralPaths(source: number): Float64Array {
|
||||
if (!this.neuralBMSSP) {
|
||||
throw new SolverError('Neural BMSSP not initialized', ErrorCodes.INVALID_PARAMETERS);
|
||||
}
|
||||
return this.neuralBMSSP.compute_neural_paths(source);
|
||||
}
|
||||
|
||||
semanticDistance(node1: number, node2: number): number {
|
||||
if (!this.neuralBMSSP) {
|
||||
throw new SolverError('Neural BMSSP not initialized', ErrorCodes.INVALID_PARAMETERS);
|
||||
}
|
||||
return this.neuralBMSSP.semantic_distance(node1, node2);
|
||||
}
|
||||
|
||||
updateEmbeddings(gradients: Float64Array, learningRate: number): boolean {
|
||||
if (!this.neuralBMSSP) {
|
||||
throw new SolverError('Neural BMSSP not initialized', ErrorCodes.INVALID_PARAMETERS);
|
||||
}
|
||||
return this.neuralBMSSP.update_embeddings(
|
||||
gradients,
|
||||
learningRate,
|
||||
this.embeddingDim
|
||||
);
|
||||
}
|
||||
|
||||
cleanup(): void {
|
||||
if (this.wasmGraph) {
|
||||
this.wasmGraph.free();
|
||||
this.wasmGraph = undefined;
|
||||
}
|
||||
if (this.neuralBMSSP) {
|
||||
this.neuralBMSSP.free();
|
||||
this.neuralBMSSP = undefined;
|
||||
}
|
||||
this.isInitialized = false;
|
||||
}
|
||||
|
||||
get vertexCount(): number {
|
||||
return this.wasmGraph?.vertex_count ?? 0;
|
||||
}
|
||||
|
||||
get edgeCount(): number {
|
||||
return this.wasmGraph?.edge_count ?? 0;
|
||||
}
|
||||
|
||||
private ensureInitialized(): void {
|
||||
if (!this.isInitialized || !this.wasmGraph) {
|
||||
throw new SolverError('BMSSP not initialized', ErrorCodes.INVALID_PARAMETERS);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Matrix to Graph Bridge
|
||||
|
||||
**File**: `src/core/bmssp-bridge.ts`
|
||||
```typescript
|
||||
import { Matrix, Vector } from './types.js';
|
||||
import { MatrixOperations } from './matrix.js';
|
||||
import { BMSSPWrapper } from './bmssp-wrapper.js';
|
||||
|
||||
export class BMSSPBridge {
|
||||
/**
|
||||
* Convert adjacency matrix to BMSSP graph
|
||||
*/
|
||||
static async createGraphFromMatrix(
|
||||
adjacency: Matrix,
|
||||
enableNeural = false,
|
||||
embeddingDim = 128
|
||||
): Promise<BMSSPWrapper> {
|
||||
MatrixOperations.validateMatrix(adjacency);
|
||||
|
||||
if (adjacency.rows !== adjacency.cols) {
|
||||
throw new Error('Adjacency matrix must be square');
|
||||
}
|
||||
|
||||
const graph = new BMSSPWrapper(adjacency.rows, enableNeural, embeddingDim);
|
||||
await graph.initialize();
|
||||
|
||||
// Add edges from matrix
|
||||
for (let i = 0; i < adjacency.rows; i++) {
|
||||
for (let j = 0; j < adjacency.cols; j++) {
|
||||
const weight = MatrixOperations.getEntry(adjacency, i, j);
|
||||
if (weight !== 0) {
|
||||
graph.addEdge(i, j, weight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return graph;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert Laplacian matrix to graph (for effective resistance)
|
||||
*/
|
||||
static async createGraphFromLaplacian(laplacian: Matrix): Promise<BMSSPWrapper> {
|
||||
// Convert Laplacian to adjacency: A = D - L
|
||||
const adjacency = this.laplacianToAdjacency(laplacian);
|
||||
return this.createGraphFromMatrix(adjacency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract adjacency matrix from Laplacian
|
||||
*/
|
||||
private static laplacianToAdjacency(laplacian: Matrix): Matrix {
|
||||
const n = laplacian.rows;
|
||||
|
||||
if (laplacian.format === 'dense') {
|
||||
const data: number[][] = Array(n).fill(null).map(() => Array(n).fill(0));
|
||||
|
||||
for (let i = 0; i < n; i++) {
|
||||
const diagonal = MatrixOperations.getEntry(laplacian, i, i);
|
||||
|
||||
for (let j = 0; j < n; j++) {
|
||||
if (i !== j) {
|
||||
data[i][j] = -MatrixOperations.getEntry(laplacian, i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { rows: n, cols: n, data, format: 'dense' };
|
||||
} else {
|
||||
// Handle sparse format
|
||||
const values: number[] = [];
|
||||
const rowIndices: number[] = [];
|
||||
const colIndices: number[] = [];
|
||||
|
||||
const sparse = laplacian as any;
|
||||
for (let k = 0; k < sparse.values.length; k++) {
|
||||
const i = sparse.rowIndices[k];
|
||||
const j = sparse.colIndices[k];
|
||||
|
||||
if (i !== j) {
|
||||
values.push(-sparse.values[k]);
|
||||
rowIndices.push(i);
|
||||
colIndices.push(j);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
rows: n,
|
||||
cols: n,
|
||||
values,
|
||||
rowIndices,
|
||||
colIndices,
|
||||
format: 'coo'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set node embeddings for neural pathfinding
|
||||
*/
|
||||
static async setNodeEmbeddings(
|
||||
graph: BMSSPWrapper,
|
||||
embeddings: Float64Array[],
|
||||
embeddingDim: number
|
||||
): Promise<void> {
|
||||
for (let i = 0; i < embeddings.length; i++) {
|
||||
if (embeddings[i].length !== embeddingDim) {
|
||||
throw new Error(`Embedding ${i} has wrong dimension: ${embeddings[i].length} vs ${embeddingDim}`);
|
||||
}
|
||||
graph.setEmbedding(i, embeddings[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert BMSSP distances back to vector format
|
||||
*/
|
||||
static distancesToVector(distances: Float64Array): Vector {
|
||||
return Array.from(distances);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Hybrid Solver Integration
|
||||
|
||||
**File**: `src/core/hybrid-solver.ts`
|
||||
```typescript
|
||||
import { SublinearSolver } from './solver.js';
|
||||
import { BMSSPWrapper } from './bmssp-wrapper.js';
|
||||
import { BMSSPBridge } from './bmssp-bridge.js';
|
||||
import {
|
||||
Matrix,
|
||||
Vector,
|
||||
SolverConfig,
|
||||
SolverResult,
|
||||
PageRankConfig,
|
||||
SolverError,
|
||||
ErrorCodes
|
||||
} from './types.js';
|
||||
|
||||
interface HybridConfig extends SolverConfig {
|
||||
useBMSSP?: boolean;
|
||||
bmsspThreshold?: {
|
||||
minGraphSize: number;
|
||||
minSparsity: number;
|
||||
multiSourceMin: number;
|
||||
};
|
||||
enableNeural?: boolean;
|
||||
}
|
||||
|
||||
export class HybridSolver extends SublinearSolver {
|
||||
private bmsspGraph?: BMSSPWrapper;
|
||||
|
||||
constructor(private hybridConfig: HybridConfig) {
|
||||
super(hybridConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enhanced PageRank using BMSSP when beneficial
|
||||
*/
|
||||
async computePageRank(adjacency: Matrix, config: PageRankConfig): Promise<Vector> {
|
||||
const shouldUseBMSSP = this.shouldUseBMSSP(adjacency, 'pagerank');
|
||||
|
||||
if (shouldUseBMSSP) {
|
||||
return this.computePageRankBMSSP(adjacency, config);
|
||||
} else {
|
||||
return super.computePageRank(adjacency, config);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Multi-source shortest paths using BMSSP
|
||||
*/
|
||||
async multiSourceShortestPaths(
|
||||
adjacency: Matrix,
|
||||
sources: number[],
|
||||
targets?: number[]
|
||||
): Promise<{
|
||||
distances: Map<number, Vector>;
|
||||
paths: Map<number, number[][]>;
|
||||
computeTime: number;
|
||||
}> {
|
||||
const startTime = performance.now();
|
||||
|
||||
this.bmsspGraph = await BMSSPBridge.createGraphFromMatrix(adjacency);
|
||||
|
||||
const distances = new Map<number, Vector>();
|
||||
const paths = new Map<number, number[][]>();
|
||||
|
||||
try {
|
||||
for (const source of sources) {
|
||||
const sourceDistances = this.bmsspGraph.computeShortestPaths(source);
|
||||
distances.set(source, BMSSPBridge.distancesToVector(sourceDistances));
|
||||
|
||||
// Reconstruct paths (simplified - BMSSP focuses on distances)
|
||||
const sourcePaths: number[][] = [];
|
||||
if (targets) {
|
||||
for (const target of targets) {
|
||||
sourcePaths.push(this.reconstructPath(adjacency, source, target, sourceDistances));
|
||||
}
|
||||
}
|
||||
paths.set(source, sourcePaths);
|
||||
}
|
||||
|
||||
return {
|
||||
distances,
|
||||
paths,
|
||||
computeTime: performance.now() - startTime
|
||||
};
|
||||
} finally {
|
||||
this.bmsspGraph.cleanup();
|
||||
this.bmsspGraph = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Semantic pathfinding using Neural BMSSP
|
||||
*/
|
||||
async semanticPathfinding(
|
||||
adjacency: Matrix,
|
||||
embeddings: Float64Array[],
|
||||
source: number,
|
||||
target: number,
|
||||
alpha: number = 0.5
|
||||
): Promise<{
|
||||
distance: number;
|
||||
semanticDistance: number;
|
||||
path: number[];
|
||||
computeTime: number;
|
||||
}> {
|
||||
const startTime = performance.now();
|
||||
|
||||
this.bmsspGraph = await BMSSPBridge.createGraphFromMatrix(
|
||||
adjacency,
|
||||
true, // Enable neural
|
||||
embeddings[0].length
|
||||
);
|
||||
|
||||
try {
|
||||
// Set embeddings
|
||||
await BMSSPBridge.setNodeEmbeddings(
|
||||
this.bmsspGraph,
|
||||
embeddings,
|
||||
embeddings[0].length
|
||||
);
|
||||
|
||||
// Add semantic edges
|
||||
for (let i = 0; i < adjacency.rows; i++) {
|
||||
for (let j = 0; j < adjacency.cols; j++) {
|
||||
if (i !== j) {
|
||||
this.bmsspGraph.addSemanticEdge(i, j, alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compute neural paths
|
||||
const neuralDistances = this.bmsspGraph.computeNeuralPaths(source);
|
||||
const semanticDist = this.bmsspGraph.semanticDistance(source, target);
|
||||
|
||||
// Reconstruct semantic path (simplified)
|
||||
const path = this.reconstructSemanticPath(source, target, neuralDistances);
|
||||
|
||||
return {
|
||||
distance: neuralDistances[target],
|
||||
semanticDistance: semanticDist,
|
||||
path,
|
||||
computeTime: performance.now() - startTime
|
||||
};
|
||||
} finally {
|
||||
this.bmsspGraph.cleanup();
|
||||
this.bmsspGraph = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decide whether to use BMSSP based on problem characteristics
|
||||
*/
|
||||
private shouldUseBMSSP(matrix: Matrix, operation: string): boolean {
|
||||
if (!this.hybridConfig.useBMSSP) return false;
|
||||
|
||||
const threshold = this.hybridConfig.bmsspThreshold || {
|
||||
minGraphSize: 1000,
|
||||
minSparsity: 0.9,
|
||||
multiSourceMin: 2
|
||||
};
|
||||
|
||||
const size = matrix.rows;
|
||||
const sparsity = this.calculateSparsity(matrix);
|
||||
|
||||
// Size threshold
|
||||
if (size < threshold.minGraphSize) return false;
|
||||
|
||||
// Sparsity threshold (BMSSP excels with sparse graphs)
|
||||
if (sparsity < threshold.minSparsity) return false;
|
||||
|
||||
// Operation-specific logic
|
||||
switch (operation) {
|
||||
case 'pagerank':
|
||||
return size > 5000; // BMSSP beneficial for large PageRank
|
||||
case 'shortest-path':
|
||||
return true; // BMSSP always good for shortest paths
|
||||
case 'multi-source':
|
||||
return true; // BMSSP designed for multi-source
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private calculateSparsity(matrix: Matrix): number {
|
||||
let nonZeros = 0;
|
||||
const total = matrix.rows * matrix.cols;
|
||||
|
||||
if (matrix.format === 'dense') {
|
||||
const dense = matrix as any;
|
||||
for (let i = 0; i < matrix.rows; i++) {
|
||||
for (let j = 0; j < matrix.cols; j++) {
|
||||
if (dense.data[i][j] !== 0) nonZeros++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const sparse = matrix as any;
|
||||
nonZeros = sparse.values.length;
|
||||
}
|
||||
|
||||
return 1 - (nonZeros / total);
|
||||
}
|
||||
|
||||
private async computePageRankBMSSP(adjacency: Matrix, config: PageRankConfig): Promise<Vector> {
|
||||
// Convert PageRank to shortest path problem for BMSSP
|
||||
// This is a simplified approach - full implementation would be more complex
|
||||
|
||||
this.bmsspGraph = await BMSSPBridge.createGraphFromMatrix(adjacency);
|
||||
|
||||
try {
|
||||
const n = adjacency.rows;
|
||||
const pagerank = new Array(n).fill(0);
|
||||
|
||||
// Compute influence from each node (simplified)
|
||||
for (let i = 0; i < n; i++) {
|
||||
const distances = this.bmsspGraph.computeShortestPaths(i);
|
||||
const influence = this.computeInfluence(distances, config.damping);
|
||||
pagerank[i] = influence;
|
||||
}
|
||||
|
||||
// Normalize
|
||||
const sum = pagerank.reduce((a, b) => a + b, 0);
|
||||
return pagerank.map(p => p / sum);
|
||||
} finally {
|
||||
this.bmsspGraph.cleanup();
|
||||
this.bmsspGraph = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
private computeInfluence(distances: Float64Array, damping: number): number {
|
||||
// Convert distances to influence scores
|
||||
let influence = 0;
|
||||
for (let i = 0; i < distances.length; i++) {
|
||||
if (distances[i] < Infinity) {
|
||||
influence += damping / (1 + distances[i]);
|
||||
}
|
||||
}
|
||||
return influence;
|
||||
}
|
||||
|
||||
private reconstructPath(
|
||||
adjacency: Matrix,
|
||||
source: number,
|
||||
target: number,
|
||||
distances: Float64Array
|
||||
): number[] {
|
||||
// Simple path reconstruction (breadth-first approach)
|
||||
const path: number[] = [];
|
||||
let current = target;
|
||||
|
||||
while (current !== source) {
|
||||
path.unshift(current);
|
||||
|
||||
// Find predecessor with minimum distance
|
||||
let minDist = Infinity;
|
||||
let predecessor = -1;
|
||||
|
||||
for (let i = 0; i < adjacency.rows; i++) {
|
||||
if (MatrixOperations.getEntry(adjacency, i, current) > 0) {
|
||||
if (distances[i] < minDist) {
|
||||
minDist = distances[i];
|
||||
predecessor = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (predecessor === -1) break;
|
||||
current = predecessor;
|
||||
}
|
||||
|
||||
path.unshift(source);
|
||||
return path;
|
||||
}
|
||||
|
||||
private reconstructSemanticPath(
|
||||
source: number,
|
||||
target: number,
|
||||
neuralDistances: Float64Array
|
||||
): number[] {
|
||||
// Simplified semantic path reconstruction
|
||||
// In practice, would use more sophisticated neural pathfinding
|
||||
const path: number[] = [source];
|
||||
|
||||
let current = source;
|
||||
const visited = new Set([source]);
|
||||
|
||||
while (current !== target && path.length < neuralDistances.length) {
|
||||
let nextNode = -1;
|
||||
let minDist = Infinity;
|
||||
|
||||
for (let i = 0; i < neuralDistances.length; i++) {
|
||||
if (!visited.has(i) && neuralDistances[i] < minDist) {
|
||||
minDist = neuralDistances[i];
|
||||
nextNode = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (nextNode === -1) break;
|
||||
|
||||
path.push(nextNode);
|
||||
visited.add(nextNode);
|
||||
current = nextNode;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
override async cleanup(): Promise<void> {
|
||||
if (this.bmsspGraph) {
|
||||
this.bmsspGraph.cleanup();
|
||||
this.bmsspGraph = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔧 MCP Tools Integration
|
||||
|
||||
### Enhanced Graph Tools
|
||||
|
||||
**File**: `src/mcp/tools/bmssp-tools.ts`
|
||||
```typescript
|
||||
import { HybridSolver } from '../../core/hybrid-solver.js';
|
||||
import { BMSSPBridge } from '../../core/bmssp-bridge.js';
|
||||
import { Matrix, Vector, SolverError, ErrorCodes } from '../../core/types.js';
|
||||
|
||||
export class BMSSPTools {
|
||||
/**
|
||||
* Ultra-fast shortest path using BMSSP WASM
|
||||
*/
|
||||
static async shortestPath(params: {
|
||||
adjacency: Matrix;
|
||||
source: number;
|
||||
target: number;
|
||||
method?: 'bmssp' | 'hybrid';
|
||||
}) {
|
||||
const graph = await BMSSPBridge.createGraphFromMatrix(params.adjacency);
|
||||
|
||||
try {
|
||||
const distances = graph.computeShortestPaths(params.source);
|
||||
const distance = distances[params.target];
|
||||
|
||||
return {
|
||||
distance,
|
||||
source: params.source,
|
||||
target: params.target,
|
||||
algorithm: 'bmssp-wasm',
|
||||
performance: {
|
||||
vertices: graph.vertexCount,
|
||||
edges: graph.edgeCount,
|
||||
complexity: 'O(m·log^(2/3) n)'
|
||||
}
|
||||
};
|
||||
} finally {
|
||||
graph.cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Multi-source PageRank using BMSSP
|
||||
*/
|
||||
static async multiSourcePageRank(params: {
|
||||
adjacency: Matrix;
|
||||
sources: number[];
|
||||
damping?: number;
|
||||
epsilon?: number;
|
||||
maxIterations?: number;
|
||||
}) {
|
||||
const config = {
|
||||
method: 'neumann' as const,
|
||||
epsilon: params.epsilon || 1e-6,
|
||||
maxIterations: params.maxIterations || 1000,
|
||||
useBMSSP: true,
|
||||
bmsspThreshold: {
|
||||
minGraphSize: 100,
|
||||
minSparsity: 0.7,
|
||||
multiSourceMin: 2
|
||||
}
|
||||
};
|
||||
|
||||
const solver = new HybridSolver(config);
|
||||
|
||||
const pageRankConfig = {
|
||||
damping: params.damping || 0.85,
|
||||
epsilon: params.epsilon || 1e-6,
|
||||
maxIterations: params.maxIterations || 1000
|
||||
};
|
||||
|
||||
try {
|
||||
const result = await solver.multiSourceShortestPaths(
|
||||
params.adjacency,
|
||||
params.sources
|
||||
);
|
||||
|
||||
return {
|
||||
sources: params.sources,
|
||||
distances: Object.fromEntries(result.distances),
|
||||
computeTime: result.computeTime,
|
||||
algorithm: 'bmssp-multi-source',
|
||||
statistics: {
|
||||
totalSources: params.sources.length,
|
||||
averageDistance: this.calculateAverageDistance(result.distances),
|
||||
performance: result.computeTime
|
||||
}
|
||||
};
|
||||
} finally {
|
||||
await solver.cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Semantic pathfinding with neural BMSSP
|
||||
*/
|
||||
static async semanticPathfinding(params: {
|
||||
adjacency: Matrix;
|
||||
embeddings: Float64Array[];
|
||||
source: number;
|
||||
target: number;
|
||||
alpha?: number;
|
||||
embeddingDim?: number;
|
||||
}) {
|
||||
const config = {
|
||||
method: 'neumann' as const,
|
||||
epsilon: 1e-6,
|
||||
maxIterations: 1000,
|
||||
useBMSSP: true,
|
||||
enableNeural: true
|
||||
};
|
||||
|
||||
const solver = new HybridSolver(config);
|
||||
|
||||
try {
|
||||
const result = await solver.semanticPathfinding(
|
||||
params.adjacency,
|
||||
params.embeddings,
|
||||
params.source,
|
||||
params.target,
|
||||
params.alpha || 0.5
|
||||
);
|
||||
|
||||
return {
|
||||
...result,
|
||||
algorithm: 'neural-bmssp',
|
||||
semantics: {
|
||||
embeddingDim: params.embeddings[0].length,
|
||||
alpha: params.alpha || 0.5,
|
||||
semanticSimilarity: 1 / (1 + result.semanticDistance)
|
||||
}
|
||||
};
|
||||
} finally {
|
||||
await solver.cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch shortest paths computation
|
||||
*/
|
||||
static async batchShortestPaths(params: {
|
||||
adjacency: Matrix;
|
||||
queries: Array<{ source: number; target: number }>;
|
||||
}) {
|
||||
const graph = await BMSSPBridge.createGraphFromMatrix(params.adjacency);
|
||||
const results: Array<{
|
||||
source: number;
|
||||
target: number;
|
||||
distance: number;
|
||||
}> = [];
|
||||
|
||||
try {
|
||||
// Group queries by source for efficiency
|
||||
const sourceGroups = new Map<number, number[]>();
|
||||
for (const query of params.queries) {
|
||||
if (!sourceGroups.has(query.source)) {
|
||||
sourceGroups.set(query.source, []);
|
||||
}
|
||||
sourceGroups.get(query.source)!.push(query.target);
|
||||
}
|
||||
|
||||
// Compute distances for each source group
|
||||
for (const [source, targets] of sourceGroups) {
|
||||
const distances = graph.computeShortestPaths(source);
|
||||
|
||||
for (const target of targets) {
|
||||
results.push({
|
||||
source,
|
||||
target,
|
||||
distance: distances[target]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
results,
|
||||
statistics: {
|
||||
totalQueries: params.queries.length,
|
||||
uniqueSources: sourceGroups.size,
|
||||
algorithm: 'bmssp-batch',
|
||||
performance: {
|
||||
vertices: graph.vertexCount,
|
||||
edges: graph.edgeCount
|
||||
}
|
||||
}
|
||||
};
|
||||
} finally {
|
||||
graph.cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
private static calculateAverageDistance(distances: Map<number, Vector>): number {
|
||||
let total = 0;
|
||||
let count = 0;
|
||||
|
||||
for (const distanceVector of distances.values()) {
|
||||
for (const distance of distanceVector) {
|
||||
if (distance < Infinity) {
|
||||
total += distance;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count > 0 ? total / count : 0;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 Performance Monitoring
|
||||
|
||||
**File**: `src/core/bmssp-benchmarks.ts`
|
||||
```typescript
|
||||
export class BMSSPBenchmarks {
|
||||
static async comparePerformance(
|
||||
adjacency: Matrix,
|
||||
testCases: Array<{
|
||||
method: 'traditional' | 'bmssp' | 'hybrid';
|
||||
operation: 'shortest-path' | 'pagerank' | 'multi-source';
|
||||
params: any;
|
||||
}>
|
||||
) {
|
||||
const results = [];
|
||||
|
||||
for (const testCase of testCases) {
|
||||
const startTime = performance.now();
|
||||
const startMemory = process.memoryUsage().heapUsed;
|
||||
|
||||
let result;
|
||||
switch (testCase.method) {
|
||||
case 'traditional':
|
||||
result = await this.runTraditional(adjacency, testCase);
|
||||
break;
|
||||
case 'bmssp':
|
||||
result = await this.runBMSSP(adjacency, testCase);
|
||||
break;
|
||||
case 'hybrid':
|
||||
result = await this.runHybrid(adjacency, testCase);
|
||||
break;
|
||||
}
|
||||
|
||||
const endTime = performance.now();
|
||||
const endMemory = process.memoryUsage().heapUsed;
|
||||
|
||||
results.push({
|
||||
method: testCase.method,
|
||||
operation: testCase.operation,
|
||||
executionTime: endTime - startTime,
|
||||
memoryUsed: endMemory - startMemory,
|
||||
result
|
||||
});
|
||||
}
|
||||
|
||||
return this.analyzeResults(results);
|
||||
}
|
||||
|
||||
private static analyzeResults(results: any[]) {
|
||||
// Group by operation and compare methods
|
||||
const analysis = {
|
||||
performanceGains: {},
|
||||
memoryEfficiency: {},
|
||||
recommendations: []
|
||||
};
|
||||
|
||||
// Implementation details...
|
||||
return analysis;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This API integration strategy provides a comprehensive approach to incorporating BMSSP's high-performance graph algorithms while maintaining compatibility with existing sublinear solver functionality.
|
||||
Reference in New Issue
Block a user