chase-rs/README.md
Hassan Abedi dda7bfb9e8 WIP
2026-03-09 13:25:25 +01:00

2.8 KiB

Chase-rs

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

Overview

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

  • Query answering under tuple-generating dependencies (TGDs)
  • Computing universal models
  • Ontology-based data access (OBDA)
  • Datalog with existential rules

This implementation provides a restricted chase that guarantees termination even with existential rules by tracking applied triggers.

Features

  • Core Data Types: Terms, Atoms, Rules, and Instances
  • Existential Quantification: Automatic generation of labeled nulls
  • Restricted Chase: Termination guarantees via trigger tracking
  • Fluent API: RuleBuilder for readable rule construction
  • 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());

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();

Usful 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.