UNPKG

@rimbu/graph

Version:

Immutable Graph data structures for TypeScript

322 lines (317 loc) 10.6 kB
import type { RelatedTo, ToJSON, TraverseState } from '@rimbu/common'; import type { FastIterable, Stream, Streamable, StreamSource, } from '@rimbu/stream'; import type { GraphValues, WithGraphValues } from '../index.mjs'; import type { Link } from '../index.mjs'; export interface VariantGraphBase< N, V, Tp extends VariantGraphBase.Types = VariantGraphBase.Types, > extends FastIterable<[N] | WithGraphValues<Tp, N, V>['link']> { /** * Returns true if the graph is an arrow (directed) graph. */ readonly isDirected: boolean; /** * Returns true if the graph has no nodes. * @example * ```ts * ArrowGraphHashed.empty<number>().isEmpty // => true * ArrowGraphHashed.of([1]).isEmpty // => false * ``` */ readonly isEmpty: boolean; /** * Returns the amount of nodes in the graph. * @example * ```ts * ArrowGraphHashed.empty<number>().nodeSize // => 0 * ArrowGraphHashed.of([1], [2, 3]).nodeSize // => 3 * ``` */ readonly nodeSize: number; /** * Returns the amount of connections in the graph. * @example * ```ts * ArrowGraphHashed.empty<number>().connectionSize // => 0 * ArrowGraphHashed.of([1], [2, 3]).connectionSize // => 1 * ``` */ readonly connectionSize: number; /** * Returns true if there is at least one node in the collection, and instructs the compiler to treat the collection * as a .NonEmpty type. * @example * ```ts * const g: ArrowGraphHashed<number> = ArrowGraphHashed.of([1, 1], [2, 2]) * g.streamNodes().first(0) // compiler allows fallback value since the Stream may be empty * if (g.nonEmpty()) { * g.streamNodes().first(0) // compiler error: fallback value not allowed since Stream is not empty * } * ``` */ nonEmpty(): this is WithGraphValues<Tp, N, V>['nonEmpty']; /** * Returns the collection as a .NonEmpty type * @throws RimbuError.EmptyCollectionAssumedNonEmptyError if the collection is empty * @example * ```ts * ArrowGraphHashed.empty<number>().assumeNonEmpty() // => throws * const g: ArrowGraphHashed<number> = ArrowGraphHashed.of([1, 1], [2, 2]) * const g2: ArrowGraphHashed.NonEmpty<number> = g // => compiler error * const g3: ArrowGraphHashed.NonEmpty<number> = g.assumeNonEmpty() * ``` * @note returns reference to this collection */ assumeNonEmpty(): WithGraphValues<Tp, N, V>['nonEmpty']; /** * Returns a `Stream` containing all graph elements of this collection as single tuples for isolated nodes * and 2-valued tuples of nodes for connections. * @example * ```ts * ArrowGraphHashed.of([1], [2, 3]).stream().toArray() // => [[1], [2, 3]] * ``` */ stream(): Stream<[N] | WithGraphValues<Tp, N, V>['link']>; /** * Returns a `Stream` containing all nodes of this collection. * @example * ```ts * ArrowGraphHashed.of([1], [2, 3]).stream().toArray() // => [1, 2, 3] * ``` */ streamNodes(): Stream<N>; /** * Returns a `Stream` containing all connections of this collection. * @example * ```ts * ArrowGraphHashed.of([1], [2, 3]).stream().toArray() // => [[2, 3]] * ``` */ streamConnections(): Stream<WithGraphValues<Tp, N, V>['link']>; /** * Returns true if the graph contains the given `node`. * @param node - the node to search * @example * ```ts * const g = ArrowGraphHashed.of([1], [2, 3]) * g.hasNode(2) // => true * g.hasNode(5) // => false * ``` */ hasNode<UN = N>(node: RelatedTo<N, UN>): boolean; /** * Returns true if the graph has a connection between given `node1` and `node2`. * @param node1 - the first connection node * @param node2 - the second connection node * @example * ```ts * const g = ArrowGraphHashed.of([1], [2, 3]) * g.hasConnection(2, 3) // => true * g.hasConnection(3, 1) // => false * ``` */ hasConnection<UN = N>( node1: RelatedTo<N, UN>, node2: RelatedTo<N, UN> ): boolean; /** * Returns a `Stream` containing all the connetions from the given `node1` * @param node1 - the first connection node * @example * ```ts * const g = ArrowGraphHashed.of([1], [2, 3]) * g.getConnectionStreamFrom(2).toArray() // => [3] * g.getConnectionStreamFrom(5).toArray() // => [] * ``` */ getConnectionStreamFrom<UN = N>( node1: RelatedTo<N, UN> ): Stream<WithGraphValues<Tp, N, V>['link']>; /** * Returns a `Stream` containing all the connetions to the given `node2` * @param node2 - the second connection node * @example * ```ts * const g = ArrowGraphHashed.of([1], [2, 3]) * g.getConnectionStreamTo(3).toArray() // => [2] * g.getConnectionStreamTo(5).toArray() // => [] * ``` */ getConnectionStreamTo<UN = N>( node2: RelatedTo<N, UN> ): Stream<WithGraphValues<Tp, N, V>['link']>; /** * Returns the graph with the given `node` and all its connections removed. * @param node - the node to remove * @example * ```ts * const g = ArrowGraphHashed.of([1], [2, 3]) * g.removeNode(2).stream().toArray() // => [[1]] * g.removeNode(6).stream().toArray() // => [[1], [2, 3]] * ``` */ removeNode<UN = N>( node: RelatedTo<N, UN> ): WithGraphValues<Tp, N, V>['normal']; /** * Returns the graph with all nodes in given `nodes` stream removed, together with all their * connections. * @param nodes - a `StreamSource` containing the nodes to remove * @example * ```ts * const g = ArrowGraphHashed.of([1], [2, 3]) * g.removeNodes([2, 3]).stream().toArray() // => [[1]] * g.removeNodes([4, 5]).stream().toArray() // => [[1], [2, 3]] * ``` */ removeNodes<UN = N>( nodes: StreamSource<RelatedTo<N, UN>> ): WithGraphValues<Tp, N, V>['normal']; /** * Returns the graph with the connection between given `node1` and `node2` removed if it exists. * @param node1 - the first connection node * @param node2 - the second connectio node * @example * ```ts * const g = ArrowGraphHashed.of([1], [2, 3]) * g.disconnect(2, 3).stream().toArray() // => [[1], [2], [3]] * g.disconnect(1, 2).stream().toArray() // => [[1], [2, 3]] * ``` */ disconnect<UN = N>( node1: RelatedTo<N, UN>, node2: RelatedTo<N, UN> ): WithGraphValues<Tp, N, V>['normal']; /** * Returns the graph with all connections in given `links` removed if they exist. * @param links - a `StreamSource` containing tuples of nodes representing connections * @example * ```ts * const g = ArrowGraphHashed.of([1], [2, 3]) * g.disconnectAll([[1, 2], [3, 4]]).stream().toArray() // => [[1], [2, 3]] * g.disconnectAll([[2, 3], [3, 4]]).stream().toArray() // => [[1], [2], [3]] * ``` */ disconnectAll<UN = N>( links: StreamSource<Link<RelatedTo<N, UN>>> ): WithGraphValues<Tp, N, V>['normal']; /** * Returns the graph with all isolated nodes removed. * @example * ```ts * const g = ArrowGraphHashed.of([1], [2, 3]) * g.removeUnconnectedNodes().stream().toArray() // => [[2, 3]] * ``` */ removeUnconnectedNodes(): WithGraphValues<Tp, N, V>['normal']; /** * Performs given function `f` for each entry of the collection, using given `state` as initial traversal state. * @param f - the function to perform for each entry, receiving:<br/> * - `entry`: the next graph element<br/> * - `index`: the index of the element<br/> * - `halt`: a function that, if called, ensures that no new elements are passed * @param options - object containing the following<br/> * - state: (optional) the traverse state * @example * ```ts * const g = ArrowGraphHashed.of([1], [2, 3], [4]) * g.forEach((entry, i, halt) => { * console.log([entry]); * if (i >= 1) halt(); * }) * // => logs [1] [2, 3] * ``` * @note O(N) */ forEach( f: ( entry: [N] | WithGraphValues<Tp, N, V>['link'], index: number, halt: () => void ) => void, options?: { state?: TraverseState } ): void; /** * Returns a string representation of this collection. * @example * ```ts * ArrowGraphHashed.of([1], [2, 3]).toString() // => ArrowGraphHashed(1 => [], 2 => [3]) * ``` */ toString(): string; /** * Returns a JSON representation of this collection. * @example * ```ts * ArrowGraphHashed.of([1], [2, 3]).toJSON() * // => { dataType: 'ArrowGraphHashed', value: [[1, []], [2, [3]]] } * ``` */ toJSON(): ToJSON<[N, WithGraphValues<Tp, N, V>['linkTarget'][]][]>; } export namespace VariantGraphBase { export interface NonEmpty< N, V, Tp extends VariantGraphBase.Types = VariantGraphBase.Types, > extends VariantGraphBase<N, V, Tp>, Streamable.NonEmpty<[N] | WithGraphValues<Tp, N, V>['link']> { /** * Returns false since the graph is known to be non-empty. * @example * ```ts * ArrowGraphHashed.empty<number>().isEmpty // => true * ArrowGraphHashed.of([1]).isEmpty // => false * ``` */ readonly isEmpty: false; /** * Returns true since this collection is known to be non-empty * @example * ```ts * ArrowGraphHashed.of([1], [2, 3]).nonEmpty() // => true * ``` */ nonEmpty(): this is WithGraphValues<Tp, N, V>['nonEmpty']; /** * Returns this collection typed as a 'possibly empty' collection. * @example * ```ts * ArrowGraphHashed.of([1], [2, 3]).asNormal(); // type: ArrowGraphHashed<number> * ``` */ asNormal(): WithGraphValues<Tp, N, V>['normal']; /** * Returns a non-empty `Stream` containing all graph elements of this collection as single tuples for isolated nodes * and 2-valued tuples of nodes for connections. * @example * ```ts * ArrowGraphHashed.of([1], [2, 3]).stream().toArray() // => [[1], [2, 3]] * ``` */ stream(): Stream.NonEmpty<[N] | WithGraphValues<Tp, N, V>['link']>; /** * Returns a non-empty `Stream` containing all nodes of this collection. * @example * ```ts * ArrowGraphHashed.of([1], [2, 3]).stream().toArray() // => [1, 2, 3] * ``` */ streamNodes(): Stream.NonEmpty<N>; } /** * Utility interface that provides higher-kinded types for this collection. */ export interface Types extends GraphValues { readonly normal: VariantGraphBase<this['_N'], this['_V']>; readonly nonEmpty: VariantGraphBase.NonEmpty<this['_N'], this['_V']>; readonly link: Link<this['_N']>; readonly linkTarget: Link.Target<this['_N']>; } }