CIRCUIT COMPONENTS

auto

image

Auto-associative topological memory component, storing items and hypergraphs.

See also: https://creatingintelligence.org/#auto-associative-memory

Details and properties

  • Incrementally learns auto-associations at every execution cycle.
  • Uses update rule plugins to control the mechanics of state updates.
  • Controls sparsity through stochastic subsampling mechanisms.
  • Deduplicates incoming multisets and inhibitory signals, internally processing the underlying set of unique elements.
  • Supports multiple data blocks, joined internally as the memory’s shared input/output layer. The hyperparameters of input and output blocks must be identical.


Property Default Description
send required [integer,...] representing one or more output slots
receive required same as send, with optional pathway tags
plugin replacement auto-associative update rule
threshold automatic relative auto-associative pattern matching threshold
residual unlimited non-matching query elements that may be absorbed as noise, relative to the input population; 0 requires a full match
rate_limit unlimited subsample input if it exceeds the specified relative rate limit
decimate 1 proportional stochastic decimation
learn 1 learning threshold or interval, given as scaling factors relative to the default population


Use standard style options to customize the component’s appearance in circuit schematics.

Auto-associative memory with replacement update

As the default update rule for the auto component, replacement substitutes the memory’s state with the retrieved value.

This is the classic auto-associative setup, most useful for pattern completion, denoising, and item stores. With this configuration, the auto-associative memory converges to a stable state. Stability is normally reached with just a single cycle because denoising iterations are already encapsulated within the memory retrieval algorithm.

{ "hyperparameters": {"default": [1000, 10]},
  "dataflow": [
    {"component": "input", "send": [1]},
    {"component": "auto", "plugin": "replacement", 
        "send": [2], "receive": [1]},
    {"component": "output", "receive": [2]}
  ]}

image

Auto-associative memory with residual update

As a plugin for the auto component, the residual update rule removes the retrieved pattern from the query, leaving only the novel elements. This mechanism is the basis for associative novelty detection.

{ "hyperparameters": {"default": [1000, 10]},
  "dataflow": [
    {"component": "input", "send": [1]},
    {"component": "auto", "plugin": "residual", "send": [2], "receive": [1]},
    {"component": "output", "receive": [2]}
  ]}

image

Auto-associative memory with difference update

As a plugin for the auto component, the difference update rule replaces the memory’s state with the symmetric difference between the query and the retrieved data, removing the matching elements.

This update rule enables generative behavior in auto-associative memory retrieval.

{ "hyperparameters": {"default": [1000, 10]},
  "dataflow": [
    {"component": "input", "send": [1]},
    {"component": "auto", "plugin": "difference", 
        "send": [2], "receive": [1]},
    {"component": "output", "receive": [2]}
  ]}

image

Auto-associative memory with complement update

As a plugin for the auto component, the complement update removes the query pattern from the retrieved pattern, returning only the completed or predicted elements.

{ "hyperparameters": {"default": [1000, 10]},
  "dataflow": [
    {"component": "input", "send": [1]},
    {"component": "auto", "plugin": "complement", "send": [2], "receive": [1]},
    {"component": "output", "receive": [2]}
  ]}

image

Auto-associative memory with augmentation update

As a plugin for the auto component, augmentation aggregates the memory’s state with the retrieved value, then deduplicating the multiset to give its underlying set of unique elements.

The augmentation rule completes the input while retaining non-matching elements. Used iteratively in conjunction with stochastic subsampling, this mechanism converges incrementally to a stable state.

{ "hyperparameters": {"default": [1000, 10]},
  "dataflow": [
    {"component": "input", "send": [1]},
    {"component": "auto", "plugin": "augmentation", 
        "send": [2], "receive": [1]},
    {"component": "output", "receive": [2]}
  ]}

image

Auto-associative memory with coincidence update

As a plugin for the auto component, the coincidence update rule retains the matching elements between the query and the retrieved pattern.

{ "hyperparameters": {"default": [1000, 10]},
  "dataflow": [
    {"component": "input", "send": [1]},
    {"component": "auto", "plugin": "coincidence", 
        "send": [2], "receive": [1]},
    {"component": "output", "receive": [2]}
  ]}

image

Source code

def auto(config):
    plugin_factory = config.get("plugin", replacement)

    if isinstance(plugin_factory, str):
        # Resolve string name to function dynamically
        import sys
        plugin_factory = getattr(
            sys.modules[__name__],
            plugin_factory,
            replacement)

    plugin = plugin_factory(config)

    receive_blocks = config.get("receive_blocks", [])
    dims = [b[0] for b in receive_blocks]

    # params = Plus @@ config["receive_blocks"] (Sums Ns and Ps respectively)
    params = [sum(b[0] for b in receive_blocks), sum(b[1]
                                                     for b in receive_blocks)]
    pop = params[1] if len(params) > 1 else 0

    # Limit size of query pattern, relative to pop.
    # Default: total input dimension (no limit).
    if "rate_limit" in config:
        absratelimit = round(pop * config["rate_limit"])
    else:
        absratelimit = sum(dims)

    decimation = config.get("decimate", 1.0)

    # Learning thresholds
    min_val = pop
    max_val = pop
    learn_val = config.get("learn", False)

    if isinstance(learn_val, (int, float)) and not isinstance(learn_val, bool):
        min_val = max_val = round(learn_val * pop)
    elif isinstance(learn_val, (list, tuple)) and len(learn_val) == 2:
        min_val = round(learn_val[0] * pop)
        max_val = round(learn_val[1] * pop)

    # Memory with identical input and output parameters
    m_config = dict(config)
    m_config.update({
        "A_parameters": params,
        "B_parameters": params
    })

    # Memory backend
    M = Memory(m_config)

    def f(*blocks):
        # Join partitions and apply inhibition
        A = resolve_block_join_normal(list(blocks), dims)
        X = A

        # Limit the rate of incoming positives
        if len(X) > absratelimit:
            X = sorted(
                rng.choice(
                    X,
                    size=absratelimit,
                    replace=False).tolist())

        # Proportional decimation
        if decimation < 1.0:
            sample_size = math.floor(decimation * len(X))
            Xdec = sorted(
                rng.choice(
                    X,
                    size=sample_size,
                    replace=False).tolist())
        else:
            Xdec = X

        # Always learn if "learn" is True
        if learn_val is True:
            M["store"](A)

        # Memory retrieval with decimated and rate-limited input state
        Y = M["retrieve"](Xdec)

        # Learn input A if retrieval fails and it falls within thresholds
        if not Y and min_val <= len(A) <= max_val:
            if learn_val is not True:
                M["store"](A)
            Y = A

        X_out = plugin["updaterule"](Y, X)
        X_out = sorted(list(set(X_out)))

        return tuple(multiset_block_split(X_out, dims))

    # Merge plugin attributes, component defaults, and Memory closures (e.g.,
    # "clear")
    result = dict(plugin)
    result.update({
        "function": f,
        "checks": ["arginp", "argout", "ident"],
        "shape": "square", "fill": 8
    })
    result.update(M)

    return result