UNPKG

tree-multimap-typed

Version:
341 lines (340 loc) 14.5 kB
/** * data-structure-typed * * @author Pablo Zeng * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com> * @license MIT License */ import type { DijkstraResult, EntryCallback, GraphOptions, VertexKey } from '../../types'; import { IterableEntryBase } from '../base'; import { IGraph } from '../../interfaces'; export declare abstract class AbstractVertex<V = any> { key: VertexKey; value: V | undefined; protected constructor(key: VertexKey, value?: V); } export declare abstract class AbstractEdge<E = any> { value: E | undefined; weight: number; protected constructor(weight?: number, value?: E); protected _hashCode: string; get hashCode(): string; } /** * Abstract graph over vertices and edges. * @template V - Vertex value type. * @template E - Edge value type. * @template VO - Concrete vertex subclass (extends AbstractVertex<V>). * @template EO - Concrete edge subclass (extends AbstractEdge<E>). * @remarks Time O(1), Space O(1) * @example examples will be generated by unit test */ export declare abstract class AbstractGraph<V = any, E = any, VO extends AbstractVertex<V> = AbstractVertex<V>, EO extends AbstractEdge<E> = AbstractEdge<E>> extends IterableEntryBase<VertexKey, V | undefined> implements IGraph<V, E, VO, EO> { /** * Construct a graph with runtime defaults. * @param options - `GraphOptions<V>` in `options.graph` (e.g. `vertexValueInitializer`, `defaultEdgeWeight`). * @remarks Time O(1), Space O(1) */ constructor(options?: Partial<Record<string, unknown>>); protected _options: GraphOptions<V>; get options(): Readonly<GraphOptions<V>>; protected _vertexMap: Map<VertexKey, VO>; get vertexMap(): Map<VertexKey, VO>; set vertexMap(v: Map<VertexKey, VO>); get size(): number; /** * Create a new vertex instance (implementation specific). * @param key - Vertex identifier. * @param value - Optional payload. * @returns Concrete vertex instance. * @remarks Time O(1), Space O(1) */ abstract createVertex(key: VertexKey, value?: V): VO; /** * Create a new edge instance (implementation specific). * @param srcOrV1 - Source/endpoint A key. * @param destOrV2 - Destination/endpoint B key. * @param weight - Edge weight (defaults may apply). * @param value - Edge payload. * @returns Concrete edge instance. * @remarks Time O(1), Space O(1) */ abstract createEdge(srcOrV1: VertexKey, destOrV2: VertexKey, weight?: number, value?: E): EO; /** * Delete an edge by instance. * @param edge - Edge instance. * @returns Removed edge or `undefined`. * @remarks Time O(1) avg, Space O(1) */ abstract deleteEdge(edge: EO): EO | undefined; /** * Get an edge between two vertices if present. * @param srcOrKey - Source/endpoint A vertex or key. * @param destOrKey - Destination/endpoint B vertex or key. * @returns Edge instance or `undefined`. * @remarks Time O(1) avg, Space O(1) */ abstract getEdge(srcOrKey: VO | VertexKey, destOrKey: VO | VertexKey): EO | undefined; /** * Degree of a vertex in this graph model. * @param vertexOrKey - Vertex or key. * @returns Non-negative integer degree. * @remarks Time O(1) avg, Space O(1) */ abstract degreeOf(vertexOrKey: VO | VertexKey): number; /** * All edges in the graph (unique, order not guaranteed). * @returns Array of edges. * @remarks Time O(E), Space O(E) */ abstract edgeSet(): EO[]; /** * Incident edges of a vertex. * @param vertexOrKey - Vertex or key. * @returns Array of incident edges. * @remarks Time O(deg), Space O(deg) */ abstract edgesOf(vertexOrKey: VO | VertexKey): EO[]; /** * One-step neighbors of a vertex. * @param vertexOrKey - Vertex or key. * @returns Array of neighbor vertices. * @remarks Time O(deg), Space O(deg) */ abstract getNeighbors(vertexOrKey: VO | VertexKey): VO[]; /** * Resolve endpoints of an edge to vertex instances. * @param edge - Edge instance. * @returns `[v1, v2]` or `undefined` if missing. * @remarks Time O(1), Space O(1) */ abstract getEndsOfEdge(edge: EO): [VO, VO] | undefined; /** * Get vertex instance by key. * @param vertexKey - Vertex key. * @returns Vertex instance or `undefined`. * @remarks Time O(1), Space O(1) */ getVertex(vertexKey: VertexKey): VO | undefined; /** * Whether a vertex exists. * @param vertexOrKey - Vertex or key. * @returns `true` if present, otherwise `false`. * @remarks Time O(1) avg, Space O(1) */ hasVertex(vertexOrKey: VO | VertexKey): boolean; addVertex(vertex: VO): boolean; addVertex(key: VertexKey, value?: V): boolean; /** * Type guard: check if a value is a valid vertex key. * @param potentialKey - Value to test. * @returns `true` if string/number; else `false`. * @remarks Time O(1), Space O(1) */ isVertexKey(potentialKey: any): potentialKey is VertexKey; /** * Delete a vertex and its incident edges. * @param vertexOrKey - Vertex or key. * @returns `true` if removed; otherwise `false`. * @remarks Time O(deg), Space O(1) */ abstract deleteVertex(vertexOrKey: VO | VertexKey): boolean; /** * Delete multiple vertices. * @param vertexMap - Array of vertices or keys. * @returns `true` if any vertex was removed. * @remarks Time O(sum(deg)), Space O(1) */ removeManyVertices(vertexMap: VO[] | VertexKey[]): boolean; /** * Whether an edge exists between two vertices. * @param v1 - Endpoint A vertex or key. * @param v2 - Endpoint B vertex or key. * @returns `true` if present; otherwise `false`. * @remarks Time O(1) avg, Space O(1) */ hasEdge(v1: VertexKey | VO, v2: VertexKey | VO): boolean; addEdge(edge: EO): boolean; addEdge(src: VO | VertexKey, dest: VO | VertexKey, weight?: number, value?: E): boolean; /** * Set the weight of an existing edge. * @param srcOrKey - Source vertex or key. * @param destOrKey - Destination vertex or key. * @param weight - New weight. * @returns `true` if updated; otherwise `false`. * @remarks Time O(1) avg, Space O(1) */ setEdgeWeight(srcOrKey: VertexKey | VO, destOrKey: VertexKey | VO, weight: number): boolean; /** * Enumerate simple paths up to a limit. * @param v1 - Source vertex or key. * @param v2 - Destination vertex or key. * @param limit - Maximum number of paths to collect. * @returns Array of paths (each path is an array of vertices). * @remarks Time O(paths) worst-case exponential, Space O(V + paths) */ getAllPathsBetween(v1: VO | VertexKey, v2: VO | VertexKey, limit?: number): VO[][]; /** * Sum the weights along a vertex path. * @param path - Sequence of vertices. * @returns Path weight sum (0 if empty or edge missing). * @remarks Time O(L), Space O(1) where L is path length */ getPathSumWeight(path: VO[]): number; /** * Minimum hops/weight between two vertices. * @param v1 - Source vertex or key. * @param v2 - Destination vertex or key. * @param isWeight - If `true`, compare by path weight; otherwise by hop count. * @returns Minimum cost or `undefined` if missing/unreachable. * @remarks Time O((V + E) log V) weighted / O(V + E) unweighted, Space O(V + E) */ getMinCostBetween(v1: VO | VertexKey, v2: VO | VertexKey, isWeight?: boolean): number | undefined; /** * Minimum path (as vertex sequence) between two vertices. * @param v1 - Source vertex or key. * @param v2 - Destination vertex or key. * @param isWeight - If `true`, compare by path weight; otherwise by hop count. * @param isDFS - For weighted mode only: if `true`, brute-force all paths; if `false`, use Dijkstra. * @returns Vertex sequence, or `undefined`/empty when unreachable depending on branch. * @remarks Time O((V + E) log V) weighted / O(V + E) unweighted, Space O(V + E) */ getMinPathBetween(v1: VO | VertexKey, v2: VO | VertexKey, isWeight?: boolean, isDFS?: boolean): VO[] | undefined; /** * Dijkstra without heap (array-based selection). * @param src - Source vertex or key. * @param dest - Optional destination for early stop. * @param getMinDist - If `true`, compute global minimum distance. * @param genPaths - If `true`, also generate path arrays. * @returns Result bag or `undefined` if source missing. * @remarks Time O(V^2 + E), Space O(V + E) */ dijkstraWithoutHeap(src: VO | VertexKey, dest?: VO | VertexKey | undefined, getMinDist?: boolean, genPaths?: boolean): DijkstraResult<VO> | undefined; dijkstra(src: VO | VertexKey, dest?: VO | VertexKey | undefined, getMinDist?: boolean, genPaths?: boolean): DijkstraResult<VO> | undefined; /** * Bellman-Ford single-source shortest paths with option to scan negative cycles. * @param src - Source vertex or key. * @param scanNegativeCycle - If `true`, also detect negative cycles. * @param getMin - If `true`, compute global minimum distance. * @param genPath - If `true`, generate path arrays via predecessor map. * @returns Result bag including distances, predecessors, and optional cycle flag. * @remarks Time O(V * E), Space O(V + E) */ bellmanFord(src: VO | VertexKey, scanNegativeCycle?: boolean, getMin?: boolean, genPath?: boolean): { hasNegativeCycle: boolean | undefined; distMap: Map<VO, number>; preMap: Map<VO, VO>; paths: VO[][]; min: number; minPath: VO[]; }; /** * Floyd–Warshall all-pairs shortest paths. * @returns `{ costs, predecessor }` matrices. * @remarks Time O(V^3), Space O(V^2) */ floydWarshall(): { costs: number[][]; predecessor: (VO | undefined)[][]; }; /** * Enumerate simple cycles (may be expensive). * @param isInclude2Cycle - If `true`, include 2-cycles when graph semantics allow. * @returns Array of cycles (each as array of vertex keys). * @remarks Time exponential in worst-case, Space O(V + E) */ getCycles(isInclude2Cycle?: boolean): VertexKey[][]; /** * Induced-subgraph filter: keep vertices where `predicate(key, value)` is true, * and only keep edges whose endpoints both survive. * @param predicate - `(key, value, index, self) => boolean`. * @param thisArg - Optional `this` for callback. * @returns A new graph of the same concrete class (`this` type). * @remarks Time O(V + E), Space O(V + E) */ filter(predicate: EntryCallback<VertexKey, V | undefined, boolean>, thisArg?: any): this; /** * Preserve the old behavior: return filtered entries as an array. * @remarks Time O(V), Space O(V) */ filterEntries(predicate: EntryCallback<VertexKey, V | undefined, boolean>, thisArg?: any): [VertexKey, V | undefined][]; map<T>(callback: EntryCallback<VertexKey, V | undefined, T>, thisArg?: any): T[]; /** * Create a deep clone of the graph with the same species. * @remarks Time O(V + E), Space O(V + E) */ /** * Create a deep clone of the graph with the same species. * @returns A new graph of the same concrete class (`this` type). * @remarks Time O(V + E), Space O(V + E) */ clone(): this; /** * Internal iterator over `[key, value]` entries in insertion order. * @returns Iterator of `[VertexKey, V | undefined]`. * @remarks Time O(V), Space O(1) */ protected _getIterator(): IterableIterator<[VertexKey, V | undefined]>; /** * Capture configuration needed to reproduce the current graph. * Currently the graph has no runtime options, so we return an empty object. */ /** * Capture configuration needed to reproduce the current graph. * @returns Options bag (opaque to callers). * @remarks Time O(1), Space O(1) */ protected _snapshotOptions(): Record<string, unknown>; /** * Create an empty graph instance of the same concrete species (Directed/Undirected/etc). * @remarks Time O(1), Space O(1) */ /** * Create an empty graph instance of the same concrete species. * @param _options - Snapshot options from `_snapshotOptions()`. * @returns A new empty graph instance of `this` type. * @remarks Time O(1), Space O(1) */ protected _createInstance(_options?: Partial<Record<string, unknown>>): this; /** * Create a same-species graph populated with the given entries. * Also preserves edges between kept vertices from the source graph. * @remarks Time O(V + E), Space O(V + E) */ /** * Create a same-species graph populated with entries; preserves edges among kept vertices. * @param iter - Optional entries to seed the new graph. * @param options - Snapshot options. * @returns A new graph of `this` type. * @remarks Time O(V + E), Space O(V + E) */ protected _createLike(iter?: Iterable<[VertexKey, V | undefined]>, options?: Partial<Record<string, unknown>>): this; /** * Internal hook to attach an edge into adjacency structures. * @param edge - Edge instance. * @returns `true` if inserted; otherwise `false`. * @remarks Time O(1) avg, Space O(1) */ protected abstract _addEdge(edge: EO): boolean; /** * Insert a pre-built vertex into the graph. * @param newVertex - Concrete vertex instance. * @returns `true` if inserted; `false` if key already exists. * @remarks Time O(1) avg, Space O(1) */ protected _addVertex(newVertex: VO): boolean; /** * Resolve a vertex key or instance to the concrete vertex instance. * @param vertexOrKey - Vertex key or existing vertex. * @returns Vertex instance or `undefined`. * @remarks Time O(1), Space O(1) */ protected _getVertex(vertexOrKey: VertexKey | VO): VO | undefined; /** * Resolve a vertex key from a key or vertex instance. * @param vertexOrKey - Vertex key or existing vertex. * @returns The vertex key. * @remarks Time O(1), Space O(1) */ protected _getVertexKey(vertexOrKey: VO | VertexKey): VertexKey; }