For contributors — how epistemic execution works internally. This page assumes
you work on the xlog runtime itself. It is dense on purpose; it is not the
user-facing explanation of the epistemic feature.
What this page covers
XLOG can reason about what a program knows and what it holds possible, not just what is plainly true. These are called epistemic (knowledge-level) literals. This page explains how the runtime carries those literals through compilation and GPU execution without losing their meaning. The key design choice: epistemic literals travel through their own explicit intermediate representation, called EIR (the Epistemic Intermediate Representation), before anything else touches them. That wayknow and
possible literals do not quietly collapse into ordinary predicate rewrites
before their semantic mode has been validated.
The accepted paths
Every accepted epistemic program first passes through the same semantic boundary:- parse and normalize source into the frontend AST (abstract syntax tree);
- build EIR from that AST so modal operators and their source spans remain explicit;
- classify ordinary and modal dependencies, validate relation identity and tuple shape, and select an execution route.
- An acyclic modal program builds a single-pass GPU plan and runs Generate-Propagate-Test workspace phases.
- A positive modal dependency cycle uses whichever fixpoint the program’s semantic
mode selects, set by
#pragma epistemic_mode.faeel(the mode’s internal name is FAEEL) is the default and is founded: a fact counts as known only when some rule actually derives it, so a tuple that supports only itself does not survive. Before compilation the reducer drops that unfounded exact-tuple self-support, then computes the least fixpoint — the smallest set of facts every rule supports.g91(Gelfond’s 1991 epistemic-specification semantics) instead admits a self-supporting tuple. For a supported exact-tuplepossiblecycle it computes the greatest set of tuples that stay mutually compatible, descending from a GPU-computed over-approximation.
- A supported cycle through negation reduces to a non-monotone ordinary program and runs through the GPU-backed well-founded semantics (WFS) alternating fixpoint — the standard three-valued treatment of a rule that negates something it depends on, where a fact can be true, false, or undefined.
ordinary_post unit; its cost is
one additional ordinary fixpoint pass per stratified evaluation. The compiler’s
query rules run in that post stage over the final gated relations, so authored
queries keep source order, constants, repeated-variable filters, projection order,
and logical zero-column shape.
Source surface
The frontend represents epistemic constructs explicitly, so the programmer’s intent survives parsing:#pragma epistemic_mode = faeel#pragma epistemic_mode = g91
epistemic_mode, apply only when declared in the entry file; a
declaration in an imported module is ignored with warning[W0510] (see the
pragmas guide).
know atom(...)possible atom(...)not know atom(...)not possible atom(...)
faeel is the default semantic mode for evaluating these literals. g91
selects a compatibility mode matching Gelfond’s 1991 epistemic-specification
semantics.
The EIR boundary
xlog_logic::build_eir converts the parsed AST into the EIR structures defined
in xlog-ir:
EirProgramEirRuleEirBodyLiteralEirEpistemicLiteralEirEpistemicModeEirEpistemicOp
The single-pass GPU plan contract
plan_epistemic_gpu_execution builds the semantic contract that runtime
execution must satisfy for an acyclic modal program. Recursive dependency classes
are intercepted by the high-level dispatcher before this planner. The single-pass
plan does four things:
- it preserves the epistemic literals rather than discarding them;
- it records, for each accepted rule, how that rule is reduced;
- it binds each modal literal (a
knoworpossibleliteral) to the reduced stable-model tuple source it draws from — where stable models are the answer sets a logic program admits; - it declares the typed structural policy
execution_backend=gpuandfallback_policy=reject_unsupported.
The plan and evidence JSON intentionally no longer publish synthetic zero
measurements. The removed keys include
cpu_fallbacks,
cpu_fallbacks_zero, cpu_fallback_is_zero, and
cpu_fallback_total_zero, along with the former semantic and split-batch
cpu_candidate_enumerations, cpu_world_view_validations,
cpu_recomposition_steps, cpu_solver_search_fallbacks, and
cpu_probability_recomputations fields. Production solver/probability traces
and their CLI/PyXLOG exports also dropped cpu_assignment_enumerations,
cpu_maxsat_enumerations, cpu_learned_clause_transfers,
cpu_only_probability_recomputations, and fixture_circuit_evaluations;
those values were default-only zeros rather than observations. Hardcoded
solver/probability no-fallback booleans were removed for the same reason.
WFS summaries likewise omit host_wfs_fallback_allowed; the typed fallback
policy is the structural contract. Specialized CLI evidence also omits
cpu_threshold_only_promotions, the Python/host score-materialization flags,
cpu_template_expansions, and host_materialized_explanation_fallback
because those values were constants rather than observed runtime events.
Consumers should gate acceptance on the typed policy plus observed dispatch,
kernel timing, device-buffer, candidate-accounting, solver/probability event,
and scoped-transfer evidence. The separately selected CPU solver oracle keeps
its real, incremented search counters, remains labeled as fixture-only, and is
not eligible as production GPU evidence.Reduced runtime plans
compile_epistemic_gpu_execution and
compile_epistemic_gpu_execution_with_stats_snapshot strip out the epistemic
literals for the single-pass route, but only after the GPU plan contract already
exists. Positive recursive routes use their recursive reducer instead. FAEEL
produces one ordinary least-fixpoint program. The Gelfond-1991 compatibility
route produces an upper-bound program and a frozen-snapshot refinement program.
All resulting ordinary programs go through the same compiler that deterministic
programs use. A non-monotone pass outside the compatibility component is compiled
into the GPU-backed WFS plan rather than the ordinary semi-naive plan.
That reuse is load-bearing:
- statistics snapshots still feed the compiler;
- helper splitting — breaking a complex rule into smaller helper rules — stays owned by the ordinary optimizer path;
- WCOJ promotion and route gates are shared with deterministic execution. A WCOJ (worst-case-optimal join) computes a multiway pattern directly instead of chaining two-way joins; a route gate is the runtime check that decides whether such a specialized route actually fires.
- reduced positive plans do not get a private epistemic join planner.
Gelfond-1991 tuple compatibility
The compatibility route is selected for a positive, non-invariantpossible
literal when its tuple key exactly matches its rule head and the head and target
belong to one recursive dependency component. Predicate recursion alone is not
treated as tuple support: body filters on different rules may describe disjoint
tuple domains even when the predicates form a strongly connected component.
The route compiles two GPU evaluation passes:
- The upper-bound pass relaxes only the selected compatibility gates. Its result contains every tuple that could survive those gates.
- The refinement pass replaces each selected gate with a read from a collision-free snapshot relation containing the preceding iteration’s tuples. It starts again from the original extensional inputs on every iteration.
#pragma max_recursion_depth bounds refinement
iterations.
Single-pass candidate bounds
The Generate-Propagate-Test route must enumerate the candidate knowledge states it will test. A bounded fixture (a test harness that generates candidates, propagates constraints, then tests them) accepts an explicitmax_candidates
configuration.
Production single-pass planning derives the candidate space from the EIR program
itself. It computes the full candidate lattice (the ordered space of candidate
knowledge states) from the number of epistemic literals. It is not a fixed
literal count or a large hardcoded bound. Models per Generate-Propagate-Test
reduction are capped by the configurable max_models_per_reduction field,
which defaults to DEFAULT_EPISTEMIC_MAX_MODELS_PER_REDUCTION = 1024. FAEEL
founded positive-cycle, Gelfond-1991 tuple-compatibility, and WFS routes do not
enumerate this lattice.
Single-pass workspace phases
The Generate-Propagate-Test workspace uses device (GPU) buffers for:- candidate assumptions;
- world views (a world view is the set of models the program considers possible at once);
- model membership;
- rejection reasons;
- final flags and materialized output tuples where applicable.
possible cycles run through the descending tuple-compatibility fixpoint.
Supported cycles through negation use the GPU-backed well-founded plan.
Split execution
Epistemic splitting groups rules by their modal dependencies and their ordinary derived dependencies. Independent components may be solved separately, but only when splitting preserves the semantics of the unsplit program. Modal predicates that are coupled stay in one component and are solved jointly. For acyclic components, split execution reusescompile_epistemic_gpu_execution_with_stats_snapshot for each executable
component. There is no separate split-only runtime. Recursive programs are
classified before the single-pass split planner.
Boundaries added with the recursive rewrite
The 0.12.0 rewrite that preserved predicate unions and recursive epistemic semantics also closed five shapes that previously compiled. Each now fails closed at compile time with a typedUnsupportedEpistemicConstruct:
The first is the one a program author is most likely to hit: writing two rule
clauses for one epistemic head is ordinary Datalog style, and it is now rejected
rather than silently mis-filtered.
Invariants and diagnostics
Contributors verifying epistemic behavior can rely on these facts:- EIR is built from the AST, not from RIR.
- Dependency classification occurs before single-pass plan construction.
- Positive FAEEL cycles execute through an ordinary founded least-fixpoint reduction, supported exact-tuple Gelfond-1991 possibility cycles use a descending greatest compatibility fixpoint, and supported negative cycles execute through GPU-backed WFS.
- The bounded fixture evaluators (with
max_candidates) are distinct from the production GPU execution path. - Unsupported shapes surface as typed, fail-closed boundaries.
- Preflight metadata (information collected before execution runs) alone is not proof that a WCOJ or solver route fired.
- Runtime claims should be paired with counters, transfer telemetry, or validation evidence.