pulsatrix
Loading...
Searching...
No Matches
pulsatrix::datalog::BooleanSemiring Struct Reference

A "Semiring" here is not a base class – it is a compile-time trait shape a type must satisfy to be usable as naive_evaluate_weighted<Semiring>'s template parameter: a nested Value type alias plus four static functions, zero(), one(), add(Value,Value) (⊕), mul(Value,Value) (⊗). There is no virtual interface anywhere in this file. More...

#include <datalog_semiring.hpp>

Public Types

using Value = bool
 

Static Public Member Functions

static constexpr Value zero ()
 
static constexpr Value one ()
 
static constexpr Value add (Value a, Value b)
 
static constexpr Value mul (Value a, Value b)
 

Detailed Description

A "Semiring" here is not a base class – it is a compile-time trait shape a type must satisfy to be usable as naive_evaluate_weighted<Semiring>'s template parameter: a nested Value type alias plus four static functions, zero(), one(), add(Value,Value) (⊕), mul(Value,Value) (⊗). There is no virtual interface anywhere in this file.

Note
Stage 3 design decision 3 (templating mechanism): a compile-time template parameter with a duck-typed trait shape, not a type-erased/virtual interface. Rationale, checked against this codebase's own precedent rather than assumed:
  • The mission's own open-design-question text guessed this would be "closer to how `DeviceBackend` is chosen" – recon of include/pulsatrix/device_backend.hpp shows that guess was backwards: DeviceBackend is an abstract virtual interface, chosen at runtime per-Tensor (DeviceType::Cpu/Cuda/Hip), precisely because a single running program legitimately mixes backends (a Tensor moves between devices via Tensor::to()). A Datalog evaluation's semiring choice has no such runtime-mixing requirement – one naive_evaluate_weighted call always uses exactly one semiring, decided at the call site, never switched mid-evaluation.
  • The actual matching precedent, found by checking include/pulsatrix/selection.hpp (the evolutionary-algorithms family), is a duck-typed template parameter pattern: template <typename Genotype, typename FitnessT, typename RNG> free functions, no C++20 concept (this codebase targets C++17), no shared base class – the compiler enforces the shape at the instantiation call site via ordinary overload resolution/member lookup. Semiring here follows that exact precedent.
  • Templates give zero runtime overhead (every add/mul call is inlined at naive_evaluate_weighted<BooleanSemiring> / <RealSemiring<double>>'s own call site, no vtable indirection per fixpoint-round arithmetic operation, which matters since these run inside the evaluator's innermost loop), and they make "the boolean semiring is the trivial case, not special-cased engine logic" (campaign doc's own phrasing) literally true: naive_evaluate_weighted's body contains no if constexpr/if (is_boolean) branch anywhere – BooleanSemiring and RealSemiring<double> are two ordinary instantiations of one generic algorithm.

The boolean semiring: ⊕ = OR, ⊗ = AND, zero = false, one = true.

Note
This is Mission 0's implicit boolean-only engine semantics, now made an explicit, swappable instantiation rather than hardcoded evaluator logic (the mission's own framing: "boolean semiring re-expressed as the trivial case").

Member Typedef Documentation

◆ Value

Member Function Documentation

◆ add()

static constexpr Value pulsatrix::datalog::BooleanSemiring::add ( Value  a,
Value  b 
)
inlinestaticconstexpr

◆ mul()

static constexpr Value pulsatrix::datalog::BooleanSemiring::mul ( Value  a,
Value  b 
)
inlinestaticconstexpr

◆ one()

static constexpr Value pulsatrix::datalog::BooleanSemiring::one ( )
inlinestaticconstexpr

◆ zero()

static constexpr Value pulsatrix::datalog::BooleanSemiring::zero ( )
inlinestaticconstexpr

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