2026-04-09 12:45:34 +02:00
WIP
2026-04-08 09:04:29 +02:00
WIP
2026-03-11 10:37:22 +01:00
2026-03-13 10:07:30 +01:00
2026-03-09 11:12:18 +01:00
2026-03-09 10:42:31 +01:00
2026-04-09 12:45:34 +02:00
2026-03-09 11:12:18 +01:00
2026-03-09 17:42:33 +01:00
2026-03-09 13:20:46 +01:00
2026-03-09 13:20:46 +01:00
2026-03-09 10:42:31 +01:00
2026-03-10 12:41:33 +01:00
2026-03-09 10:42:31 +01:00
WIP
2026-03-16 13:11:50 +01:00
2026-03-10 12:41:33 +01:00
2026-03-09 10:42:31 +01:00

Chase-rs

An implementation of the chase algorithm in Rust for reasoning engines.

Overview

The chase algorithm is a technique in context of database theory and knowledge representation used for:

  • Query answering under tuple-generating dependencies (TGDs)
  • Computing universal models
  • Datalog with existential rules

This implementation provides a restricted-chase style materialization with active-trigger checks. The default entrypoints use a 10_000 step safeguard and report incomplete results with terminated == false if that limit is reached.

Features

  • Core Data Types: Terms, Atoms, Rules, and Instances
  • Existential Quantification: Automatic generation of labeled nulls
  • Restricted Chase Style: Active-trigger checks for existential rules
  • Configurable Step Limit: chase_with_config exposes the step bound
  • Fluent API: RuleBuilder for readable rule construction
  • Interactive Frontends: REPL, script runner, and a local GUI
  • Zero Dependencies: Pure Rust with no external runtime dependencies

See ROADMAP.md for the list of implemented and planned features.

Important

This project is still in early development, so bugs and breaking changes are expected. Please use the issues page to report bugs or request features.


Quickstart

Example

use chase_rs::{chase, Atom, Instance, Term};
use chase_rs::chase::rule::RuleBuilder;

// Create initial facts
let instance: Instance = vec![
    Atom::new("Parent", vec![Term::constant("alice"), Term::constant("bob")]),
    Atom::new("Parent", vec![Term::constant("bob"), Term::constant("carol")]),
].into_iter().collect();

// Define rules
// Parent(X, Y) -> Ancestor(X, Y)
let rule1 = RuleBuilder::new()
    .when("Parent", vec![Term::var("X"), Term::var("Y")])
    .then("Ancestor", vec![Term::var("X"), Term::var("Y")])
    .build();

// Ancestor(X, Y), Parent(Y, Z) -> Ancestor(X, Z)
let rule2 = RuleBuilder::new()
    .when("Ancestor", vec![Term::var("X"), Term::var("Y")])
    .when("Parent", vec![Term::var("Y"), Term::var("Z")])
    .then("Ancestor", vec![Term::var("X"), Term::var("Z")])
    .build();

// Run the chase
let result = chase(instance, &[rule1, rule2]);

assert!(result.terminated);
println!("Derived {} facts", result.instance.len());

Use chase_with_config to change the default step bound:

use chase_rs::{Atom, ChaseConfig, Instance, Term, chase_with_config};
use chase_rs::chase::rule::RuleBuilder;

let instance: Instance = vec![Atom::new("P", vec![Term::constant("a")])]
    .into_iter()
    .collect();
let rule = RuleBuilder::new()
    .when("P", vec![Term::var("X")])
    .then("Q", vec![Term::var("X")])
    .build();

let result = chase_with_config(
    instance,
    &[rule],
    ChaseConfig { max_steps: 100 },
);

assert!(result.terminated);

Existential Rules

Rules with head-only variables (existential quantification) automatically generate fresh labeled nulls:

// Every person has an SSN: Person(X) -> HasSSN(X, Y)
let rule = RuleBuilder::new()
    .when("Person", vec![Term::var("X")])
    .then("HasSSN", vec![Term::var("X"), Term::var("Y")]) // Y is existential
    .build();

Frontends

The binary now supports three entrypoints:

# Start the interactive REPL
cargo run -- repl

# Start the local GUI at http://127.0.0.1:7878
cargo run -- gui

# Run a script file
cargo run -- script examples/scripts/ancestor.chase

The REPL and GUI share a minimal command language:

fact Parent(alice, bob).
rule Parent(?X, ?Y) -> Ancestor(?X, ?Y).
run.
query Ancestor(?X, ?Y)?
explain Ancestor(alice, carol)?
show facts
show rules
reset
help

Rules:

  • facts and rules end with .
  • queries end with ?
  • explain ... ? shows one derivation tree per matching answer
  • variables are prefixed with ?
  • quoted constants are supported, for example "alice smith"

Useful Commands

# Install dependencies
nix develop -c make install-deps

# Run all tests
make test

# Run linter checks
make lint

# Run with optimizations
make build

# Run CLI
make run

License

This project is licensed under BSD-3.

Description
A chase algorithm implementation (with a lot of features like REPL, GUI, etc.) in Rust 🦀
Readme BSD-3-Clause 291 KiB
Languages
Rust 96.4%
Makefile 2.7%
Nix 0.9%