Scope and release context
This reference describes XLOG’s implemented language surface. It has three layers:- The core language — facts, rules, recursion, deterministic negation, aggregation, and arithmetic.
- The language-completeness contract — finite terms and lists, safe meta-predicates, deterministic negation, magic sets, probabilistic aggregates, approximate inference, and CLI inspectability.
- The epistemic surface — the modal operators
know,possible,not know, andnot possible, plus#pragma epistemic_mode = faeel|g91. “Modal” here means the operator talks about the models (the possible “worlds”) a program admits, not about a single fact.
know/possible
programs — and run through the high-level xlog run GPU epistemic runtime. An
unsupported epistemic form must fail with a typed diagnostic rather than
silently falling back to CPU evaluation.
Within the epistemic surface, the executor is complete for:
- enumerating candidate worlds from the EIR;
- checking modal membership at the value level, one tuple key at a time;
- FAEEL foundedness per tuple key — FAEEL is XLOG’s default epistemic semantics, and a tuple is “founded” when it has a non-circular justification;
- ground epistemic constraints, safe splitting of independent components, and solving several epistemic components jointly.
- global and per-row modal gates, which combine with logical AND;
- finite nested modal chains (such as
know possible fact()), which normalize to a single operator by parity/duality; - predicates that share a name but differ in arity, told apart by their arity-qualified tuple sources;
- recursion — covering determined stratification (ordered evaluation after a
modal target is materialized), positive FAEEL dependency cycles through an
ordinary founded least fixpoint, supported positive exact-tuple Gelfond-1991
possiblecycles through a greatest compatibility fixpoint, stratified negated modals, and cyclic negated modals. Supported cycles through negation use thexlog-gpuGPU-backed Well-Founded Semantics (WFS) plan — a fixpoint that assigns each atom true, false, or undefined — which replaces the olderxlog_probhost-side WFS solver. A positive compatibility component does not itself use WFS, although an unrelated nonmonotone component may use WFS within the same upper-bound or refinement pass.
Table of Contents
- Overview
- Basic Syntax
- Data Types
- Language Completeness Contract
- Predicates and Declarations
- Facts
- Rules
- Queries
- Constraints
- Variables and Wildcards
- Comparisons
- Arithmetic Expressions
- Negation
- Aggregations
- Lists
- Safe Meta-Predicates
- Magic Sets
- User-Defined Functions
- Modules
- Symbols
- Probabilistic Logic
- Epistemic Logic
- Approximate Inference
- Neural Predicates
- Learnable Rules
- Term Embeddings
- GPU ILP Configuration
- Pragmas and Directives
- CLI Developer Experience
- Float Predicates and IEEE 754 Semantics
- Comments
- Complete Grammar Reference
Overview
XLOG is a GPU-native logic programming language that compiles typed, modular logic programs into backend-specific GPU execution paths. It supports:- Datalog fundamentals: Facts, rules, recursive queries, and stratified negation
- Arithmetic operations: Comparisons, computed values via
is, and built-in functions - Aggregations:
count,sum,min,max, andlogsumexp - Probabilistic reasoning: Probabilistic facts, annotated disjunctions, evidence, and queries
- Epistemic reasoning:
know/possiblemodal body literals, FAEEL default semantics, and Gelfond 1991 compatibility mode through explicit EIR/GPU execution paths - Language-completeness contract: Finite lists, safe meta-predicates, explicit negation contracts, magic-set planning, probabilistic aggregate semantics, approximate inference configuration, incremental parsing, and CLI inspectability
- GPU execution: All core operations (joins, sorts, aggregations) run on the GPU
Hello World Example
Basic Syntax
Program Structure
An XLOG program consists of a sequence of statements. Each statement ends with a period (.).
Statement Types
Identifiers
- Predicates and atoms: Start with a lowercase letter, followed by alphanumerics or underscores (
edge,reach_from,node2) - Variables: Start with an uppercase letter, followed by alphanumerics or underscores (
X,Node,Value1) - Anonymous variable: A single underscore (
_) matches any value without binding
Data Types
XLOG supports the following scalar types:Literals
Type Inference
Predicate declarations set column types explicitly. Without a declaration, compilation infers a schema from available facts and rule information. When different source programs—either the entry program and a selected import, or two selected imports—contribute clauses for the same undeclared predicate name and arity, module resolution compares inferred head-column types before merging them. Head constants, head variables typed by ordinary body atoms or built-in arithmetic bindings, and aggregate result types supply evidence, including through rule chains; unanchored variables do not. Conflicts produceerror[E0412]. Invalid
built-in arithmetic or aggregate evidence produces error[E0413] with its source module and
file; user-defined function calls are expanded after imports merge and validated during
compilation.
pred declaration makes the expected schema stable and visible at the
source boundary. Without one, compilation infers the predicate schema from the
available program evidence and still rejects conflicting type flows.
Language-Completeness Type Forms
The language-completeness contract extends the type model with finite language-level terms that must lower to typed relation layouts before execution:
Unsupported type forms must fail during parsing or semantic analysis before
runtime execution starts.
Language Completeness Contract
The language-completeness contract is a language-surface expansion over the core runtime. New syntax is accepted only when it has a typed normalization and lowering path for every execution route that supports it. Deterministic programs flow through RIR (XLOG’s internal relational intermediate representation), the optimizer, and runtime; probabilistic and epistemic constructs use their own typed IR and execution routes. CLI commands report the route that was actually analyzed rather than implying that every construct traverses every subsystem.Execution Responsibilities
Accepted language-completeness and epistemic features must not execute by constructing
an arbitrary CPU Prolog term heap, running dynamic CPU predicate calls, or
using a hidden CPU-only fallback for a GPU-claimed path.
Feature Coverage Matrix
Diagnostic Contract
Unsupported language-completeness and epistemic forms must report:- the feature area, such as
list,meta,naf,magic_sets,prob_aggregate, orepistemic; - the source span when available;
- the reason the form is unsafe, unbounded, or not GPU-lowerable;
- a remediation, such as adding a positive binder, a finite cap, or a static predicate reference.
Epistemic support and boundaries
The source language accepts the epistemic literals and theepistemic_mode
pragma listed here, and routes accepted epistemic examples through xlog run.
The epistemic executor supports:
- candidate enumeration derived from the EIR;
- value-level modal membership;
- per-tuple-key FAEEL foundedness;
- ground and variable-keyed epistemic integrity constraints;
- safe-split equivalence;
- same-name, multi-arity disambiguation;
- finite nested-chain normalization;
- determined-head stratification;
- positive FAEEL modal dependency cycles through founded least-fixpoint reduction;
- supported positive exact-tuple Gelfond-1991
possiblecycles through a greatest compatibility fixpoint; - stratified negated-modal recursion;
- cyclic negated-modal recursion through the
xlog-gpuGPU-backed WFS plan, which replaces the oldxlog_probhost-side WFS solver.
- direct raw RIR lowering;
- genuinely unbounded or untyped modal tuple keys;
- unsafe unbound negated epistemic variables;
- CPU-only world-view scans;
- cyclic WFS shapes outside the
xlog-gpuGPU-backed negated-modal WFS plan; - recursive epistemic programs that also carry modal integrity constraints;
- Gelfond-1991 compatibility components with recursive negation or aggregation;
- one derived epistemic predicate name authored at multiple source arities (pure extensional predicates may still share a name across arities);
- sibling clauses for an augmented epistemic head that lower to different hidden tuple shapes;
- queries over an augmented epistemic head whose arguments are not a tuple of distinct named variables; and
- single-pass clause unions whose modal conjunctions differ and are not proven redundant for every row of the combined relation.
Predicates and Declarations
Predicate Declarations
Predicate declarations specify the name and column types:Visibility
By default, predicates are public and can be imported by other modules. Useprivate to hide internal predicates:
error[E0406].
Domain Declarations
Domain declarations provide semantic naming for types:Facts
Facts are ground atoms (no variables) that assert tuples exist in a relation:Numeric Facts
Rules
Rules derive new facts from existing ones. A rule has a head (the derived fact) and a body (the conditions).Simple Rules
Recursive Rules
Recursive rules derive facts that depend on themselves:Multi-Atom Bodies
Rules can have multiple atoms in the body, which are implicitly joined:Variable Binding
Variables are bound by appearing in positive atoms. The same variable name in different atoms creates a join condition:Queries
Queries specify which relations to output. Use?- followed by an atom pattern:
Constraints
Constraints assert that a condition must have no solutions. If any tuples satisfy the constraint body, execution fails:Variables and Wildcards
Named Variables
Variables start with an uppercase letter and are bound to values when matched:Anonymous Wildcard
The underscore (_) matches any value without binding. Multiple underscores in a rule are independent:
Comparisons
XLOG supports comparison operators in rule bodies:Examples
Explicit Equality
Use= to explicitly compare variables (in addition to implicit join):
Arithmetic Expressions
XLOG uses theis keyword for arithmetic computations. The left-hand side must be a fresh (unbound) variable.
Basic Syntax
Operators
Built-in Functions
Examples
Type Casting
Type casting is explicit in XLOG. Usecast(expr, type):
Division and Error Handling
To avoid division by zero errors, filter explicitly:
Negation
XLOG supports deterministic negation as failure using thenot keyword.
In deterministic programs, not atom(...) is closed-world, stratified
negation. This is distinct from probabilistic nonmonotone negation, where exact
inference may use Well-Founded Semantics (WFS) for accepted probabilistic
programs.
Syntax
Examples
Stratification Requirements
Negation must be stratifiable: there cannot be a cycle where a predicate depends on its own negation. Valid (stratifiable):negation safety error. Low-level stratification analysis still reports the
underlying dependency cycle for callers that use it directly.
Domain Safety
Named variables in negated atoms must be bound by a prior source-order binder in the same rule body. Positive atoms bind their named variables, and a deterministicis expression binds its target after the expression appears.
Source order matters: a later positive atom does not make an earlier negated
atom safe. Use _ for existential positions inside negated atoms.
Aggregations
Aggregations compute summary values over groups of tuples.Supported Aggregates
Syntax
Aggregates appear in the rule head. Variables not in the aggregate form the grouping key:Examples
Multi-Key Aggregation
Multiple Aggregates
Computing Averages
XLOG does not have a built-inavg aggregate. Compute it using sum and count:
Log-Sum-Exp Aggregation
For probabilistic and numerical applications,logsumexp computes log(sum(exp(values))) in a numerically stable way:
Lists
The language-completeness contract defines finite list syntax and list built-ins. Lists are accepted only when they are finite and typed; accepted programs lower to relation layouts and normal GPU-capable execution paths. Current finite-list implementation status: scalar, symbol, nested finite list, and finite meta term IDs are normalized tou64 list identifiers plus
__xlog_list_* helper relations. list<T> predicate columns lower to scalar
list-id columns while helper relations carry length, item, cons, append, sort,
msort, and set facts. The current implementation accepts finite literals,
declared list<T> columns, safe [Head | Tail] patterns in declared list
columns, and the built-ins below when their list argument has a finite literal
or a known list<T> type.
Syntax
Built-Ins
Pair helpers may be added as typed helpers when they lower to finite relation
columns. Unsupported helpers must be rejected with a typed diagnostic rather
than simulated by a CPU term evaluator.
Current implementation limits:
append(A, B, C)accepts finite first and second list literals; split generation such asappend(A, B, [1,2,3])is rejected as unbounded;sort,msort, andlist_to_setrequire a finite input literal;term,compound, andpredreflist elements lower to finiteu64meta term IDs when they appear in declaredlist<term>,list<compound>, orlist<predref>contexts.
Examples
Unsupported Forms
The following forms are outside the finite-list contract:- unbounded list generation, such as asking
append(A, B, [1,2,3])to enumerate every split unless a finite split mode is explicitly implemented; - cyclic lists;
- heterogeneous lists unless represented through a declared finite
termdomain; - list evaluation that requires an arbitrary CPU Prolog term heap.
Safe Meta-Predicates
Safe meta-predicates provide finite term inspection and static predicate mapping. They do not introduce an unrestricted Prolog dynamic database or unrestrictedcall/N.
Current safe-meta implementation status: accepted safe meta forms normalize
before stratification and lowering into ordinary helper relations such as
__xlog_meta_functor, __xlog_meta_univ, __xlog_meta_findall_*, and
__xlog_meta_maplist_*. Finite term, compound, and predref predicate
columns lower to u64 term IDs; compound metadata and univ parts are stored in
typed helper relations. findall and maplist currently accept finite source
facts and finite list literals only; derived-goal collection and non-literal
maplist inputs are explicitly rejected. Use head aggregates such as count and
sum to fold data that rules produce.
Supported Meta-Predicates
Examples
Unsupported Forms
- runtime-variable predicate names in
maplistor any future call-like form; assert,retract, dynamic database mutation, or IO predicates;findallover derived goals or goals with variables that are neither bound beforefindallnor collected by the template;- non-literal
maplistinputs in the current safe-meta subset; - constructing recursive or open compound terms with
=..; - higher-arity
maplistunless explicitly implemented and tested.
Magic Sets
Magic-set rewriting specializes bound deterministic recursive queries by adding derived magic predicates and adorned rules before optimization. The accepted accepted magic-set subset is a source-level rewrite over positive recursive rules that can be proven query-equivalent under the supported left-to-right SIPS (sideways-information-passing strategy — the order in which bound argument values flow through a rule).Configuration
auto lets the compiler apply the rewrite only when it can prove that the
transformed program preserves query output. on requests the rewrite and fails
with a typed magic_sets error if the compiler cannot safely apply it.
off disables the rewrite.
Example
1 may seed a magic predicate so recursive evaluation
does not materialize unreachable source components. xlog explain must show
the adornment, generated magic predicates, and any declined-rewrite reason.
The compiler currently emits helper predicates such as
__xlog_magic_reach_bf, where b marks a bound argument and f marks a free
argument. Accepted rules continue through the normal AST, stratification,
lowering, optimizer, WCOJ, and runtime paths.
Supported Subset
- deterministic programs with
?-queries over recursive predicates; - at least one scalar constant in the queried recursive atom;
- positive recursive rules over the same head predicate;
- source-order binding propagation through prior positive body atoms;
auto,on, andoffsource pragmas.
Declined Forms
auto leaves the program unchanged and records a decline reason. on fails
with a typed diagnostic for:
- unbound recursive calls under the supported SIPS;
- rules with negation, aggregation, comparison,
is, or unnormalized univ in the recursive target; - recursive rules that cross language-completeness list/meta helper predicates;
- mutual-recursive SCCs in the current subset;
- probabilistic profiles, which remain governed by the probabilistic engine.
Unsupported Forms
Magic-set rewriting must decline or fail before execution when negation, aggregates, list/meta constructs, or probabilistic rules would make equivalence uncertain. It must not create a runtime side engine.User-Defined Functions
XLOG supports user-defined functions for reusable arithmetic and relational lookups.Basic Functions
Conditional Functions
Useif-then-else for conditional logic:
Predicate-bodied functions
A predicate-bodied function derives its result through a relational body:is expressions in ordinary rules and
constraints. The relational literals are inserted immediately before the source is
binding. Multiple calls within one expression are inserted from left to right. Each
invocation receives fresh names for its non-parameter result and body-local variables,
and nested calls are expanded recursively up to #pragma max_recursion_depth.
The relational body may match zero, one, or many rows. Each match contributes a caller
row; predicate-bodied function syntax does not enforce a unique scalar result. Ordinary
set semantics deduplicates identical projected caller tuples even when multiple body
witnesses derive them.
When a parameter is used in a predicate-body term position, its argument must be a
variable or numeric literal. Materialize a compound arithmetic expression with an
earlier is binding before passing it. Predicate-bodied calls in conditional result
branches are rejected because their relational literals cannot be hoisted without
changing guarded semantics.
Recursive definitions
Production compilation registers function declarations in source order and expands only definitions reachable from ordinary rule or constraint calls. It rejects duplicate function declarations, but unused definitions with recursion, undefined callees, or a predicate-name conflict do not block this demand-driven path. Expansion is eager across both conditional branches rather than data-dependent. If it tries to enter another user-defined call while already at the depth configured by#pragma max_recursion_depth, it reports error[E0504]. A reachable cyclic call chain
therefore reaches E0504 whether it is wholly unguarded or contains a conditional branch
that looks like a base case. Function recursion is not a runtime looping construct.
The Rust library also exposes strict whole-program validation through
FunctionRegistry::from_program. It visits every definition in declaration order and
callees in source order. A recursive strongly connected component (SCC) with no
conditional-bodied member is rejected with error[E0502]; a conditional-bodied member
lets the SCC pass that structural check. Because later expansion still visits both
branches, a used guarded SCC can pass strict validation and then reach E0504.
Using Functions in Rules
Functions are called on the right side of anis expression:
Type Annotations
Optional parameter and return annotations are parsed and preserved as function metadata:Private Functions
Functions can be marked private and used by other definitions in the same entry file:Modules
XLOG supports organizing code into modules for reusability and encapsulation.Creating Modules
Imported modules are.xlog files, and the filename without its extension becomes the
module name. The entry file is loaded from the exact path supplied to the CLI and may use
another extension:
Importing Modules
Use theuse statement to import public deterministic definitions from modules:
Module Paths
Module paths use/ as the separator:
use in the entry file first resolves relative to the entry path’s directory. A nested
use first resolves relative to the importing module’s canonical source directory, then
through the configured module search paths. Resolution follows those importer-specific
edges throughout validation and merging. Distinct files are not conflated merely because
their imports use the same spelling, and aliases of one canonical source file do not
duplicate its definitions.
Public facts and rules for the same predicate are merged across resolved import branches
into one relation. The same union semantics apply when selective imports name that
predicate in multiple modules. Participating declarations are checked under
error[E0408]. Without a participating declaration, inferred clause-head column types from
different source programs—either the entry program and a selected import, or two selected
imports—are compared by predicate name and arity. Constants, head variables typed by ordinary
body atoms or built-in arithmetic bindings, and aggregate result types supply evidence;
unanchored variables do not. Conflicting types for one signature produce error[E0412]. For
invalid built-in arithmetic or aggregate evidence, resolution reports error[E0413] with the
contributing module and source file. User-defined function calls are expanded after import
resolution. For import schema validation, different arities remain distinct. Functions have one body:
separate branches cannot
define the same imported function, and a module or entry file cannot redefine an imported
function. Those function conflicts produce error[E0402]. An imported module that defines
an exported function name more than once is rejected with error[E0410].
Every declaration in the entry program and every public declaration selected by the
resolved imports participates in declaration compatibility checking. Participating
declarations for one predicate must have identical arity, column names, and resolved
types; otherwise resolution reports error[E0408]. Private declarations in imported
modules and public declarations omitted by a selective import are not merged and do not
participate in that comparison.
Domain-backed types are compared using the scalar type to which each local alias resolves.
Reusing one domain alias name for different scalar types in the entry program or import
closure is error[E0409].
Within an imported module, every declaration of one predicate must use the same visibility;
mixing public and private declarations is rejected with error[E0411].
Visibility and Encapsulation
Predicates and functions are public by default. Useprivate to hide implementation details:
use fails with
error[E0404]; it does not make the predicate visible to the importing program.
An exported rule or function that depends on a private item, or on a public item omitted
by a selective import, is rejected with error[E0406]. Include every public dependency
in a selective import.
Imports merge public deterministic predicates, functions, facts, and rules, together
with domain aliases. Probabilistic facts, annotated disjunctions, evidence, integrity
constraints, neural predicate declarations, and learnable rule templates belong in the
entry file; an imported module containing one is rejected with error[E0405]. Queries,
probabilistic queries, and pragmas are entry-file-scoped. Imported queries are not merged,
and imported pragmas are ignored with warning[W0510].
Symbols
Symbols are interned strings, represented internally as integers for efficient comparison and storage.Declaring Symbol Types
Symbol Literals
Symbol literals are written as identifiers (lowercase) or as string literals:Querying Symbols
Symbols are displayed as their original string values in query output:Symbol Comparison
Symbols can be compared for equality:Reversible Symbols
Symbols are reversible: the original string value is preserved and displayed in query output. Symbols are stored internally asu32 IDs with a
bidirectional mapping to strings.
Probabilistic Logic
XLOG supports probabilistic Datalog for reasoning under uncertainty.Probabilistic Facts
Probabilistic facts are Bernoulli random variables with a specified probability:Annotated Disjunctions
Annotated disjunctions represent categorical distributions (mutually exclusive outcomes):Deterministic Rules with Probabilistic Facts
Rules can derive facts from probabilistic facts:is in probabilistic rules must be representable by
the probabilistic tuple value model. In particular, a u64 result greater than
i64::MAX is rejected with a range error before it can be used by another
literal or emitted in a derived tuple. Deterministic execution continues to use
the full declared u64 range.
Evidence
Evidence constrains the probabilistic model to worlds consistent with observations:Probabilistic Queries
Usequery to compute the probability of an atom:
Complete Probabilistic Example
Inference Engines
XLOG supports two inference engines:
Exact inference supports:
- Stratified deterministic negation: Automatic layer detection and
two-valued evaluation for deterministic
not atomprograms - Probabilistic non-monotone negation: Well-Founded Semantics (WFS) for accepted cyclic probabilistic programs
- Finite probabilistic aggregates:
count,sum,min,max, andlogsumexpaggregate outputs compiled through provenance/PIR when the exact finite domain cap is respected - Gradients: Correct gradient flow through negated literals
count, sum, min, max,
and logsumexp aggregate programs are supported for exact and MC inference in
the finite probabilistic-aggregate subset. Exact mode enumerates finite aggregate
outcomes into provenance/PIR formulas, so query and evidence may reference
aggregate output tuples. Exact enumeration is capped per group by the operators
in the head: a head whose aggregate expressions are all count accepts up to 64
uncertain contributing rows per group, while sum, min, max, and logsumexp
accept up to 16. Cap excess fails with a typed
prob_aggregate error that recommends MC or reducing the finite domain.
Monte Carlo supports probabilistic rules and non-monotone recursion.
The production MC path is the GPU-resident megakernel engine, which rejects
negation, aggregates, and other unbounded constructs with a typed
ResidentRejection. Programs in that fragment (including non-monotone
recursion and language-completeness probabilistic aggregates under MC) require an explicit
opt-in to the labeled CPU oracle — --allow-cpu-oracle on the CLI,
allow_cpu_oracle=True in Python, McEvalConfig::allow_cpu_oracle_fallback
in Rust — and their results carry mc_engine = "cpu-oracle". Without the
opt-in, such programs fail closed with the typed rejection (corrected
2026-06-10; previously this fallback was silent and unlabeled):
Probabilistic Aggregates
Finite probabilistic aggregate programs may query or condition on aggregate outputs:count(..., 0) tuples. MC mode samples worlds on the GPU and
executes the shared deterministic aggregate path for each accepted sample batch.
Aggregate Lifting
Small-domain aggregate lifting is permitted only when the lifted computation is semantically identical to finite exact enumeration. For each successful lift, explain output reports the detected finite domain, cap, operator, andfired
status. Unsupported operators and type, domain, or cap violations return typed
compilation errors instead of aggregate-lifting report entries.
In the aggregate-lifting subset, finite probabilistic count aggregate heads use
exact cardinality dynamic programming when every aggregate expression in the
head is count(...). The lift constructs formulas for exactly k contributing
rows over the same row-presence formulas used by finite enumeration, so it does
not change exact semantics. The count lift accepts up to 64 uncertain rows per
group; larger count domains fail closed with a typed agg_lift error.
sum, min, max, and logsumexp use factorized aggregate-state dynamic
programming with a cap of 16 uncertain rows per group. Successful count and
numeric lifts both report fired. xlog explain --format json emits an
aggregate_lifting array containing the predicate, group key, operator,
finite-domain source, domain size, cap, status, reason, naive outcome count, and
dynamic-programming state count for those successful lifts.
Monte Carlo Sampling Methods
The Monte Carlo engine supports two sampling methods:
Evidence clamping avoids wasted samples when rejection acceptance rates are
low. If evidence is derived, deterministic, or otherwise not directly
forceable, XLOG falls back to rejection sampling.
Negation in Probabilistic Programs
Probabilistic exact inference supports both stratified probabilistic negation and accepted non-monotone WFS profiles:Probabilistic Recursion
Probabilistic facts can be used with recursive rules:Pragma for Engine Selection
The inference engine can be specified in the source file:Epistemic Logic
Epistemic logic is part of the accepted source surface. Epistemic logic adds modal body literals for bounded knowledge and possibility reasoning. Modal literals are valid in rule bodies and use the same atom syntax as ordinary predicates.Modal Literals
Finite nested modal chains such as
know possible fact(),
not know possible fact(), and know not possible fact() are accepted program
forms. The parser normalizes them to a single epistemic literal by the semantic
parity/duality rules: the operator adjacent to the atom determines the modal
operator, while leading/interior/atom-adjacent not tokens dualize or negate
the resulting literal according to their position.
Epistemic Mode Pragma
faeel is the default epistemic mode when no pragma is present. g91 is an
explicit compatibility mode for programs that need Gelfond 1991 possibility behavior.
Runtime Boundary
Accepted epistemic programs enter EIR throughxlog_logic::build_eir and run
through the high-level xlog run / xlog_gpu::LogicProgram dispatch path. That
path classifies dependencies before selecting a single-pass epistemic GPU plan,
an ordinary FAEEL founded least-fixpoint reduction, a Gelfond-1991 positive
exact-tuple possible greatest compatibility fixpoint, or a GPU-backed WFS
alternating-fixpoint plan. Direct ordinary RIR lowering of raw epistemic body
literals remains a rejection boundary and must report
UnsupportedEpistemicConstruct.
The Gelfond-1991 compatibility plan relaxes the selected gates once to compute a
GPU upper bound. It then reevaluates the program from its extensional inputs,
reading each selected modal target from a frozen copy of the preceding
iteration. GPU set comparison over the intensional relations detects the
greatest compatible tuple fixpoint. This is a tuple-level contract: a positive
non-invariant possible literal qualifies when its key exactly matches its rule
head and its head and target share a recursive dependency component. Predicate
recursion without compatible concrete tuples is not sufficient. Ordinary
integrity constraints are evaluated after tuple convergence. When a pass uses
WFS, a positive constraint atom is true only in the lower extension, while a
negated atom is true only when its tuple is absent from the upper extension; an
undefined atom satisfies neither polarity. Modal integrity constraints in a
recursive epistemic program remain unsupported. An unrelated negative cycle may
use GPU-backed WFS inside a pass; recursive negation or aggregation within the
compatibility component is unsupported because the descending operator would be
non-monotone.
Single-pass epistemic output materialization does not retain the defining
clause that supplied each row. One active clause per predicate signature is
always unambiguous. Multiple clauses are also accepted when their normalized
modal conjunctions are identical relative to the output columns, because the
shared filter distributes over the clause union. For an invariant modal target,
know and possible normalize to the same fixed-extension test.
A single epistemic clause may coexist with ordinary sibling clauses when each
of its positive modal gates is proven to be a no-op for every union row. This
includes ground atoms derived from explicit ordinary facts or rules, bijective
all-variable exact-head tuples with independent founded support, and positive
exact-head possible self-support in G91 compatibility mode. Repeated-variable,
constant, or wildcard heads do not qualify as bijective tuple keys.
Other mixed or differently filtered clause unions are rejected with
epistemic rule-union materialization; applying every clause’s modal gate to
the combined relation would otherwise lose valid sibling rows. Admissible
recursive epistemic programs are not subject to this single-pass restriction.
FAEEL positive-cycle literals resolve into ordinary rule bodies before
least-fixpoint execution. Selected Gelfond-1991 gates instead become reads from
frozen relation snapshots during descending refinement.
Examples
FAEEL default knowledge:Approximate Inference
Approximate inference is the source and CLI contract for Monte Carlo probabilistic reasoning. It must be reproducible under a fixed seed and must report uncertainty, sample counts, evidence handling, and sampling method.Source Pragmas
CLI flags override source pragmas when both are provided; the effective
configuration must be visible in CLI output and explain JSON.
In the approximate-inference subset,
xlog prob uses source #pragma prob_engine = mc
when --prob-engine is not supplied. CLI flags override source pragmas
field-by-field: --samples, --seed, --confidence, --prob-method, and
--prob-max-nonmonotone-iterations replace only their matching source values.
--output json emits a machine-readable MC report with the same probability,
standard-error, confidence-interval, sample-count, evidence-count, seed,
confidence, and sampling-method fields as the pretty/csv batch output.
Output Contract
Approximate output formats must include:- probability estimate;
- standard error;
- confidence interval low/high;
- sample count;
- evidence count or acceptance/clamping count;
- seed and method.
Neural Predicates
Neural predicate declarations embed a neural network directly into an XLOG program as a first-class predicate.Declaration Forms
Classification (nn/4):
nn/3):
Arguments
Lowering
Fornn/4, the network output is treated as a label distribution and lowered
to probabilistic facts that enter the inference pipeline. For nn/3, the
network output is a dense tensor bound into the program and used through the
embedding APIs.
Example: MNIST Classification
Example: Embedding Mode
Cross-Registration Validation
Classification declarations (nn/4) require register_network(). Embedding
declarations (nn/3) require register_embedding(). Reusing the same name
across both forms is rejected.
Learnable Rules
Learnable rules are the source-level surface for differentiable ILP. A rule is gated by a named mask tensor:Training API
Multiple Learnable Rules
Cross-References
Term Embeddings
Term embeddings associate dense vectors with discrete logic terms.register_embedding()
forward_embedding()
nn.Embedding, gradients remain attached; for frozen tensors they do
not.
Current scope: explicit training-side embedding registration and batched
lookup are supported. Rule-level embedding inference remains deferred.
GPU ILP Configuration
The GPU-resident ILP path exposes runtime configuration and telemetry through Python.coo_chunk_budget
Controls the per-chunk temporary allocation ceiling used during sparse COO
construction on GPU:
coo_memory_cap naming is deprecated.
host_transfer_stats()
Training APIs expose transfer telemetry so strict zero device-to-host workflows can verify
that the hot path stayed device-resident:
Pragmas and Directives
Pragmas configure compiler and runtime behavior. The current source grammar acceptsprob_engine, prob_cache,
epistemic_mode, max_recursion_depth, magic_sets, and the MC configuration
pragmas below. The epistemic_mode pragma is accepted for the epistemic solver
surface.
Syntax
Scoping
Pragmas are entry-file-scoped: only directives in the file passed toxlog run,
xlog prob, or xlog explain configure the engine. A pragma declared in an imported module
is dropped at merge time and reported with warning[W0510]. See
Pragmas apply only in the entry file.
Available Pragmas
Examples
CLI Developer Experience
Developer-experience commands make the language inspectable and interactive without changing the runtime execution contract.xlog explain
Incremental Parsing
xlog_logic::ParserSession is the shared parser cache for explain, REPL, and
watch workflows. It splits .xlog source into statement units, records stable
text hashes and byte/line spans, and reparses only changed statements through
the production parser. Cache statistics report hits, misses, invalidations,
module invalidations, statement count, and an estimated statement-unit speedup.
Module invalidation removes the changed module and cached sources that import
that module name. Incremental parse diagnostics include the original
line/column and byte span before forwarding the underlying parser error.
xlog repl
xlog watch
--explain also builds a fresh explain report. Explain
passes resolve sibling imports and imports from --module-path again after each
re-read. --once runs one pass and exits, and --debounce-ms controls the interval
between repeated passes.
Unsupported REPL/watch mutation semantics, such as dynamic assert or
retract, remain outside the language.
Float Predicates and IEEE 754 Semantics
XLOG uses hybrid semantics for floating-point comparisons to handle special values (NaN, Infinity, signed zero) correctly.Comparison Semantics
Total Ordering
For ordering comparisons, XLOG uses a total ordering consistent with Rust’sf64::total_cmp:
- NaN values are at the extremes (negative NaN is smallest, positive NaN is largest)
-0.0and+0.0are distinguishable in ordering (unlike IEEE equality)- All values are comparable (no undefined ordering)
Filtering NaN Values
SinceNaN != NaN under IEEE 754, use equality to filter out NaN:
Detecting Special Values
Use ordering to detect special values:Example: Data Cleaning Pipeline
Comments
XLOG supports single-line comments:/* ... */) are not supported.
Complete Grammar Reference
The following is a summary of the current XLOG grammar plus the language-completeness extensions and epistemic source surface in PEG-style notation.Lexical Elements
Types
Terms and Atoms
Expressions
Aggregates
Rules and Facts
Probabilistic Constructs
Declarations
Modules
Pragmas
CLI Examples
Program Structure
See Also
- Architecture Guide - System design and implementation details
- Language Completeness Architecture Contract - Parser, term, probability, CLI, and epistemic/solver handoff contract
- Epistemic Semantics And EIR - Epistemic source surface, EIR boundary, and GPU runtime path
- Arithmetic Expressions - Detailed
issyntax documentation - Probabilistic Tier - Exact and Monte Carlo inference
- GPU Execution - GPU-resident evaluation details
- CLI Reference - Command-line interface documentation
- Examples - Annotated example programs