Skip to main content

A Python implementation of a semantic tableau calculus for weak Kleene logic with restricted quantification

Project description

wKrQ: A Python Implementation of a Semantic Tableau Calculus for Weak Kleene Logic with Restricted Quantification

PyPI version Python 3.9+ License: MIT Tests

An implementation of a semantic tableau calculus for first-order weak Kleene logic with restricted quantification, featuring a command-line interface for satisfiability and inference checking.

Citation

This implementation is based on the wKrQ tableau system defined in:

Ferguson, Thomas Macaulay. "Tableaux and restricted quantification for systems related to weak Kleene logic." In International Conference on Automated Reasoning with Analytic Tableaux and Related Methods, pp. 3-19. Cham: Springer International Publishing, 2021.

The tableau construction algorithms and six-sign system (t, f, e, m, n, v) implemented here follow Ferguson's formal definitions exactly. This is a research implementation created for experimental and educational purposes.

Research Software Disclaimer

⚠️ This is research software. While extensively tested, this implementation may contain errors or behave unexpectedly in edge cases. It is intended for research, education, and experimentation. Use in production systems is not recommended without thorough validation. Please report any issues or unexpected behavior through the issue tracker.

Features

  • 🎯 Three-valued semantics: true (t), false (f), undefined (e)
  • 🔤 Weak Kleene logic: Operations with undefined propagate undefinedness
  • 🔢 Restricted quantification: Domain-bounded first-order reasoning
  • 📋 Ferguson's six-sign system: t, f, e, m, n, v exactly as in the 2021 paper
  • 🔄 ACrQ extension: Analytic Containment for paraconsistent/paracomplete reasoning
  • Industrial performance: Optimized tableau with sub-millisecond response
  • 🖥️ CLI and API: Both command-line and programmatic interfaces
  • 📚 Comprehensive docs: Full documentation with examples
  • 🔍 Construction tracing: Step-by-step proof visualization showing all rule applications

Quick Start

Installation

pip install wkrq

Command Line Usage

# Test a simple formula
wkrq "p & q"

# Test with specific sign (t, f, e, m, n)
wkrq --sign=n "p | ~p"

# Show all models
wkrq --models "p | q"

# Display tableau tree
wkrq --tree "p -> q"

# Show construction trace
wkrq --trace "p & ~p"

# First-order logic with restricted quantifiers
# Unicode syntax:
wkrq "[∃X Student(X)]Human(X)"
wkrq "[∀X Human(X)]Mortal(X)"

# ASCII syntax (easier to type):
wkrq "[exists X Student(X)]Human(X)"
wkrq "[forall X Human(X)]Mortal(X)"

# Inference checking (uses |- turnstile syntax)
wkrq "p & q |- p"
wkrq "[forall X Human(X)]Mortal(X), Human(socrates) |- Mortal(socrates)"

# ACrQ paraconsistent reasoning (handles contradictions gracefully)
wkrq --mode=acrq "Human(alice) & ~Human(alice)"  # Satisfiable with glut!

# Interactive theory manager with LLM integration for ACrQ
acrq-llm  # Start interactive session
acrq-llm --file examples/example_13_maier_et_al.json  # Load existing theory

Python API

from wkrq import Formula, solve, valid, t, f, e, m, n

# Create formulas
p, q = Formula.atoms('p', 'q')
formula = p & (q | ~p)

# Test satisfiability
result = solve(formula, t)
print(f"Satisfiable: {result.satisfiable}")
print(f"Models: {result.models}")

# Test validity - Ferguson uses classical validity with weak Kleene
# semantics
tautology = p | ~p
print(f"Valid in Ferguson's system: {valid(tautology)}")  # True (classical
                                                         # tautologies are valid)

# Three-valued reasoning
result = solve(p | ~p, e)  # Can it be undefined?
print(f"Can be undefined: {result.satisfiable}")  # True

# ACrQ paraconsistent reasoning
from wkrq import parse_acrq_formula, SyntaxMode

# Handle contradictions gracefully (no explosion)
contradiction = parse_acrq_formula("Human(alice) & ~Human(alice)")
result = solve(contradiction, t)
print(f"Contradiction satisfiable: {result.satisfiable}")  # True (glut allowed)

# Different syntax modes for ACrQ
transparent = parse_acrq_formula("~Human(alice)", SyntaxMode.TRANSPARENT)  # Standard syntax
bilateral = parse_acrq_formula("Human*(alice)", SyntaxMode.BILATERAL)      # Explicit bilateral

# LLM Integration (requires pip install wkrq[llm])
from wkrq import create_openai_evaluator, ACrQTableau

# One line to create LLM evaluator!
evaluator = create_openai_evaluator(model='gpt-4')

# Use with tableau - LLM provides real-world knowledge
tableau = ACrQTableau(
    [SignedFormula(t, parse_acrq_formula("Planet(pluto)"))],
    llm_evaluator=evaluator
)
result = tableau.construct()  # LLM knows Pluto isn't a planet anymore

Theory Manager

The interactive theory manager provides a powerful environment for building and reasoning with logical theories:

# Start the ACrQ theory manager with LLM support
acrq-llm

# In the interactive session:
theory> assert Socrates is human
theory> assert All humans are mortal
theory> infer
# Infers: Mortal(socrates)

theory> claim firstManOnTheMoon(armstrong)  # LLM verifies: TRUE
theory> claim firstManOnTheMoon(scott)      # LLM refutes: FALSE

theory> check  # Check satisfiability and detect gluts/gaps
theory> save my_theory.json

Key features:

  • Natural language assertions with automatic translation
  • LLM-verified factual claims with the claim command
  • Paraconsistent reasoning (handles contradictions without explosion)
  • Gap and glut detection for information analysis
  • Persistent storage in JSON format
  • Integration with LLM providers for fact-checking

See the Theory Manager Tutorial for detailed usage.

Syntax and Semantics

Formal Language Definition

The language of wKrQ is defined by the following BNF grammar:

⟨formula⟩ ::= ⟨atom⟩ | ⟨compound⟩ | ⟨quantified⟩

⟨atom⟩ ::= p | q | r | ... | ⟨predicate⟩

⟨predicate⟩ ::= P(⟨term⟩,...,⟨term⟩)

⟨term⟩ ::= ⟨variable⟩ | ⟨constant⟩

⟨variable⟩ ::= X | Y | Z | ...

⟨constant⟩ ::= a | b | c | ...

⟨compound⟩ ::= ¬⟨formula⟩ | (⟨formula⟩ ∧ ⟨formula⟩) | 
               (⟨formula⟩ ∨ ⟨formula⟩) | (⟨formula⟩ → ⟨formula⟩)

⟨quantified⟩ ::= [∃⟨variable⟩ ⟨formula⟩]⟨formula⟩ | 
                 [∀⟨variable⟩ ⟨formula⟩]⟨formula⟩

Truth Tables

wKrQ implements weak Kleene three-valued logic with truth values:

  • t (true)
  • f (false)
  • e (undefined/error)

Negation (¬)

p ¬p
t f
f t
e e

Conjunction (∧)

p \ q t f e
t t f e
f f f e
e e e e

Disjunction (∨)

p \ q t f e
t t t e
f t f e
e e e e

Material Implication (→)

p \ q t f e
t t f e
f t t e
e e e e

Quantifier Semantics

Restricted Existential Quantification: [∃X φ(X)]ψ(X)

The formula is true iff there exists a domain element d such that both φ(d) and ψ(d) are true. It is false iff for all domain elements d, either φ(d) is false or ψ(d) is false (but not undefined). It is undefined if any evaluation results in undefined.

Restricted Universal Quantification: [∀X φ(X)]ψ(X)

The formula is true iff for all domain elements d, either φ(d) is false or ψ(d) is true. It is false iff there exists a domain element d such that φ(d) is true and ψ(d) is false. It is undefined if any evaluation results in undefined.

The key principle of weak Kleene logic is that any operation involving an undefined value produces an undefined result. This differs from strong Kleene logic where, for example, t ∨ e = t.

ACrQ: Analytic Containment with restricted Quantification

ACrQ extends wKrQ with bilateral predicates for paraconsistent and paracomplete reasoning:

Key Features

  • Paraconsistent: Handle contradictory information without explosion
  • Paracomplete: Handle incomplete information without classical assumptions
  • Bilateral predicates: Each predicate R has a dual R* for independent positive/negative tracking
  • Information states: Distinguishes true, false, gaps (missing info), and gluts (conflicting info)

Usage Modes

from wkrq import parse_acrq_formula, SyntaxMode

# Transparent mode (default): Standard syntax, automatic translation
formula1 = parse_acrq_formula("Human(alice) & ~Human(alice)")  # Handles gluts

# Bilateral mode: Explicit R/R* syntax required
formula2 = parse_acrq_formula("Human(alice) & Human*(alice)", SyntaxMode.BILATERAL)

# Mixed mode: Both syntaxes allowed
formula3 = parse_acrq_formula("Human(alice) & Robot*(bob)", SyntaxMode.MIXED)

Information States

State R(a) R*(a) Meaning
True t f Positive evidence only
False f t Negative evidence only
Gap f f No evidence (incomplete)
Glut t t Conflicting evidence (paraconsistent)

LLM Integration (ACrQ)

The ACrQ system seamlessly integrates with Large Language Models through the bilateral-truth package. This integration is specific to ACrQ because it leverages bilateral predicates to handle LLM uncertainty and conflicting information:

# Install with LLM support
pip install wkrq[llm]
from wkrq import create_openai_evaluator, ACrQTableau, parse_acrq_formula, SignedFormula, t

# One line to connect to your LLM
evaluator = create_openai_evaluator(model='gpt-4')  # Or use anthropic, google, local

# Combine formal logic with LLM knowledge
formulas = [
    SignedFormula(t, parse_acrq_formula("[∀X Orbits(X, sun)]Planet(X)")),  # Formal rule
    SignedFormula(t, parse_acrq_formula("Orbits(pluto, sun)")),            # Fact
]

tableau = ACrQTableau(formulas, llm_evaluator=evaluator)
result = tableau.construct()
# LLM knows modern astronomy: Pluto isn't a planet → contradiction detected

The bilateral-truth package handles all the complexity:

  • API connections and authentication
  • Prompt engineering for factuality assessment
  • Response parsing and error handling
  • Caching to minimize API calls

Supported providers: OpenAI, Anthropic, Google, local models (Ollama), and more.

Documentation

Core Documentation

Ferguson Compliance

ACrQ and LLM Integration

Examples

Philosophical Logic: Sorites Paradox

from wkrq import Formula, solve, T, N

# Model vague predicates with three-valued logic
heap_1000 = Formula.atom("Heap1000")  # Clearly a heap
heap_999 = Formula.atom("Heap999")    # Borderline case
heap_1 = Formula.atom("Heap1")        # Clearly not a heap

# Sorites principle
sorites = heap_1000.implies(heap_999)

# The paradox dissolves with undefined values
result = solve(heap_999, N)  # Can be undefined
print(f"Borderline case can be undefined: {result.satisfiable}")

First-Order Reasoning

from wkrq import Formula

# Variables and predicates
x = Formula.variable("X")
human = Formula.predicate("Human", [x])
mortal = Formula.predicate("Mortal", [x])

# Restricted quantification
all_humans_mortal = Formula.restricted_forall(x, human, mortal)
print(f"∀-formula: {all_humans_mortal}")  # [∀X Human(X)]Mortal(X)

Development

# Clone repository
git clone https://github.com/bradleypallen/wkrq.git
cd wkrq

# Install in development mode
pip install -e ".[dev]"

# Run tests
pytest

# Format code
black src tests
ruff check src tests

# Type checking
mypy src

Implementation Approach

The wKrQ package implements a semantic tableau calculus for three-valued weak Kleene logic with restricted quantification. The tableau engine (tableau.py) uses a six-sign system (t, f, e, m, n, v) following Ferguson (2021), where t and f represent definite truth values, e represents error/undefined, m represents epistemic uncertainty (both true and false are possible), n represents nontrue (false or undefined), and v is a meta-sign used in rule notation. The core algorithm maintains branches as collections of signed formulas, with hash-based indexing by sign and formula for O(1) contradiction detection. The system applies tableau rules in priority order: alpha-rules (non-branching) before beta-rules (branching), with explicit priority values assigned to each rule type. For quantifier instantiation, the engine tracks ground terms per branch and attempts unification with existing constants before generating fresh ones. Universal quantifiers are re-instantiated with new constants as they appear, with the system tracking which constants have been used for each quantified formula to prevent redundant applications. The implementation supports extension to ACrQ through polymorphic branch creation, where bilateral predicates R and R* are processed independently—t:R(a) generates only t:R(a) rather than also concluding f:R*(a), enabling paraconsistent reasoning where contradictory information (t:R(a) ∧ t:R*(a)) remains satisfiable. Model extraction from open branches assigns truth values based on the signs present: t-signed atoms map to true, f-signed to false, e-signed to undefined, with m-signed atoms arbitrarily assigned (true or false) to maintain completeness.

The ACrQ implementation extends wKrQ's tableau calculus to handle bilateral predicates for paraconsistent reasoning. Each predicate R has an associated dual predicate R*, with the system maintaining bidirectional mappings between them. The ACrQTableau class overrides the base tableau's branch creation to use ACrQBranch instances that track bilateral predicate pairs. During formula processing, negated predicates in transparent syntax mode are automatically converted: ¬R(x) becomes R*(x). The tableau rules for bilateral predicates differ fundamentally from standard predicates: t:R(x) produces only t:R(x) as a conclusion, while t:R*(x) produces only t:R*(x), without generating complementary constraints. Similarly, f:R(x) yields only f:R(x), and f:R*(x) yields only f:R*(x). The m-sign rules branch on individual predicates (m:R(x) branches to t:R(x) or f:R(x)), while n-sign rules generate knowledge gaps (n:R(x) produces f:R(x) and f:R*(x)). This design permits gluts where both R(a) and R*(a) hold true simultaneously—the _check_contradiction method in ACrQBranch explicitly allows t:R(a) and t:R*(a) to coexist without closing the branch. Model extraction constructs ACrQModel instances containing bilateral valuations: for each predicate-argument combination, the model tracks both positive and negative truth values as a BilateralTruthValue object. The semantic evaluator (ACrQEvaluator) retrieves the appropriate component based on whether the formula references R (positive component) or R* (negative component), maintaining weak Kleene semantics where any operation involving undefined values produces undefined results.

Note: Our implementation is validated against Ferguson (2021) and uses classical validity with weak Kleene semantics, meaning classical tautologies remain valid. The implementation has been thoroughly tested against literature examples - see the validation examples for comprehensive test results.

Citation

If you use wKrQ in academic work, please cite:

@software{wkrq2025,
  title={wKrQ: A Python Implementation of a Semantic Tableau Calculus for
         Weak Kleene Logic with Restricted Quantification},
  author={Allen, Bradley P.},
  year={2025},
  version={1.2.0},
  url={https://github.com/bradleypallen/wkrq}
}

License

MIT License - see LICENSE file for details.

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

wkrq-3.3.2.tar.gz (342.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

wkrq-3.3.2-py3-none-any.whl (75.4 kB view details)

Uploaded Python 3

File details

Details for the file wkrq-3.3.2.tar.gz.

File metadata

  • Download URL: wkrq-3.3.2.tar.gz
  • Upload date:
  • Size: 342.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.13

File hashes

Hashes for wkrq-3.3.2.tar.gz
Algorithm Hash digest
SHA256 34c9554ffd8662faf6dc67e5e8290f80fd100901fa879fc84beae28b5acf8509
MD5 15ec8b64ee408a19defeceabd3fa38f2
BLAKE2b-256 4dc7095735a05f3df57c7099c442dc747125f874bf2ef9040e7521a0053b6252

See more details on using hashes here.

File details

Details for the file wkrq-3.3.2-py3-none-any.whl.

File metadata

  • Download URL: wkrq-3.3.2-py3-none-any.whl
  • Upload date:
  • Size: 75.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.13

File hashes

Hashes for wkrq-3.3.2-py3-none-any.whl
Algorithm Hash digest
SHA256 e769b04adbd54a4f2072c024f82874e774e34233f5b631dbbee2451eb3d7bb62
MD5 76dc36c49746e0ab3690e19371777009
BLAKE2b-256 873755408e2d7e7713c393b6d03e4cfba32ca00cbc0ee41ae24cedb59b06c0e5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page