UNPKG

@thi.ng/cellular

Version:

Highly customizable 1D cellular automata, shared env, multiple rules, arbitrary sized/shaped neighborhoods, short term memory, cell states etc.

232 lines 9.14 kB
import type { IClear, TypedArray, UIntArray } from "@thi.ng/api"; import type { IRandom } from "@thi.ng/random"; import type { CAConfig1D, CASpec1D, Kernel, Target, UpdateImageOpts1D } from "./api.js"; /** * Standard Wolfram automata 3-neighborhood (no history) */ export declare const WOLFRAM3: Kernel; /** * Standard 5-neighborhood (no history) */ export declare const WOLFRAM5: Kernel; /** * Standard 7-neighborhood (no history) */ export declare const WOLFRAM7: Kernel; /** * Implementation of a 1D cellular automata environment with support for * multiple automata, each with its own settings for replication rules, * arbitrary neighborhood kernels (optionally with short term memory) and number * of cell states, all selectable via a shared per-cell mask array. This generic * setup enables many novel and unusual CA setups as well as coevolution of * multiple CAs within a shared environment. * * @remarks * ### Neighborhoods * * Cell neighborhoods are defined via an arbitrary number of 2D offset vectors * `[x, y]`, where `x` coordinates are horizontal offsets and positive `y` * coordinates are used to refer to previous generations (e.g. 0 = current gen, * 1 = T-1, 2 = T-2 etc.) and thereby providing a form of short term memory for * that specific automata. Negative `y` coords will lead to cells being ignored. * * ### Rule encoding * * Automata rules are encoded as JS `BigInt` values and are considered * anisotropic by default. If isotropy is desired, it has to be explicitly * pre-encoded (out of scope of this library). There's also built-in optional * support for position independent neighborhood encoding, only considering the * number/count of non-zero cells. An encoded rule ID and its overall magnitude * is directly related and dependent on the size and shape of its kernel config, * e.g.: * * ```ts * kernel = [[-2, 1], [-1, 0], [0, 0], [1, 0], [2, 1]] * ``` * * This example kernel defines a 5-cell neighborhood with a max. short term * memory of one additional previous generation (i.e. the `[-2,1]` and `[2,1]` * offsets) * * The rules related to this kernel have a 32 bit address space (4 billion * possibilities), due to 2^5 = 32 and each kernel offset being assigned a * distinct bit value by default, i.e. first kernel offset = 2^0, second kernel * offset = 2^1, third = 2^2, fourth = 2^3, fifth = 2^4. Via the * {@link CASpec1D.positional} config option, this behavior can be overridden * per kernel, to achieve position-independent kernels (with much smaller rule * spaces). * * Given the following example cell matrix with the center cell highlighted with * caret (`^`): * * ```text * T-1: 2 0 1 2 1 * T-0: 0 1 0 3 0 * ^ * ``` * * The above example kernel will select the following values and assign bit * positions (for all non-zero cell states) to compute a summed ID: * * | k index | offset | cell value | encoded | * |--------:|-----------|-----------:|--------:| * | 0 | `[-2, 1]` | 2 | 1 | * | 1 | `[-1, 0]` | 1 | 2 | * | 2 | `[0, 0]` | 0 | 0 | * | 3 | `[1, 0]` | 3 | 8 | * | 4 | `[2, 1]` | 1 | 16 | * * Final encoded neighborhood sum: 1 + 2 + 8 + 16 = 27 * * To determine if a the current cell should be active or not in the next * generation, we now use that encoded sum as bit position to test a single bit * of the automata's rule ID, i.e. here we're testing bit 27. If that * corresponding bit is set in the rule ID, the cell's state will be increased * by 1. * * ### Cell states * * Each automata config can define a max. number of possible cell states (aka * age). Once a cell reaches the configured `numStates`, it automatically resets * to zero. This is by default, but can be overridden via the * {@link CASpec1D.reset} option. Conversely, if the corresponding bit is _not_ * set in the rule ID, the cell state will be zeroed too. * * ### Update probabilities * * Each cell has an optional update probability, which is initialized to 1.0 by * default (i.e. to always be updated). Use * {@link MultiCA1D.updateProbabilistic} or {@link MultiCA1D.updateImage} to * take these probabilities into account. * * ### Wraparound * * By default the environment is configured to be toroidal, i.e. both left/right * sides of the env are connected. The behavior can be controlled via a ctor arg * and/or at runtime via the {@link MultiCA1D.wrap} property. * * ### Masks * * The {@link MultiCA1D.mask} array can be used to select different CA * configurations for each cell in the environment. Because this mask array is * initialized to zero, only the first CA configuration will be used for all * cells in the environment by default. It's the user's responsibility to manage * the mask and select/enable other (if any) CA configs for individual cells * (usually cell ranges). The values stored in this array correspond to the * indices of the {@link MultiCA1D.configs} array given at construction. * * ### Limits * * Due to using `Uint8Arrays` for storage, only up to 256 cell states are * supported. The same limit applies to the number of CA configs given. * * @example * ```ts tangle:../export/wolfram.ts * import { MultiCA1D } from "@thi.ng/cellular"; * * // classic Wolfram Rule 110 automata * const wolfram = new MultiCA1D( * [{ * kernel: [[-1, 0], [0, 0], [1, 0]], * rule: 110, * states: 2, * reset: false * }], * 256 * ); * ``` */ export declare class MultiCA1D implements IClear { width: number; wrap: boolean; configs: CAConfig1D[]; rows: number; numStates: number; mask: Uint8Array; gens: Uint8Array[]; prob: Float32Array; constructor(configs: CASpec1D[], width: number, wrap?: boolean); get current(): Uint8Array<ArrayBufferLike>; get previous(): Uint8Array<ArrayBufferLike>; clear(): void; clearTarget(target: Target): void; resize(width: number): void; /** * Sets a parametric pattern in the current generation or mask array. * * @param target - target buffer ID to apply pattern * @param width - number of consecutive cells per segment * @param stride - number of cells between each pattern segment * @param val - start cell value per segment * @param inc - cell value increment * @param offset - start cell offset */ setPattern(target: Target, width: number, stride: number, val?: number, inc?: number, offset?: number): this; /** * Sets cells in current generation array to a random state using given * `probability` and optional PRNG * ([`IRandom`](https://docs.thi.ng/umbrella/random/interfaces/IRandom.html) * instance). * * @param target * @param prob * @param rnd */ setNoise(target: Target, prob?: number, rnd?: IRandom): this; /** * Computes a single new generation using current cell states and mask only * (no consideration for cell update probabilities, use * {@link MultiCA1D.updateProbabilistic} for that instead). Als see * {@link MultiCA1D.updateImage} for batch updates. */ update(): void; /** * Same as {@link MultiCA1D.update}, but also considering cell update * probabilities stored in the {@link MultiCA1D.prob} array. * * @param rnd */ updateProbabilistic(rnd?: IRandom): void; /** * Computes (but doesn't apply) the new state for a single cell. * * @param config - CA configuration * @param x - cell index * @param val - current cell value */ computeCell({ rule, kernel, weights, fn }: CAConfig1D, x: number, val: number): number; /** * Batch version of {@link MultiCA1D.update} to compute an entire image of * given `height` (and assumed to be the same width as this CA instance has * been configured to). Fills given `pixels` array with consecutive * generations. * * @remarks * Via the provided options object, per-generation & per-cell perturbance * settings can be provided for cell states, mask and cell update * probabilities. The latter are only considered if the * {@link UpdateImageOpts1D.probabilistic} option is enabled. This can be * helpful to sporadically introduce noise into the sim, break constant * patterns and/or produce more varied/complex outputs. * * See {@link UpdateImageOpts1D} for further options. * * @param pixels * @param height * @param opts */ updateImage(pixels: UIntArray, height: number, opts?: Partial<UpdateImageOpts1D>): void; rotate(target: Target | "all", dir: number): void; protected _getTarget(target: Target): [TypedArray, number]; } /** * Creates a random rule ID for given `kernelSize` and using optionally provided * `rnd` * [`IRandom`](https://docs.thi.ng/umbrella/random/interfaces/IRandom.html) * instance. * * @param kernelSize * @param rnd */ export declare const randomRule1D: (kernelSize: number, rnd?: IRandom) => bigint; //# sourceMappingURL=1d.d.ts.map