@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
TypeScript
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