Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
Aleph::CA::Hashlife_Engine Class Reference

Hashlife engine for outer-totalistic binary cellular automata. More...

#include <tpl_ca_hashlife.H>

Collaboration diagram for Aleph::CA::Hashlife_Engine:
[legend]

Classes

struct  BBox
 Inclusive bounding box (returned by bbox). More...
 
struct  Stats
 Diagnostics returned by stats. More...
 

Public Types

using Rule = Outer_Totalistic_Binary_Rule
 Rule type used by the engine.
 

Public Member Functions

 Hashlife_Engine (Rule rule=Conway_Life, std::size_t cache_capacity=std::size_t{1}<< 22)
 Build an engine with the given rule and result-cache capacity.
 
void set_rule (const Rule &r)
 Replace the rule. Invalidates the result cache.
 
Rule rule () const noexcept
 Current rule.
 
void set_alive (const std::int64_t x, const std::int64_t y, const bool alive=true)
 Set or clear the cell at world coordinates (x, y).
 
bool alive_at (const std::int64_t x, const std::int64_t y) const
 Read the cell at world coordinates (x, y).
 
std::uint64_t advance (const unsigned k)
 Advance the universe by 2^k generations.
 
std::uint64_t run (std::uint64_t generations)
 Advance by exactly generations steps.
 
std::uint64_t population () const noexcept
 Number of alive cells.
 
std::int64_t generation () const noexcept
 Number of generations elapsed since construction (or the last clear).
 
BBox bbox () const
 Tight bounding box of the alive cells (empty if population() == 0).
 
void clear ()
 Reset the universe to empty (preserves rule, capacity and node cache).
 
Stats stats () const noexcept
 Diagnostic counters and current root level.
 
std::size_t cache_capacity () const noexcept
 Maximum allowed canonical-node count before the result cache is dropped.
 
template<typename F >
void for_each_alive (F &&f) const
 Iterate over all alive cells, calling f(x, y) for each.
 
void load_rle (std::istream &in)
 Load an RLE pattern from in (centred at the origin).
 
void load_rle_string (const std::string &s)
 Convenience overload that reads the pattern from a string.
 
void save_rle (std::ostream &out, const std::string &comment={}) const
 Write the alive cells in RLE format.
 
std::string save_rle_string (const std::string &comment={}) const
 Convenience overload returning the RLE serialisation as a string.
 

Private Types

using Node = ca_hashlife_detail::Node
 
using Node_Key = ca_hashlife_detail::Node_Key
 

Private Member Functions

Node * make_leaf (const std::uint8_t bits)
 
Node * make_node (Node *nw, Node *ne, Node *sw, Node *se)
 
Node * empty_node (const std::uint8_t level)
 
void clear_result_cache ()
 
Node * expand (const Node *n)
 
Node * horizontal_centered (Node *w, Node *e)
 
Node * vertical_centered (Node *n, Node *s)
 
Node * center_of_4 (Node *nw, Node *ne, Node *sw, Node *se)
 
Node * evolve_level_2 (Node *n)
 
Node * evolve (Node *n)
 
Node * set_in_node (const Node *n, const std::int64_t x, const std::int64_t y, const bool alive)
 
template<typename F >
void visit_alive (Node *n, std::int64_t x, std::int64_t y, F &&f) const
 

Static Private Member Functions

static bool is_centered_well (const Node *n) noexcept
 Standard Hashlife "centered well" predicate: every quadrant of n has its population concentrated in the sub-quadrant closest to the centre.
 
static bool get_in_node (const Node *n, const std::int64_t x, const std::int64_t y) noexcept
 
static std::int64_t parse_header_value (const std::string &line, const char key)
 
static std::optional< Outer_Totalistic_Binary_Rule > parse_rule_field (const std::string &line)
 

Private Attributes

Rule rule_
 
std::size_t cache_capacity_
 
std::deque< Node > pool_
 
std::unordered_map< Node_Key, Node *, ca_hashlife_detail::Node_Key_Hash > table_
 
Array< Node * > empty_by_level_
 Aleph::Array of canonical empties per level.
 
Node * root_ = nullptr
 
std::int64_t generation_ = 0
 
std::size_t result_hits_ = 0
 
std::size_t result_misses_ = 0
 
std::size_t result_cache_clears_ = 0
 

Static Private Attributes

static constexpr std::uint8_t initial_level_ = 3
 8 × 8 starting universe
 

Detailed Description

Hashlife engine for outer-totalistic binary cellular automata.

Implements Bill Gosper's Hashlife algorithm on top of a hash-consed quadtree. Suitable for very large patterns (10⁶+ cells) advanced by enormous numbers of generations (10⁹+) — uses cases that are out of reach for the dense Synchronous_Engine.

Algorithm
Every node represents a 2^k × 2^k square; level-1 leaves pack their 4 cells into a single byte. evolve(n) returns the central 2^(k-1) × 2^(k-1) area of n after 2^(k-2) generations: it builds the 9 overlapping level k-1 sub-squares of n, evolves each (giving 9 level k-2 results), recombines them into 4 level k-1 macrocells advanced by 2^(k-3) generations, and evolves those for another 2^(k-3) generations — totalling 2^(k-2).
Memoisation
Each canonical node caches its evolve result. Because identical subtrees share the same Node *, the recursion sees an effective subset of nodes that grows with the pattern's complexity, not its size. Patterns with strong spatial / temporal self-similarity (gliders, repeating engines, regular gun outputs) are accelerated by orders of magnitude.
Memory bounds
When the canonical-node hash table exceeds cache_capacity(), the per-node result pointers are invalidated (the canonical nodes themselves are kept alive). This bounds the memoisation footprint while preserving correctness; future evolve calls simply recompute.
Thread-safety
Not thread-safe. Each engine instance must be driven by a single thread; the canonical table and result cache are written during evolution.

Definition at line 300 of file tpl_ca_hashlife.H.

Member Typedef Documentation

◆ Node

◆ Node_Key

◆ Rule

Rule type used by the engine.

Definition at line 304 of file tpl_ca_hashlife.H.

Constructor & Destructor Documentation

◆ Hashlife_Engine()

Aleph::CA::Hashlife_Engine::Hashlife_Engine ( Rule  rule = Conway_Life,
std::size_t  cache_capacity = std::size_t{1} << 22 
)
inlineexplicit

Build an engine with the given rule and result-cache capacity.

Parameters
ruleouter-totalistic rule (default: Conway's Game of Life).
cache_capacitymaximum number of canonical nodes before the per-node result cache is dropped (default: 4 Mi).
Exceptions
std::domain_errorif cache_capacity < 1024.

Definition at line 350 of file tpl_ca_hashlife.H.

Member Function Documentation

◆ advance()

std::uint64_t Aleph::CA::Hashlife_Engine::advance ( const unsigned  k)
inline

Advance the universe by 2^k generations.

The universe is automatically padded so that evolution is well-defined. If the alive pattern is too dense to fit at level k + 2, the engine expands further and the call advances by 2^L generations for some L > k. Use the return value to discover the actual advance.

Parameters
klogarithm of the desired step size.
Returns
number of generations actually advanced (always a power of 2, always ≥ 2^k).
Exceptions
std::domain_errorif k > 62.

Definition at line 417 of file tpl_ca_hashlife.H.

References ah_domain_error_if, Aleph::blossom_maximum_cardinality_matching(), cache_capacity_, clear_result_cache(), evolve(), expand(), generation_, is_centered_well(), k, Aleph::CA::ca_hashlife_detail::Node::level, root_, steps, and table_.

Referenced by run(), TEST(), TEST(), TEST(), TEST(), TEST(), TEST(), TEST(), and TEST().

◆ alive_at()

bool Aleph::CA::Hashlife_Engine::alive_at ( const std::int64_t  x,
const std::int64_t  y 
) const
inline

Read the cell at world coordinates (x, y).

Cells outside the root area are reported as dead.

Definition at line 397 of file tpl_ca_hashlife.H.

References Aleph::blossom_maximum_cardinality_matching(), get_in_node(), Aleph::CA::ca_hashlife_detail::Node::level, root_, and y.

Referenced by TEST(), TEST(), and TEST().

◆ bbox()

BBox Aleph::CA::Hashlife_Engine::bbox ( ) const
inline

Tight bounding box of the alive cells (empty if population() == 0).

Definition at line 475 of file tpl_ca_hashlife.H.

References Aleph::blossom_maximum_cardinality_matching(), Aleph::CA::ca_hashlife_detail::Node::level, Aleph::CA::ca_hashlife_detail::Node::population, root_, visit_alive(), and y.

Referenced by TEST(), TEST(), TEST(), and TEST().

◆ cache_capacity()

std::size_t Aleph::CA::Hashlife_Engine::cache_capacity ( ) const
inlinenoexcept

Maximum allowed canonical-node count before the result cache is dropped.

Definition at line 510 of file tpl_ca_hashlife.H.

References cache_capacity_.

◆ center_of_4()

Node * Aleph::CA::Hashlife_Engine::center_of_4 ( Node *  nw,
Node *  ne,
Node *  sw,
Node *  se 
)
inlineprivate

◆ clear()

void Aleph::CA::Hashlife_Engine::clear ( )
inline

Reset the universe to empty (preserves rule, capacity and node cache).

Definition at line 497 of file tpl_ca_hashlife.H.

References empty_node(), generation_, initial_level_, and root_.

Referenced by TEST().

◆ clear_result_cache()

void Aleph::CA::Hashlife_Engine::clear_result_cache ( )
inlineprivate

Definition at line 785 of file tpl_ca_hashlife.H.

References pool_, result_cache_clears_, result_hits_, and result_misses_.

Referenced by advance(), and set_rule().

◆ empty_node()

Node * Aleph::CA::Hashlife_Engine::empty_node ( const std::uint8_t  level)
inlineprivate

◆ evolve()

◆ evolve_level_2()

◆ expand()

◆ for_each_alive()

template<typename F >
void Aleph::CA::Hashlife_Engine::for_each_alive ( F &&  f) const
inline

Iterate over all alive cells, calling f(x, y) for each.

Visits each alive cell exactly once, in unspecified order.

Template Parameters
Fcallable accepting (std::int64_t, std::int64_t).
Parameters
fvisitor.

Definition at line 523 of file tpl_ca_hashlife.H.

References Aleph::blossom_maximum_cardinality_matching(), Aleph::CA::ca_hashlife_detail::Node::level, Aleph::CA::ca_hashlife_detail::Node::population, root_, and visit_alive().

◆ generation()

std::int64_t Aleph::CA::Hashlife_Engine::generation ( ) const
inlinenoexcept

Number of generations elapsed since construction (or the last clear).

Definition at line 469 of file tpl_ca_hashlife.H.

References generation_.

Referenced by TEST(), TEST(), TEST(), TEST(), and TEST().

◆ get_in_node()

static bool Aleph::CA::Hashlife_Engine::get_in_node ( const Node *  n,
const std::int64_t  x,
const std::int64_t  y 
)
inlinestaticprivatenoexcept

Definition at line 984 of file tpl_ca_hashlife.H.

References Aleph::blossom_maximum_cardinality_matching(), get_in_node(), and y.

Referenced by alive_at(), and get_in_node().

◆ horizontal_centered()

Node * Aleph::CA::Hashlife_Engine::horizontal_centered ( Node *  w,
Node *  e 
)
inlineprivate

◆ is_centered_well()

static bool Aleph::CA::Hashlife_Engine::is_centered_well ( const Node *  n)
inlinestaticprivatenoexcept

Standard Hashlife "centered well" predicate: every quadrant of n has its population concentrated in the sub-quadrant closest to the centre.

This guarantees that, after evolve (which advances 2^(L-2) generations and returns only the central area), no alive cell escapes the new root — for any rule whose maximum signal speed is at most c/2 (which holds for every life-like outer-totalistic rule, including Conway's B3/S23).

Definition at line 822 of file tpl_ca_hashlife.H.

References Aleph::blossom_maximum_cardinality_matching().

Referenced by advance().

◆ load_rle()

void Aleph::CA::Hashlife_Engine::load_rle ( std::istream &  in)
inline

Load an RLE pattern from in (centred at the origin).

Parses the standard RLE dialect (# comments, x = W, y = H, rule = R header, b/o/$/! body, run-length prefixes). The rule field is parsed and replaces the engine's current rule when valid.

Parameters
ininput stream positioned at the start of the pattern.

Definition at line 543 of file tpl_ca_hashlife.H.

References Aleph::and, Aleph::blossom_maximum_cardinality_matching(), parse_header_value(), parse_rule_field(), r, rule_, run(), and set_alive().

Referenced by load_rle_string().

◆ load_rle_string()

void Aleph::CA::Hashlife_Engine::load_rle_string ( const std::string &  s)
inline

Convenience overload that reads the pattern from a string.

Definition at line 604 of file tpl_ca_hashlife.H.

References Aleph::blossom_maximum_cardinality_matching(), and load_rle().

Referenced by TEST(), TEST(), and TEST().

◆ make_leaf()

Node * Aleph::CA::Hashlife_Engine::make_leaf ( const std::uint8_t  bits)
inlineprivate

◆ make_node()

◆ parse_header_value()

static std::int64_t Aleph::CA::Hashlife_Engine::parse_header_value ( const std::string &  line,
const char  key 
)
inlinestaticprivate

Definition at line 1023 of file tpl_ca_hashlife.H.

References Aleph::and, and Aleph::blossom_maximum_cardinality_matching().

Referenced by load_rle().

◆ parse_rule_field()

static std::optional< Outer_Totalistic_Binary_Rule > Aleph::CA::Hashlife_Engine::parse_rule_field ( const std::string &  line)
inlinestaticprivate

◆ population()

std::uint64_t Aleph::CA::Hashlife_Engine::population ( ) const
inlinenoexcept

Number of alive cells.

Definition at line 463 of file tpl_ca_hashlife.H.

References Aleph::CA::ca_hashlife_detail::Node::population, and root_.

Referenced by TEST(), TEST(), TEST(), TEST(), TEST(), TEST(), TEST(), TEST(), TEST(), TEST(), TEST(), TEST(), TEST(), and TEST().

◆ rule()

Rule Aleph::CA::Hashlife_Engine::rule ( ) const
inlinenoexcept

Current rule.

Definition at line 368 of file tpl_ca_hashlife.H.

References rule_.

◆ run()

std::uint64_t Aleph::CA::Hashlife_Engine::run ( std::uint64_t  generations)
inline

Advance by exactly generations steps.

Decomposes generations into a sum of powers of two and chains the corresponding advance calls. The actual advance may slightly exceed the request when the pattern outgrows the chosen level.

Parameters
generationstarget step count (0 is a no-op).
Returns
number of generations actually advanced (≥ generations).

Definition at line 447 of file tpl_ca_hashlife.H.

References advance(), Aleph::blossom_maximum_cardinality_matching(), and k.

Referenced by load_rle(), TEST(), TEST(), TEST(), TEST(), TEST(), TEST(), TEST(), TEST(), TEST(), and TEST_P().

◆ save_rle()

void Aleph::CA::Hashlife_Engine::save_rle ( std::ostream &  out,
const std::string &  comment = {} 
) const
inline

Write the alive cells in RLE format.

Emits a single-line header (x = W, y = H, rule = ...) and a run-length-encoded body wrapped at ~70 characters per line.

Parameters
outoutput stream.
commentoptional #C comment line (ignored if empty).

Definition at line 618 of file tpl_ca_hashlife.H.

◆ save_rle_string()

std::string Aleph::CA::Hashlife_Engine::save_rle_string ( const std::string &  comment = {}) const
inline

Convenience overload returning the RLE serialisation as a string.

Definition at line 704 of file tpl_ca_hashlife.H.

Referenced by TEST(), TEST(), and TEST().

◆ set_alive()

void Aleph::CA::Hashlife_Engine::set_alive ( const std::int64_t  x,
const std::int64_t  y,
const bool  alive = true 
)
inline

Set or clear the cell at world coordinates (x, y).

Coordinates are signed 64-bit. The universe automatically expands to contain the requested cell.

Parameters
xcolumn (positive = east).
yrow (positive = south, RLE convention).
alivenew state (default true).

Definition at line 382 of file tpl_ca_hashlife.H.

References Aleph::and, Aleph::blossom_maximum_cardinality_matching(), expand(), Aleph::CA::ca_hashlife_detail::Node::level, root_, set_in_node(), and y.

Referenced by load_rle(), TEST(), TEST(), TEST(), TEST(), and TEST().

◆ set_in_node()

◆ set_rule()

void Aleph::CA::Hashlife_Engine::set_rule ( const Rule &  r)
inline

Replace the rule. Invalidates the result cache.

Definition at line 359 of file tpl_ca_hashlife.H.

References clear_result_cache(), r, and rule_.

Referenced by TEST().

◆ stats()

Stats Aleph::CA::Hashlife_Engine::stats ( ) const
inlinenoexcept

Diagnostic counters and current root level.

Definition at line 504 of file tpl_ca_hashlife.H.

References Aleph::CA::ca_hashlife_detail::Node::level, result_cache_clears_, result_hits_, result_misses_, root_, and table_.

Referenced by TEST(), TEST(), and TEST().

◆ vertical_centered()

Node * Aleph::CA::Hashlife_Engine::vertical_centered ( Node *  n,
Node *  s 
)
inlineprivate

◆ visit_alive()

Member Data Documentation

◆ cache_capacity_

std::size_t Aleph::CA::Hashlife_Engine::cache_capacity_
private

Definition at line 718 of file tpl_ca_hashlife.H.

Referenced by advance(), and cache_capacity().

◆ empty_by_level_

Array<Node *> Aleph::CA::Hashlife_Engine::empty_by_level_
private

Aleph::Array of canonical empties per level.

Definition at line 722 of file tpl_ca_hashlife.H.

Referenced by empty_node().

◆ generation_

std::int64_t Aleph::CA::Hashlife_Engine::generation_ = 0
private

Definition at line 725 of file tpl_ca_hashlife.H.

Referenced by advance(), clear(), and generation().

◆ initial_level_

constexpr std::uint8_t Aleph::CA::Hashlife_Engine::initial_level_ = 3
staticconstexprprivate

8 × 8 starting universe

Definition at line 715 of file tpl_ca_hashlife.H.

Referenced by clear().

◆ pool_

std::deque<Node> Aleph::CA::Hashlife_Engine::pool_
private

Definition at line 720 of file tpl_ca_hashlife.H.

Referenced by clear_result_cache(), make_leaf(), and make_node().

◆ result_cache_clears_

std::size_t Aleph::CA::Hashlife_Engine::result_cache_clears_ = 0
private

Definition at line 729 of file tpl_ca_hashlife.H.

Referenced by clear_result_cache(), and stats().

◆ result_hits_

std::size_t Aleph::CA::Hashlife_Engine::result_hits_ = 0
mutableprivate

Definition at line 727 of file tpl_ca_hashlife.H.

Referenced by clear_result_cache(), evolve(), and stats().

◆ result_misses_

std::size_t Aleph::CA::Hashlife_Engine::result_misses_ = 0
mutableprivate

Definition at line 728 of file tpl_ca_hashlife.H.

Referenced by clear_result_cache(), evolve(), and stats().

◆ root_

Node* Aleph::CA::Hashlife_Engine::root_ = nullptr
private

◆ rule_

Rule Aleph::CA::Hashlife_Engine::rule_
private

Definition at line 717 of file tpl_ca_hashlife.H.

Referenced by evolve_level_2(), load_rle(), rule(), and set_rule().

◆ table_

std::unordered_map<Node_Key, Node *, ca_hashlife_detail::Node_Key_Hash> Aleph::CA::Hashlife_Engine::table_
private

Definition at line 721 of file tpl_ca_hashlife.H.

Referenced by advance(), make_leaf(), make_node(), and stats().


The documentation for this class was generated from the following file: