git @ Cat's Eye Technologies Burro / master src / Language / Burro / TCProof / Bisimulator.hs
master

Tree @master (Download .tar.gz)

Bisimulator.hs @master — raw · history · blame

-- SPDX-FileCopyrightText: This work was generated by Claude Opus 4.8 in 2026.
--
-- SPDX-License-Identifier: LicenseRef-No-Human-Authorship

module Language.Burro.TCProof.Bisimulator (BisimResult(..), runBisim) where

import qualified Language.Burro.Definition as B

import Language.Turmac.Model (TMRule, Configuration(..), initConfiguration, isHalted)
import Language.Turmac.Simulator (step)
import Language.Turmac.Renderer (renderConfig)
import Language.Burro.TCProof.Configuration (decodeConfiguration)

--
-- Bounded, step-by-step bisimulation checking
-- ===========================================
--
-- Unlike run-and-compare-turmac (which runs both the Turmac simulator and
-- the compiled Burro program to completion and compares only the final
-- configuration -- useless on a non-halting machine, since both sides
-- would simply hang), this compares the TM's configuration against the
-- decoded Burro configuration after *every* step, up to a bound, stopping
-- early if either side halts. This is the executable companion to the
-- Step Simulation Lemma / Bisimulation Theorem in
-- doc/Turing-completeness-of-Burro.md: it can be run on deliberately
-- non-halting machines to give direct evidence for the theorem's
-- non-halting-preservation corollary.
--

data BisimResult
    = BisimMatch Integer Bool
        -- ^ number of steps successfully compared in lockstep; whether
        -- both sides had halted by then (True) or the bound was reached
        -- with neither halting (False)
    | BisimMismatch Integer Configuration Configuration
        -- ^ first step at which the two sides' decoded configurations
        -- disagree, and each side's configuration at that step
    deriving (Eq, Show)

runBisim :: [TMRule] -> B.Burro -> Integer -> BisimResult
runBisim tmRules burroProg n =
    let
        burroCfg0 = decodeConfiguration tmRules False B.newstate
    in
        if renderConfig 0 initConfiguration /= renderConfig 0 burroCfg0
        then BisimMismatch 0 initConfiguration burroCfg0
        else go 0 initConfiguration B.newstate
  where
    go k tmCfg burroState
        | isHalted tmCfg = BisimMatch k True
        | k >= n = BisimMatch k False
        | otherwise =
            let
                tmCfg' = step tmRules tmCfg
                freshState = burroState{ B.stackTape=(B.tape [0]), B.haltFlag=True }
                burroState' = B.exec burroProg freshState
                burroHalted' = B.haltFlag burroState'
                burroCfg' = decodeConfiguration tmRules burroHalted' burroState'
            in
                if renderConfig (k + 1) tmCfg' /= renderConfig (k + 1) burroCfg'
                then BisimMismatch (k + 1) tmCfg' burroCfg'
                else go (k + 1) tmCfg' burroState'