gargamelle-fol: First-order logic institution and streaming Z3 SMT pipe for Gargamelle

[ library, logic ] [ Propose Tags ] [ Report a vulnerability ]

First-order logic institution and streaming Z3 SMT solver pipeline for Gargamelle. Provides hyperdoctrine structures, quantifier elimination, and refinement calculus generation for formal program verification.


[Skip to Readme]

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

  • No Candidates
Versions [RSS] 0.1.0.0
Change log CHANGELOG.md
Dependencies base (>=4.18 && <5), containers (>=0.6 && <0.9), gargamelle-core (>=0.1 && <0.2), gargamelle-model (>=0.1 && <0.2), polytropos-core (>=0.1.0.1 && <0.2), process (>=1.6 && <1.7) [details]
Tested with ghc ==9.6.7, ghc ==9.8.4, ghc ==9.10.3, ghc ==9.12.4, ghc ==9.14.1
License EUPL-1.2
Author Nadia Yvette Chambers
Maintainer nadia.yvette.chambers@ik.me
Uploaded by nyc at 2026-11-03T12:42:35Z
Category Logic
Home page https://github.com/NadiaYvette/gargamelle
Bug tracker https://github.com/NadiaYvette/gargamelle/issues
Source repo head: git clone https://github.com/NadiaYvette/gargamelle(packages/gargamelle-fol)
Distributions
Downloads 3 total (3 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs uploaded by user
Build status unknown [no reports yet]

Readme for gargamelle-fol-0.1.0.0

[back to package description]

gargamelle-fol — First-Order Logic Institution, Hyperdoctrines & Streaming Z3 SMT-LIB2

Haskell License: EUPL-1.2 Tier 3 Logic Engine


1. Executive Summary & Problem Framing

Predicate logic with quantifiers and relational constraints is fundamental to system verification, contract refinement, and theorem proving. However, embedding first-order logic (FOL) into modern multi-agent synthesis loops introduces major architectural hurdles:

  1. FFI Brittleness & ABI Drift: Direct C/C++ FFI bindings to solvers like Z3 cause crashes across varying GHC versions (9.6–9.14) and complicate packaging across Nix, Stack, and Cabal.
  2. Opaque Solver Outputs: Traditional solver interfaces return bare booleans (Sat/Unsat), discarding the countermodel witnesses necessary for automated fault repair and inductive learning.
  3. Context Weakening & Quantifier Inconsistency: Ad-hoc substitution engines frequently introduce variable capture and fail to preserve the adjunction laws governing universal (\(\forall\)) and existential (\(\exists\)) quantifiers.

gargamelle-fol resolves these issues via rigorous categorical foundations and POSIX streaming:

  • First-Order Institution: Embeds FOL into the Goguen-Burstall framework, supporting Herbrand universe evaluation and signature morphisms.
  • Lawvere Hyperdoctrines: Formalizes quantifiers functorially as adjoints (\(\exists_t \dashv t^* \dashv \forall_t\)) to substitution functors over context categories.
  • Streaming SMT-LIB2 Pipe: Emits standard SMT-LIB2 scripts streamed over POSIX pipes directly to host Z3 without FFI overhead.
  • Structured Evidence Extraction: Automatically transforms Z3 countermodels into inspectable Counterexample witnesses and verified proofs into VerifiedSection.

2. Mathematical Foundations & Theoretical Invariants

2.1 Categorical Hyperdoctrine Quantifier Adjunctions

In Lawvere's categorical logic, a First-Order Hyperdoctrine is a functor \(\mathcal{P} : \mathbf{C}^{\mathrm{op}} \to \mathbf{HeytAlg}\) indexing propositional fibers over a cartesian category of contexts \(\mathbf{C}\):

                       P(X × Y) (Fiber over extended context)
                       ▲      ▲
         Substitution  │      │  Universal Quantifier
          π* (Pullback)│      │  ∀_π (Right Adjoint)
                       │      ▼
                         P(X)   (Fiber over base context)
  1. Pullback (Substitution): For any projection or term substitution \(\pi : X \times Y \to X\), the contravariant functorial action \(\pi^* : \mathcal{P}(X) \to \mathcal{P}(X \times Y)\) models context weakening.
  2. Existential Quantifier as Left Adjoint: \[\exists_\pi \dashv \pi^* \iff (\exists_\pi(\varphi) \le \psi \iff \varphi \le \pi^*(\psi))\]
  3. Universal Quantifier as Right Adjoint: \[\pi^* \dashv \forall_\pi \iff (\pi^*(\psi) \le \varphi \iff \psi \le \forall_\pi(\varphi))\]
  4. Beck-Chevalley Invariance: For any pullback square in \(\mathbf{C}\), the canonical comparison between quantification and substitution commutes.

2.2 Streaming SMT-LIB2 Piping & Dual Refutation

Interfacing with external solvers avoids foreign function bindings by utilizing streaming POSIX pipes:

┌─────────────────────┐       formulaToSMTLib        ┌───────────────────────┐
│ FirstOrder Formula  │ ───────────────────────────► │ SMT-LIB2 Script       │
└─────────────────────┘                              └───────────┬───────────┘
                                                                 │
                                                      readProcessWithExitCode
                                                                 ▼
┌─────────────────────┐        parseZ3Model          ┌───────────────────────┐
│ Evidence Witness    │ ◄─────────────────────────── │ Host Z3 stdout/stderr │
│ (Counterexample /   │                              │ (sat / unsat)         │
│  VerifiedSection)   │                              └───────────────────────┘
└─────────────────────┘
  • Dual Refutation: To verify that formula \(\varphi\) is valid, verifyValidityZ3 tests whether \(\neg \varphi\) is unsatisfiable.
  • Evidence Soundness:
    • \(\neg \varphi\) is \(\mathrm{UNSAT} \implies \varphi\) holds universally, producing VerifiedSection.
    • \(\neg \varphi\) is \(\mathrm{SAT} \implies\) Z3 produces a model \(\mathcal{M} \models \neg \varphi\). Parsing this model yields a concrete Counterexample containing the exact falsifying variable assignments.

3. Module Architecture & Repertoire Breadth

The package exports 4 modules providing complete first-order verification and solver piping:

Module Primary Types & Typeclasses Architectural Purpose
Gargamelle.FOL.Z3 (Hackage) solveZ3Raw (Hackage), checkFormulaZ3 (Hackage), verifyValidityZ3 (Hackage), SMTResult (Hackage) Streaming SMT-LIB2 serialization, host Z3 process piping, and model parsing.
FirstOrder (Hackage) Formula (Hackage), Term (Hackage), FOLModel (Hackage), evalFormula (Hackage) Core first-order logic syntax, Herbrand model structures, and evaluation.
Hyperdoctrine (Hackage) Context (Hackage), HDCSig (Hackage), HDModel (Hackage) Lawvere hyperdoctrine fibered contexts and categorical institution integration.
RefinementCalculus (Hackage) Spec (Hackage), spec (Hackage), refine (Hackage) Morgan-Back-von Wright refinement calculus specifications and contract preorder.

4. Executable Worked Examples

4.1 Automated Validity Verification via Z3 Pipe

{-# LANGUAGE DataKinds #-}

module ExampleZ3Validity where

import Data.Proxy (Proxy(..))
import FirstOrder (Formula(..))
import Gargamelle.FOL.Z3 (verifyValidityZ3)
import Gargamelle.Model.Satisfaction (Evidence(..))

-- Verify the Law of Excluded Middle: (P \/ not P)
verifyLEM :: IO ()
verifyLEM = do
  let p = Pred (Proxy @"P") []
      tautology = Or p (Not p)
  evidence <- verifyValidityZ3 tautology
  case evidence of
    VerifiedSection -> putStrLn "Formally verified: tautology holds across all models."
    Counterexample sym _witness -> putStrLn $ "Disproved: countermodel found in " ++ sym

4.2 Satisfiability Model Extraction

{-# LANGUAGE DataKinds #-}

module ExampleZ3Model where

import Data.Proxy (Proxy(..))
import FirstOrder (Formula(..))
import Gargamelle.FOL.Z3 (checkFormulaZ3, SMTResult(..))

-- Find satisfying model for (P /\ not Q)
findWitness :: IO ()
findWitness = do
  let p = Pred (Proxy @"P") []
      q = Pred (Proxy @"Q") []
      formula = And p (Not q)
  result <- checkFormulaZ3 formula
  case result of
    Sat model -> putStrLn $ "Satisfying model: " ++ show model
    Unsat     -> putStrLn "Formula is unsatisfiable."
    Unknown e -> putStrLn $ "Solver inconclusive: " ++ e

5. Integration Points & Subsystem Boundaries

gargamelle-fol serves at Tier 3 (Logic Engine) of the architecture:

┌────────────────────────────────────────────────────────┐
│               Downstream Consumers                     │
│  - gargamelle-workflow: CEGIS Induction & SMT Guidance │
│  - gargamelle-persistence: Logging SMT Run Records     │
└──────────────────────────▲─────────────────────────────┘
                           │
                  [gargamelle-fol]
                           │
┌──────────────────────────▼─────────────────────────────┐
│               Upstream Substrates                      │
│  - gargamelle-core: Institutions, Signatures           │
│  - gargamelle-model: Evidence, Verifier AST            │
│  - Host OS: /usr/bin/z3 executable (POSIX pipe)        │
└────────────────────────────────────────────────────────┘

6. Diagnostic & Troubleshooting Guide

6.1 z3 Binary Not Found

  • Symptom: solveZ3Raw crashes with readProcess: z3: does not exist (No such file or directory).
  • Root Cause: Host system lacks z3 on $PATH.
  • Remedy: Ensure z3 is installed via system packages (apt install z3 or nix-shell -p z3).

6.2 Unknown SMT Results

  • Symptom: verifyValidityZ3 returns Counterexample "Z3-Unknown" "...".
  • Root Cause: Nonlinear arithmetic, unbounded quantifiers, or timeout limits triggered Z3's incomplete heuristic engine.
  • Remedy: Skolemize existential quantifiers or restrict assertions to decidable SMT fragments (e.g. QF_LIA / QF_UF).

Part of the Gargamelle Verification Suite.