36#ifndef ALEPH_REPRODUCTIONS_SOURCE_DIR
37# define ALEPH_REPRODUCTIONS_SOURCE_DIR "reproductions"
43using State = std::uint8_t;
46constexpr State empty =
static_cast<State
>(Forest_Cell::EMPTY);
47constexpr State tree =
static_cast<State
>(Forest_Cell::TREE);
48constexpr State burning =
static_cast<State
>(Forest_Cell::BURNING);
69 const double p_growth,
70 const double p_lightning,
71 const std::uint64_t master_seed)
72 : side_(
side), p_growth_(p_growth), p_lightning_(p_lightning),
73 master_seed_(master_seed), current_(
side *
side, empty),
78 for (
ca_size_t column = 0; column < side_; ++column)
80 const std::size_t index =
row * side_ + column;
85 if (dr == 0
and dc == 0)
93 neighbours_[index][
k++] =
r * side_ + c;
104 =
splitmix64(
static_cast<std::uint64_t
>(step_) + 0xa5a5a5a5a5a5a5a5ull);
105 for (std::size_t index = 0; index < current_.size(); ++index)
107 if (current_[index] == burning)
109 next_[index] = empty;
112 if (current_[index] == tree)
116 or draw(index,
step_hash) < p_lightning_ ? burning : tree;
119 next_[index] = draw(index,
step_hash) < p_growth_ ? tree : empty;
121 current_.swap(next_);
128 [[
nodiscard]]
const std::vector<State> &frame()
const noexcept
136 [[
nodiscard]]
const std::vector<Neighbours> &neighbours()
const noexcept
145 std::uint64_t master_seed_;
146 std::size_t step_ = 0;
147 std::vector<State> current_;
148 std::vector<State> next_;
149 std::vector<Neighbours> neighbours_;
150 std::vector<std::uint64_t> coord_hashes_;
160 for (
const std::size_t index : neighbours)
161 if (frame[index] == burning)
171 [[
nodiscard]]
double draw(
const std::size_t index,
172 const std::uint64_t
step_hash)
const noexcept
175 return static_cast<double>(bits >> 11) * (1.0 / 9007199254740992.0);
187 for (
const std::size_t index : neighbours)
188 if (frame[index] == burning)
200 const std::vector<State> &
after,
201 const std::vector<Neighbours> &neighbours,
202 std::vector<std::size_t> &sizes)
204 std::vector<unsigned char>
seen(
before.size(), 0);
205 std::vector<std::size_t> queue;
206 for (std::size_t origin = 0; origin <
before.size(); ++origin)
214 queue.push_back(origin);
216 std::size_t
count = 0;
217 for (std::size_t head = 0; head < queue.size(); ++head)
219 const std::size_t index = queue[head];
221 for (
const std::size_t
next : neighbours[index])
225 queue.push_back(
next);
228 sizes.push_back(
count);
237 const std::vector<std::size_t> &sizes)
239 if (
const auto parent = path.parent_path();
not parent.empty())
240 std::filesystem::create_directories(parent);
241 std::map<std::size_t, std::size_t>
histogram;
242 for (
const std::size_t
size : sizes)
244 std::ofstream
out(path);
246 throw std::runtime_error(
"Cannot write Drossel-Schwabl histogram");
247 out <<
"size,ignitions,cluster_number_weight\n";
250 <<
static_cast<double>(
ignitions) /
static_cast<double>(
size) <<
'\n';
260 std::cerr <<
"Usage: drossel_schwabl [--quick]\n";
266 constexpr double p_growth = 0.005;
267 constexpr double p_lightning = 0.0001;
268 constexpr std::uint64_t
seed = 0xD20551992ull;
274 std::vector<std::size_t> sizes;
281 std::cout <<
"Drossel-Schwabl progress: " << step + 1 <<
'/'
292 std::ofstream
summary(
root /
"results" /
"drossel_schwabl_summary.csv");
295 std::cerr <<
"Cannot write Drossel-Schwabl summary\n";
298 summary <<
"side,warmup_steps,measured_steps,p_growth,p_lightning,fires,slope,r_squared,fit_points\n"
300 << p_growth <<
',' << p_lightning <<
',' << sizes.size() <<
','
301 << std::setprecision(12) << fit.
slope <<
',' << fit.
r_squared <<
','
304 std::cout <<
"Drossel-Schwabl: slope=" << std::fixed << std::setprecision(4)
305 << fit.
slope <<
" r2=" << fit.
r_squared <<
" fires=" << sizes.size() <<
'\n';
310 std::cerr <<
"Drossel-Schwabl fire-size slope outside [-2.2, -1.8]\n";
size_t size_t int32_t * out
Internal helpers shared by the cellular-automata reproductions.
#define ALEPH_REPRODUCTIONS_SOURCE_DIR
__gmp_expr< T, __gmp_binary_expr< __gmp_expr< T, U >, unsigned long int, __gmp_root_function > > root(const __gmp_expr< T, U > &expr, unsigned long int l)
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Linear_Fit fit_log_log_histogram(const std::vector< std::size_t > &samples, const std::size_t min_value, const std::size_t max_value, const std::size_t bins, const double sample_weight_power=0.0)
Fit a power-law exponent from logarithmically binned samples.
std::ptrdiff_t ca_index_t
Signed coordinate component used by lattices and neighborhoods.
constexpr std::uint64_t splitmix64(std::uint64_t x) noexcept
64-bit SplitMix hash.
std::size_t ca_size_t
Unsigned size component used for extents and counts.
auto histogram(const Container &data, size_t num_bins) -> std::vector< std::pair< std::decay_t< decltype(*std::begin(data))>, size_t > >
Compute a histogram of the data.
size_t size(Node *root) noexcept
and
Check uniqueness with explicit hash + equality functors.
void next()
Advance all underlying iterators (bounds-checked).
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Least-squares result for a log-log histogram.
double slope
fitted exponent.
std::size_t points
populated bins included in the fit.
double r_squared
coefficient of determination.
Reproducible stochastic CA rules (Phase 8).