refactor(8.0): graph analytics contract — intent names, not algorithm names
The public brain.graph.* surface and the GraphAccelerationProvider seam must name
operations by INTENT, not by the algorithm that happens to implement them — so a
plugin can swap algorithms without the contract lying. The JS fallback computes
communities via connected-components and rank via PageRank, but a native provider
(cor) is free to use Louvain/Leiden for communities and personalized-PageRank /
eigenvector-centrality for rank: same intent, different algorithm, same name.
Renamed the (not-yet-implemented) Phase-C analytics methods + their option/result
types on GraphAccelerationProvider:
- pageRank -> rank (PageRankOptions -> RankOptions; dropped the
pagerank-internal damping/maxIterations/tolerance
knobs from the contract — each impl tunes itself)
- connectedComponents -> communities (ComponentsOptions -> CommunitiesOptions,
mode:'weak'|'strong' -> directed?:boolean;
GraphComponents -> GraphCommunities, componentIds/
Count -> communityIds/Count)
- shortestPath -> path (ShortestPathOptions -> PathOptions; weight -> by:'hops'|'weight')
- neighborhoodSample -> sample (NeighborhoodSampleOptions -> SampleOptions)
- topByDegree -> mostConnected (TopByDegreeOptions -> MostConnectedOptions)
traverse / edgesForNode / graphCursorOpen/Next/Close + GraphScores/GraphPath/
OpaqueIdSet/Subgraph are UNCHANGED — everything cor has already built is untouched;
this is a pure pre-implementation rename (cor coordinated). JSDoc reworded to state
the algorithm is the provider's choice. index.ts exports + the native-seam test
mock updated. tsc/unit 1517/integration 599 green.
This commit is contained in:
parent
96d9c0b92c
commit
f3e69110f0
3 changed files with 75 additions and 59 deletions
12
src/index.ts
12
src/index.ts
|
|
@ -194,13 +194,13 @@ export type {
|
||||||
GraphCursorOptions,
|
GraphCursorOptions,
|
||||||
GraphCursorChunk,
|
GraphCursorChunk,
|
||||||
GraphScores,
|
GraphScores,
|
||||||
GraphComponents,
|
GraphCommunities,
|
||||||
GraphPath,
|
GraphPath,
|
||||||
PageRankOptions,
|
RankOptions,
|
||||||
ComponentsOptions,
|
CommunitiesOptions,
|
||||||
ShortestPathOptions,
|
PathOptions,
|
||||||
NeighborhoodSampleOptions,
|
SampleOptions,
|
||||||
TopByDegreeOptions
|
MostConnectedOptions
|
||||||
} from './plugin.js'
|
} from './plugin.js'
|
||||||
|
|
||||||
// Export embedding functionality
|
// Export embedding functionality
|
||||||
|
|
|
||||||
112
src/plugin.ts
112
src/plugin.ts
|
|
@ -400,69 +400,77 @@ export interface GraphCursorChunk {
|
||||||
done: boolean
|
done: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Per-node scalar scores (pageRank, topByDegree); `scores[i]` belongs to `nodeInts[i]`. */
|
/** Per-node scores returned by `rank` / `mostConnected`; `scores[i]` belongs to `nodeInts[i]` (descending). */
|
||||||
export interface GraphScores {
|
export interface GraphScores {
|
||||||
nodeInts: BigInt64Array
|
nodeInts: BigInt64Array
|
||||||
scores: Float64Array
|
scores: Float64Array
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Connected-component labelling; `componentIds[i]` is the component of `nodeInts[i]`. */
|
/** Community/cluster labelling; `communityIds[i]` is the group of `nodeInts[i]`. */
|
||||||
export interface GraphComponents {
|
export interface GraphCommunities {
|
||||||
nodeInts: BigInt64Array
|
nodeInts: BigInt64Array
|
||||||
componentIds: Uint32Array
|
communityIds: Uint32Array
|
||||||
componentCount: number
|
communityCount: number
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A shortest path: the node sequence + the edges between them (or `null` if unreachable). */
|
/** A path between two nodes — the node sequence + the edges between them (or `null` if unreachable). */
|
||||||
export interface GraphPath {
|
export interface GraphPath {
|
||||||
nodeInts: BigInt64Array
|
nodeInts: BigInt64Array
|
||||||
edgeVerbInts: BigInt64Array
|
edgeVerbInts: BigInt64Array
|
||||||
/** Sum of edge weights for a weighted path; hop count for an unweighted one. */
|
/** Cost of the path: number of hops, or summed edge weight when `by: 'weight'`. */
|
||||||
cost: number
|
cost: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PageRankOptions {
|
/**
|
||||||
/** Damping factor (default 0.85). */
|
* Options for `rank` (importance / influence ranking). INTENT-level only — the
|
||||||
damping?: number
|
* ranking ALGORITHM is the provider's choice (the JS fallback uses PageRank; a
|
||||||
/** Max power-iterations (default ~20). */
|
* native provider may use personalized PageRank, eigenvector centrality, etc.),
|
||||||
maxIterations?: number
|
* so no algorithm-tuning knobs are exposed here.
|
||||||
/** Convergence tolerance. */
|
*/
|
||||||
tolerance?: number
|
export interface RankOptions {
|
||||||
excludeVisibility?: string[]
|
/** Return only the top-K nodes by score (default: all). */
|
||||||
/** Return only the top-K by score (default: all). */
|
|
||||||
topK?: number
|
topK?: number
|
||||||
}
|
/** Visibility tiers to EXCLUDE from the ranked set (default `['internal','system']`). */
|
||||||
|
|
||||||
export interface ComponentsOptions {
|
|
||||||
/** `'weak'` ignores direction (default); `'strong'` honors it. */
|
|
||||||
mode?: 'weak' | 'strong'
|
|
||||||
excludeVisibility?: string[]
|
excludeVisibility?: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ShortestPathOptions {
|
/** Options for `communities` (grouping related nodes). The grouping algorithm is the provider's choice. */
|
||||||
|
export interface CommunitiesOptions {
|
||||||
|
/** Treat the graph as directed when grouping (default `false` — direction-agnostic). */
|
||||||
|
directed?: boolean
|
||||||
|
excludeVisibility?: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Options for `path` (best route between two nodes). */
|
||||||
|
export interface PathOptions {
|
||||||
direction?: GraphTraversalDirection
|
direction?: GraphTraversalDirection
|
||||||
/** `'edge'` = weighted by edge weight; `'hops'` = unweighted BFS (default `'hops'`). */
|
/** Optimize for fewest `'hops'` (default) or least summed edge `'weight'`. */
|
||||||
weight?: 'edge' | 'hops'
|
by?: 'hops' | 'weight'
|
||||||
|
/** Restrict the route to these verb-type indices (TypeIdx). */
|
||||||
verbTypes?: number[]
|
verbTypes?: number[]
|
||||||
excludeVisibility?: string[]
|
excludeVisibility?: string[]
|
||||||
/** Abandon the search past this many hops. */
|
/** Abandon the search past this many hops. */
|
||||||
maxDepth?: number
|
maxDepth?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NeighborhoodSampleOptions {
|
/** Options for `sample` (a representative neighborhood sample for dense-graph viz). */
|
||||||
|
export interface SampleOptions {
|
||||||
|
/** Max hop distance from any seed. */
|
||||||
depth: number
|
depth: number
|
||||||
direction?: GraphTraversalDirection
|
direction?: GraphTraversalDirection
|
||||||
/** Max neighbors to sample per node (random, seeded for reproducibility). */
|
/** Max neighbors kept per node (random, seeded for reproducibility). */
|
||||||
fanout: number
|
fanout: number
|
||||||
/** RNG seed so a given (seeds, opts, seed) yields a stable sample for viz. */
|
/** RNG seed so a given (seeds, opts, seed) yields a stable sample. */
|
||||||
seed?: number
|
seed?: number
|
||||||
excludeVisibility?: string[]
|
excludeVisibility?: string[]
|
||||||
maxNodes?: number
|
maxNodes?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TopByDegreeOptions {
|
/** Options for `mostConnected` (the most-connected nodes). */
|
||||||
direction?: GraphTraversalDirection
|
export interface MostConnectedOptions {
|
||||||
|
/** Return the top-K most-connected nodes. */
|
||||||
topK: number
|
topK: number
|
||||||
|
direction?: GraphTraversalDirection
|
||||||
excludeVisibility?: string[]
|
excludeVisibility?: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -538,45 +546,53 @@ export interface GraphAccelerationProvider {
|
||||||
graphCursorClose(handle: GraphCursorHandle): Promise<void>
|
graphCursorClose(handle: GraphCursorHandle): Promise<void>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description PageRank over the visible graph (hidden tiers excluded by default,
|
* @description Rank nodes by influence/importance over the VISIBLE graph (hidden
|
||||||
* so importance reflects the public view).
|
* tiers excluded by default, so the ranking reflects the public view). The
|
||||||
* @param options - Damping, iterations, tolerance, visibility, optional top-K.
|
* ranking ALGORITHM is the provider's choice — the JS fallback uses PageRank; a
|
||||||
|
* native provider may use personalized PageRank, eigenvector centrality, etc. The
|
||||||
|
* intent ("which nodes matter most") is the contract, not the algorithm.
|
||||||
|
* @param options - Top-K + visibility (intent-level; no algorithm tuning).
|
||||||
* @param generation - Optional as-of generation.
|
* @param generation - Optional as-of generation.
|
||||||
* @returns Per-node scores.
|
* @returns Per-node scores, descending.
|
||||||
*/
|
*/
|
||||||
pageRank(options: PageRankOptions, generation?: bigint): Promise<GraphScores>
|
rank(options: RankOptions, generation?: bigint): Promise<GraphScores>
|
||||||
/**
|
/**
|
||||||
* @description Connected components over the visible graph.
|
* @description Group related nodes into communities over the VISIBLE graph. The
|
||||||
* @param options - Weak/strong, visibility.
|
* grouping ALGORITHM is the provider's choice — the JS fallback uses connected
|
||||||
|
* components; a native provider may use community detection (e.g. Louvain/Leiden).
|
||||||
|
* @param options - Directed-grouping toggle + visibility.
|
||||||
* @param generation - Optional as-of generation.
|
* @param generation - Optional as-of generation.
|
||||||
* @returns Per-node component labels + component count.
|
* @returns Per-node community labels + community count.
|
||||||
*/
|
*/
|
||||||
connectedComponents(options: ComponentsOptions, generation?: bigint): Promise<GraphComponents>
|
communities(options: CommunitiesOptions, generation?: bigint): Promise<GraphCommunities>
|
||||||
/**
|
/**
|
||||||
* @description Shortest path between two nodes (weighted by edge weight or hop count).
|
* @description Find the best path between two nodes — fewest hops by default, or
|
||||||
|
* least summed edge weight with `by: 'weight'`. The pathfinding ALGORITHM is the
|
||||||
|
* provider's choice (JS fallback: BFS / Dijkstra).
|
||||||
* @param fromInt - Start node int.
|
* @param fromInt - Start node int.
|
||||||
* @param toInt - End node int.
|
* @param toInt - End node int.
|
||||||
* @param options - Direction, weighting, filters, max depth.
|
* @param options - Direction, cost basis (`by`), verb-type filter, max depth, visibility.
|
||||||
* @param generation - Optional as-of generation.
|
* @param generation - Optional as-of generation.
|
||||||
* @returns The path, or `null` if `toInt` is unreachable from `fromInt`.
|
* @returns The path, or `null` if `toInt` is unreachable from `fromInt`.
|
||||||
*/
|
*/
|
||||||
shortestPath(fromInt: bigint, toInt: bigint, options: ShortestPathOptions, generation?: bigint): Promise<GraphPath | null>
|
path(fromInt: bigint, toInt: bigint, options: PathOptions, generation?: bigint): Promise<GraphPath | null>
|
||||||
/**
|
/**
|
||||||
* @description Bounded, randomly-sampled neighborhood expansion (capped fan-out per
|
* @description A bounded, representative SAMPLE of the neighborhood around the seeds
|
||||||
* node) — a representative subgraph for dense-graph viz. Seeded for reproducibility.
|
* (capped fan-out per node) — for dense-graph viz. Seeded for reproducibility.
|
||||||
* @param seeds - Start nodes (ints or an {@link OpaqueIdSet}).
|
* @param seeds - Start nodes (ints or an {@link OpaqueIdSet}).
|
||||||
* @param options - Depth, fan-out, RNG seed, visibility, node cap.
|
* @param options - Depth, fan-out, RNG seed, visibility, node cap.
|
||||||
* @param generation - Optional as-of generation.
|
* @param generation - Optional as-of generation.
|
||||||
* @returns The sampled {@link Subgraph}.
|
* @returns The sampled {@link Subgraph}.
|
||||||
*/
|
*/
|
||||||
neighborhoodSample(seeds: bigint[] | OpaqueIdSet, options: NeighborhoodSampleOptions, generation?: bigint): Promise<Subgraph>
|
sample(seeds: bigint[] | OpaqueIdSet, options: SampleOptions, generation?: bigint): Promise<Subgraph>
|
||||||
/**
|
/**
|
||||||
* @description The top-K nodes by degree over the visible graph.
|
* @description The top-K most-connected nodes over the VISIBLE graph. The
|
||||||
* @param options - Direction, K, visibility.
|
* connectivity metric is the provider's choice (JS fallback: edge-count degree).
|
||||||
|
* @param options - Top-K, direction, visibility.
|
||||||
* @param generation - Optional as-of generation.
|
* @param generation - Optional as-of generation.
|
||||||
* @returns Per-node degree scores (descending).
|
* @returns Per-node connectivity scores, descending.
|
||||||
*/
|
*/
|
||||||
topByDegree(options: TopByDegreeOptions, generation?: bigint): Promise<GraphScores>
|
mostConnected(options: MostConnectedOptions, generation?: bigint): Promise<GraphScores>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -45,11 +45,11 @@ function makeMockAccel() {
|
||||||
graphCursorClose: async () => {
|
graphCursorClose: async () => {
|
||||||
calls.cursorClose++
|
calls.cursorClose++
|
||||||
},
|
},
|
||||||
pageRank: async () => empty,
|
rank: async () => empty,
|
||||||
connectedComponents: async () => ({ nodeInts: new BigInt64Array(0), componentIds: new Uint32Array(0), componentCount: 0 }),
|
communities: async () => ({ nodeInts: new BigInt64Array(0), communityIds: new Uint32Array(0), communityCount: 0 }),
|
||||||
shortestPath: async () => null,
|
path: async () => null,
|
||||||
neighborhoodSample: async () => state.traverseResult,
|
sample: async () => state.traverseResult,
|
||||||
topByDegree: async () => empty
|
mostConnected: async () => empty
|
||||||
}
|
}
|
||||||
return { provider, state }
|
return { provider, state }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue