Documentation

VCVio.StateSeparating.CellRef

State-separating cell references #

Heap Ident stores typed cells at stable identifiers. CellRef Ident packages one identifier as a typed reference, so heap programs can say explicitly which cell they read or write.

The main purpose of this file is frame reasoning. A program that writes only a known footprint preserves every cell outside that footprint, and the same idea lifts from deterministic state programs to support-based effectful programs and to oracle handlers interpreted by simulateQ.

The file is organized around four small layers:

Cell references #

structure VCVio.StateSeparating.CellRef (Ident : Type u) [CellSpec Ident] :

A capability naming one typed cell in a Heap Ident. The value type of the reference is dependent: r.Value = CellSpec.type r.id.

  • id : Ident

    The underlying heap cell identifier.

Instances For
    @[reducible, inline]
    abbrev VCVio.StateSeparating.CellRef.Value {Ident : Type u} [CellSpec Ident] (r : CellRef Ident) :
    Type (max u v)

    The value type stored at a cell reference.

    Instances For
      @[reducible]
      def VCVio.StateSeparating.CellRef.get {Ident : Type u} [CellSpec Ident] (r : CellRef Ident) (h : Heap Ident) :

      Read a referenced cell from a heap.

      Instances For
        def VCVio.StateSeparating.CellRef.set {Ident : Type u} [CellSpec Ident] [DecidableEq Ident] (r : CellRef Ident) (h : Heap Ident) (x : r.Value) :
        Heap Ident

        Write a referenced cell in a heap.

        Instances For
          @[simp]
          theorem VCVio.StateSeparating.CellRef.get_set_self {Ident : Type u} [CellSpec Ident] [DecidableEq Ident] (r : CellRef Ident) (h : Heap Ident) (x : r.Value) :
          r.get (r.set h x) = x
          @[simp]
          theorem VCVio.StateSeparating.CellRef.get_set_of_ne {Ident : Type u} [CellSpec Ident] [DecidableEq Ident] (r s : CellRef Ident) (h : Heap Ident) (x : r.Value) (hne : s.id r.id) :
          s.get (r.set h x) = s.get h

          Deterministic state operations #

          def VCVio.StateSeparating.CellRef.read {Ident : Type u} [CellSpec Ident] (r : CellRef Ident) :
          StateT (Heap Ident) Id r.Value

          Deterministically read a referenced cell.

          Instances For

            Deterministically write a referenced cell.

            Instances For
              @[simp]
              theorem VCVio.StateSeparating.CellRef.read_run {Ident : Type u} [CellSpec Ident] (r : CellRef Ident) (h : Heap Ident) :
              r.read.run h = (r.get h, h)
              @[simp]
              theorem VCVio.StateSeparating.CellRef.write_run {Ident : Type u} [CellSpec Ident] [DecidableEq Ident] (r : CellRef Ident) (h : Heap Ident) (x : r.Value) :
              (r.write x).run h = (PUnit.unit, r.set h x)

              Effectful state operations #

              def VCVio.StateSeparating.CellRef.readM {Ident : Type u} [CellSpec Ident] (r : CellRef Ident) {m : Type (max u v) → Type u_1} [Monad m] :
              StateT (Heap Ident) m r.Value

              Effectfully read a referenced cell. This is the monadic version of CellRef.read: it works in any ambient monad, not just Id.

              Instances For
                def VCVio.StateSeparating.CellRef.writeM {Ident : Type u} [CellSpec Ident] [DecidableEq Ident] (r : CellRef Ident) (x : r.Value) {m : Type (max u v) → Type u_1} [Monad m] :

                Effectfully write a referenced cell. This is the monadic version of CellRef.write: it updates only the selected heap cell and performs no other ambient effects.

                Instances For
                  @[simp]
                  theorem VCVio.StateSeparating.CellRef.readM_run {Ident : Type u} [CellSpec Ident] (r : CellRef Ident) {m : Type (max u v) → Type u_1} [Monad m] (h : Heap Ident) :
                  r.readM.run h = pure (r.get h, h)
                  @[simp]
                  theorem VCVio.StateSeparating.CellRef.writeM_run {Ident : Type u} [CellSpec Ident] [DecidableEq Ident] (r : CellRef Ident) (x : r.Value) {m : Type (max u v) → Type u_1} [Monad m] (h : Heap Ident) :

                  Support-based frame predicates #

                  def VCVio.StateSeparating.CellRef.SupportPreserves {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] {α : Type (max u v)} (c : StateT (Heap Ident) m α) (r : CellRef Ident) :

                  An effectful heap program preserves a cell reference when every support-reachable final heap has the same value at that reference as the initial heap. This is the right generalization of Preserves beyond Id: for probabilistic/oracle computations there may be many possible final states.

                  Instances For
                    def VCVio.StateSeparating.CellRef.SupportWritesOnly {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] {α : Type (max u v)} (c : StateT (Heap Ident) m α) (writes : Set Ident) :

                    An effectful heap program writes only a set of identifiers when every cell outside the set is support-preserved.

                    Instances For
                      theorem VCVio.StateSeparating.CellRef.supportWritesOnly_mono {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] {α : Type (max u v)} {c : StateT (Heap Ident) m α} {writes₁ writes₂ : Set Ident} (hc : SupportWritesOnly c writes₁) (hsubset : writes₁ writes₂) :
                      SupportWritesOnly c writes₂
                      theorem VCVio.StateSeparating.CellRef.supportPreserves_pure {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] {α : Type (max u v)} (x : α) (r : CellRef Ident) :
                      theorem VCVio.StateSeparating.CellRef.supportWritesOnly_pure_empty {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] {α : Type (max u v)} (x : α) :
                      theorem VCVio.StateSeparating.CellRef.supportPreserves_readM {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] (r s : CellRef Ident) :
                      theorem VCVio.StateSeparating.CellRef.supportPreserves_bind {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] {α β : Type (max u v)} {c : StateT (Heap Ident) m α} {k : αStateT (Heap Ident) m β} {r : CellRef Ident} (hc : SupportPreserves c r) (hk : ∀ (a : α), SupportPreserves (k a) r) :
                      theorem VCVio.StateSeparating.CellRef.writeM_supportWritesOnly_single {Ident : Type u} [CellSpec Ident] [DecidableEq Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] (r : CellRef Ident) (x : r.Value) :
                      theorem VCVio.StateSeparating.CellRef.supportWritesOnly_bind {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] {α β : Type (max u v)} {c : StateT (Heap Ident) m α} {k : αStateT (Heap Ident) m β} {writes₁ writes₂ : Set Ident} (hc : SupportWritesOnly c writes₁) (hk : ∀ (a : α), SupportWritesOnly (k a) writes₂) :
                      SupportWritesOnly (c >>= k) (writes₁ writes₂)
                      theorem VCVio.StateSeparating.CellRef.supportWritesOnly_bind_dep {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] {α β : Type (max u v)} {c : StateT (Heap Ident) m α} {k : αStateT (Heap Ident) m β} {writes₁ : Set Ident} {writes₂ : αSet Ident} (hc : SupportWritesOnly c writes₁) (hk : ∀ (a : α), SupportWritesOnly (k a) (writes₂ a)) :
                      SupportWritesOnly (c >>= k) (writes₁ {i : Ident | ∃ (a : α), i writes₂ a})

                      Dependent effectful bind form: the continuation's write set may depend on the first result.

                      structure VCVio.StateSeparating.CellRef.SupportWriteFootprint {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] {α : Type (max u v)} (c : StateT (Heap Ident) m α) :

                      A support-based write footprint packages a program with the set of cells it may write and the proof that every other cell is preserved.

                      • writes : Set Ident

                        Cells that the effectful program may write.

                      • sound : SupportWritesOnly c self.writes

                        Soundness: every cell outside writes is support-framed through.

                      Instances For
                        theorem VCVio.StateSeparating.CellRef.SupportWriteFootprint.preserves {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] {α : Type (max u v)} {c : StateT (Heap Ident) m α} (footprint : SupportWriteFootprint c) (r : CellRef Ident) (hr : r.idfootprint.writes) :
                        def VCVio.StateSeparating.CellRef.SupportWriteFootprint.pure {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] {α : Type (max u v)} (x : α) :
                        Instances For
                          Instances For
                            def VCVio.StateSeparating.CellRef.SupportWriteFootprint.writeM {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] [DecidableEq Ident] (r : CellRef Ident) (x : r.Value) :
                            Instances For
                              def VCVio.StateSeparating.CellRef.SupportWriteFootprint.bind {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] {α β : Type (max u v)} {c : StateT (Heap Ident) m α} {k : αStateT (Heap Ident) m β} (footprint : SupportWriteFootprint c) (kont : (a : α) → SupportWriteFootprint (k a)) :
                              Instances For

                                Probability corollaries for cell frames #

                                theorem VCVio.StateSeparating.CellRef.SupportPreserves.prob_changed_eq_zero {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSPMF m] {α : Type (max u v)} {c : StateT (Heap Ident) m α} {r : CellRef Ident} (hc : SupportPreserves c r) (h : Heap Ident) :
                                (probEvent (c.run h) fun (z : α × Heap Ident) => r.get z.2 r.get h) = 0

                                A support-level frame implies that the cell-change event has probability zero. This is the probability-facing corollary most proofs want after a generic frame theorem has done the support-level work.

                                theorem VCVio.StateSeparating.CellRef.SupportPreserves.prob_unchanged_eq_sub_probFailure {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSPMF m] {α : Type (max u v)} {c : StateT (Heap Ident) m α} {r : CellRef Ident} (hc : SupportPreserves c r) (h : Heap Ident) :
                                (probEvent (c.run h) fun (z : α × Heap Ident) => r.get z.2 = r.get h) = 1 - Pr[⊥ | c.run h]

                                If a cell is support-preserved, then the probability of reading the initial value at the end is exactly one minus the failure probability.

                                theorem VCVio.StateSeparating.CellRef.SupportPreserves.prob_unchanged_eq_one_of_probFailure_eq_zero {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSPMF m] {α : Type (max u v)} {c : StateT (Heap Ident) m α} {r : CellRef Ident} (hc : SupportPreserves c r) (h : Heap Ident) (hnf : Pr[⊥ | c.run h] = 0) :
                                (probEvent (c.run h) fun (z : α × Heap Ident) => r.get z.2 = r.get h) = 1

                                Failure-free specialization of prob_unchanged_eq_sub_probFailure.

                                theorem VCVio.StateSeparating.CellRef.SupportPreserves.prob_unchanged_eq_one {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_2} [Monad m] [HasEvalPMF m] {α : Type (max u v)} {c : StateT (Heap Ident) m α} {r : CellRef Ident} (hc : SupportPreserves c r) (h : Heap Ident) :
                                (probEvent (c.run h) fun (z : α × Heap Ident) => r.get z.2 = r.get h) = 1

                                If the ambient monad has total probability semantics, support preservation gives probability-one preservation directly.

                                theorem VCVio.StateSeparating.CellRef.SupportPreserves.prob_final_eq_eq_zero_of_ne {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSPMF m] {α : Type (max u v)} {c : StateT (Heap Ident) m α} {r : CellRef Ident} (hc : SupportPreserves c r) (h : Heap Ident) {x : r.Value} (hne : x r.get h) :
                                (probEvent (c.run h) fun (z : α × Heap Ident) => r.get z.2 = x) = 0

                                If the initial cell value is not x, then a support-preserved cell has final value x with probability zero.

                                theorem VCVio.StateSeparating.CellRef.SupportWritesOnly.prob_changed_eq_zero {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSPMF m] {α : Type (max u v)} {c : StateT (Heap Ident) m α} {writes : Set Ident} (hc : SupportWritesOnly c writes) (r : CellRef Ident) (hr : r.idwrites) (h : Heap Ident) :
                                (probEvent (c.run h) fun (z : α × Heap Ident) => r.get z.2 r.get h) = 0
                                theorem VCVio.StateSeparating.CellRef.SupportWritesOnly.prob_unchanged_eq_sub_probFailure {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSPMF m] {α : Type (max u v)} {c : StateT (Heap Ident) m α} {writes : Set Ident} (hc : SupportWritesOnly c writes) (r : CellRef Ident) (hr : r.idwrites) (h : Heap Ident) :
                                (probEvent (c.run h) fun (z : α × Heap Ident) => r.get z.2 = r.get h) = 1 - Pr[⊥ | c.run h]
                                theorem VCVio.StateSeparating.CellRef.SupportWritesOnly.prob_final_eq_eq_zero_of_ne {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSPMF m] {α : Type (max u v)} {c : StateT (Heap Ident) m α} {writes : Set Ident} (hc : SupportWritesOnly c writes) (r : CellRef Ident) (hr : r.idwrites) (h : Heap Ident) {x : r.Value} (hne : x r.get h) :
                                (probEvent (c.run h) fun (z : α × Heap Ident) => r.get z.2 = x) = 0

                                Preservation except an event #

                                def VCVio.StateSeparating.CellRef.SupportPreservesExcept {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] {α : Type (max u v)} (c : StateT (Heap Ident) m α) (r : CellRef Ident) (event : Heap Identα × Heap IdentProp) :

                                A computation preserves a cell except on an event when every support-reachable outcome outside that event has the initial cell value. The event may depend on the initial heap.

                                Instances For
                                  theorem VCVio.StateSeparating.CellRef.SupportPreservesExcept.of_supportPreserves {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] {α : Type (max u v)} {c : StateT (Heap Ident) m α} {r : CellRef Ident} {event : Heap Identα × Heap IdentProp} (hc : SupportPreserves c r) :
                                  theorem VCVio.StateSeparating.CellRef.SupportPreservesExcept.mono_event {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] {α : Type (max u v)} {c : StateT (Heap Ident) m α} {r : CellRef Ident} {event : Heap Identα × Heap IdentProp} (hc : SupportPreservesExcept c r event) {event' : Heap Identα × Heap IdentProp} (hsubset : ∀ (h : Heap Ident) (z : α × Heap Ident), event h zevent' h z) :
                                  theorem VCVio.StateSeparating.CellRef.SupportPreservesExcept.supportPreserves_of_false_event {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] {α : Type (max u v)} {c : StateT (Heap Ident) m α} {r : CellRef Ident} (hc : SupportPreservesExcept c r fun (x : Heap Ident) (x_1 : α × Heap Ident) => False) :
                                  theorem VCVio.StateSeparating.CellRef.SupportPreservesExcept.prob_changed_le_prob_event {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSPMF m] {α : Type (max u v)} {c : StateT (Heap Ident) m α} {r : CellRef Ident} {event : Heap Identα × Heap IdentProp} (hc : SupportPreservesExcept c r event) (h : Heap Ident) :
                                  (probEvent (c.run h) fun (z : α × Heap Ident) => r.get z.2 r.get h) probEvent (c.run h) fun (z : α × Heap Ident) => event h z

                                  If a cell can change only when event occurs, then the change probability is bounded by the event probability.

                                  theorem VCVio.StateSeparating.CellRef.SupportPreservesExcept.prob_changed_eq_zero_of_prob_event_eq_zero {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSPMF m] {α : Type (max u v)} {c : StateT (Heap Ident) m α} {r : CellRef Ident} {event : Heap Identα × Heap IdentProp} (hc : SupportPreservesExcept c r event) (h : Heap Ident) (hevent : (probEvent (c.run h) fun (z : α × Heap Ident) => event h z) = 0) :
                                  (probEvent (c.run h) fun (z : α × Heap Ident) => r.get z.2 r.get h) = 0
                                  theorem VCVio.StateSeparating.CellRef.SupportPreservesExcept.prob_changed_le_of_prob_event_le {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSPMF m] {α : Type (max u v)} {c : StateT (Heap Ident) m α} {r : CellRef Ident} {event : Heap Identα × Heap IdentProp} (hc : SupportPreservesExcept c r event) (h : Heap Ident) {ε : ENNReal} (hevent : (probEvent (c.run h) fun (z : α × Heap Ident) => event h z) ε) :
                                  (probEvent (c.run h) fun (z : α × Heap Ident) => r.get z.2 r.get h) ε

                                  Relational and measured cell effects #

                                  def VCVio.StateSeparating.CellRef.SupportCellRel {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] {α : Type (max u v)} (c : StateT (Heap Ident) m α) (r : CellRef Ident) (rel : r.Valuer.ValueProp) :

                                  A support-level relation between the initial and final value of one cell. This is the general qualitative layer underneath preservation (rel := Eq) and monotonicity/growth assertions.

                                  Instances For
                                    theorem VCVio.StateSeparating.CellRef.SupportCellRel.of_supportPreserves {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] {α : Type (max u v)} {c : StateT (Heap Ident) m α} {r : CellRef Ident} (hc : SupportPreserves c r) :
                                    theorem VCVio.StateSeparating.CellRef.SupportCellRel.supportPreserves_of_eq {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] {α : Type (max u v)} {c : StateT (Heap Ident) m α} {r : CellRef Ident} (hc : SupportCellRel c r Eq) :
                                    theorem VCVio.StateSeparating.CellRef.SupportCellRel.bind {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] {α β : Type (max u v)} {c : StateT (Heap Ident) m α} {k : αStateT (Heap Ident) m β} {r : CellRef Ident} {rel : r.Valuer.ValueProp} (hc : SupportCellRel c r rel) (hk : ∀ (a : α), SupportCellRel (k a) r rel) (htrans : ∀ (x y z : r.Value), rel x yrel y zrel x z) :
                                    SupportCellRel (c >>= k) r rel
                                    theorem VCVio.StateSeparating.CellRef.SupportCellRel.prob_violate_eq_zero {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSPMF m] {α : Type (max u v)} {c : StateT (Heap Ident) m α} {r : CellRef Ident} {rel : r.Valuer.ValueProp} (hc : SupportCellRel c r rel) (h : Heap Ident) :
                                    (probEvent (c.run h) fun (z : α × Heap Ident) => ¬rel (r.get h) (r.get z.2)) = 0

                                    A support-level cell relation makes violations of the relation a probability-zero event.

                                    def VCVio.StateSeparating.CellRef.SupportMeasureBound {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] {α : Type (max u v)} (c : StateT (Heap Ident) m α) (r : CellRef Ident) (measure : r.Value) (δ : ) :

                                    A measured cell bound says a numeric measure of a cell can increase by at most δ on every support-reachable execution path. Binds compose by adding their deltas.

                                    Instances For
                                      theorem VCVio.StateSeparating.CellRef.SupportMeasureBound.of_supportPreserves {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] {α : Type (max u v)} {c : StateT (Heap Ident) m α} {r : CellRef Ident} {measure : r.Value} (hc : SupportPreserves c r) :
                                      SupportMeasureBound c r measure 0
                                      theorem VCVio.StateSeparating.CellRef.SupportMeasureBound.mono_delta {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] {α : Type (max u v)} {c : StateT (Heap Ident) m α} {r : CellRef Ident} {measure : r.Value} {δ₁ δ₂ : } (hc : SupportMeasureBound c r measure δ₁) (hle : δ₁ δ₂) :
                                      SupportMeasureBound c r measure δ₂
                                      theorem VCVio.StateSeparating.CellRef.SupportMeasureBound.bind {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSet m] {α β : Type (max u v)} {c : StateT (Heap Ident) m α} {k : αStateT (Heap Ident) m β} {r : CellRef Ident} {measure : r.Value} {δ₁ δ₂ : } (hc : SupportMeasureBound c r measure δ₁) (hk : ∀ (a : α), SupportMeasureBound (k a) r measure δ₂) :
                                      SupportMeasureBound (c >>= k) r measure (δ₁ + δ₂)
                                      theorem VCVio.StateSeparating.CellRef.SupportMeasureBound.prob_exceeds_eq_zero {Ident : Type u} [CellSpec Ident] {m : Type (max u v) → Type u_1} [Monad m] [HasEvalSPMF m] {α : Type (max u v)} {c : StateT (Heap Ident) m α} {r : CellRef Ident} {measure : r.Value} {δ : } (hc : SupportMeasureBound c r measure δ) (h : Heap Ident) :
                                      (probEvent (c.run h) fun (z : α × Heap Ident) => measure (r.get h) + δ < measure (r.get z.2)) = 0

                                      A measured support bound gives probability zero to exceeding the bound.

                                      Deterministic specialization #

                                      def VCVio.StateSeparating.CellRef.Preserves {Ident : Type u} [CellSpec Ident] {α : Type (max u v)} (c : StateT (Heap Ident) Id α) (r : CellRef Ident) :

                                      A deterministic heap program preserves a cell reference when the final heap has the same value at that reference as the initial heap.

                                      This exact Id-specific predicate is equivalent to SupportPreserves, whose support contains exactly the single deterministic output. The exact form keeps deterministic examples pleasant to use, while the combinator proofs below are derived from the generic support-based API.

                                      Instances For
                                        def VCVio.StateSeparating.CellRef.WritesOnly {Ident : Type u} [CellSpec Ident] {α : Type (max u v)} (c : StateT (Heap Ident) Id α) (writes : Set Ident) :

                                        A deterministic heap program writes only a set of identifiers when every cell outside the set is preserved.

                                        Instances For
                                          theorem VCVio.StateSeparating.CellRef.supportPreserves_of_preserves {Ident : Type u} [CellSpec Ident] {α : Type (max u v)} {c : StateT (Heap Ident) Id α} {r : CellRef Ident} (hc : Preserves c r) :
                                          theorem VCVio.StateSeparating.CellRef.preserves_of_supportPreserves {Ident : Type u} [CellSpec Ident] {α : Type (max u v)} {c : StateT (Heap Ident) Id α} {r : CellRef Ident} (hc : SupportPreserves c r) :
                                          theorem VCVio.StateSeparating.CellRef.supportPreserves_iff_preserves {Ident : Type u} [CellSpec Ident] {α : Type (max u v)} {c : StateT (Heap Ident) Id α} {r : CellRef Ident} :

                                          For the Id monad, support-based cell preservation is exactly the same as the direct final-state equality predicate.

                                          theorem VCVio.StateSeparating.CellRef.supportWritesOnly_of_writesOnly {Ident : Type u} [CellSpec Ident] {α : Type (max u v)} {c : StateT (Heap Ident) Id α} {writes : Set Ident} (hc : WritesOnly c writes) :
                                          theorem VCVio.StateSeparating.CellRef.writesOnly_of_supportWritesOnly {Ident : Type u} [CellSpec Ident] {α : Type (max u v)} {c : StateT (Heap Ident) Id α} {writes : Set Ident} (hc : SupportWritesOnly c writes) :
                                          WritesOnly c writes
                                          theorem VCVio.StateSeparating.CellRef.supportWritesOnly_iff_writesOnly {Ident : Type u} [CellSpec Ident] {α : Type (max u v)} {c : StateT (Heap Ident) Id α} {writes : Set Ident} :
                                          SupportWritesOnly c writes WritesOnly c writes
                                          theorem VCVio.StateSeparating.CellRef.writesOnly_mono {Ident : Type u} [CellSpec Ident] {α : Type (max u v)} {c : StateT (Heap Ident) Id α} {writes₁ writes₂ : Set Ident} (hc : WritesOnly c writes₁) (hsubset : writes₁ writes₂) :
                                          WritesOnly c writes₂
                                          theorem VCVio.StateSeparating.CellRef.preserves_pure {Ident : Type u} [CellSpec Ident] {α : Type (max u v)} (x : α) (r : CellRef Ident) :
                                          theorem VCVio.StateSeparating.CellRef.preserves_bind {Ident : Type u} [CellSpec Ident] {α β : Type (max u v)} {c : StateT (Heap Ident) Id α} {k : αStateT (Heap Ident) Id β} {r : CellRef Ident} (hc : Preserves c r) (hk : ∀ (a : α), Preserves (k a) r) :
                                          Preserves (c >>= k) r
                                          theorem VCVio.StateSeparating.CellRef.writesOnly_bind {Ident : Type u} [CellSpec Ident] {α β : Type (max u v)} {c : StateT (Heap Ident) Id α} {k : αStateT (Heap Ident) Id β} {writes₁ writes₂ : Set Ident} (hc : WritesOnly c writes₁) (hk : ∀ (a : α), WritesOnly (k a) writes₂) :
                                          WritesOnly (c >>= k) (writes₁ writes₂)
                                          theorem VCVio.StateSeparating.CellRef.writesOnly_bind_dep {Ident : Type u} [CellSpec Ident] {α β : Type (max u v)} {c : StateT (Heap Ident) Id α} {k : αStateT (Heap Ident) Id β} {writes₁ : Set Ident} {writes₂ : αSet Ident} (hc : WritesOnly c writes₁) (hk : ∀ (a : α), WritesOnly (k a) (writes₂ a)) :
                                          WritesOnly (c >>= k) (writes₁ {i : Ident | ∃ (a : α), i writes₂ a})

                                          Dependent bind form: the continuation's write set may depend on the first result. The resulting write set is the union of the first write set and all possible continuation write sets.

                                          Read agreement and result-dependence footprints #

                                          def VCVio.StateSeparating.CellRef.SameOn {Ident : Type u} [CellSpec Ident] (cells : Set Ident) (h₁ h₂ : Heap Ident) :

                                          Two heaps agree on a set of cell identifiers when every reference whose identifier is in the set reads the same value from both heaps.

                                          Instances For
                                            theorem VCVio.StateSeparating.CellRef.sameOn_refl {Ident : Type u} [CellSpec Ident] (cells : Set Ident) (h : Heap Ident) :
                                            SameOn cells h h
                                            theorem VCVio.StateSeparating.CellRef.sameOn_mono {Ident : Type u} [CellSpec Ident] {cells₁ cells₂ : Set Ident} {h₁ h₂ : Heap Ident} (hsubset : cells₁ cells₂) (hsame : SameOn cells₂ h₁ h₂) :
                                            SameOn cells₁ h₁ h₂
                                            theorem VCVio.StateSeparating.CellRef.sameOn_singleton_read {Ident : Type u} [CellSpec Ident] {r : CellRef Ident} {h₁ h₂ : Heap Ident} (hsame : SameOn {r.id} h₁ h₂) :
                                            r.get h₁ = r.get h₂
                                            def VCVio.StateSeparating.CellRef.ResultDependsOnly {Ident : Type u} [CellSpec Ident] {α : Type (max u v)} (c : StateT (Heap Ident) Id α) (reads : Set Ident) :

                                            A deterministic heap program's result depends only on a set of cells when heaps agreeing on those cells produce equal return values. This intentionally tracks only the returned value, not the final heap.

                                            Instances For

                                              Compositional write footprints #

                                              structure VCVio.StateSeparating.CellRef.WriteFootprint {Ident : Type u} [CellSpec Ident] {α : Type (max u v)} (c : StateT (Heap Ident) Id α) :

                                              A compositional write footprint packages a deterministic heap program with the set of cells it may write and the proof that all other cells are preserved.

                                              • writes : Set Ident

                                                Cells that the program may write.

                                              • sound : WritesOnly c self.writes

                                                Soundness: every cell outside writes is framed through.

                                              Instances For
                                                theorem VCVio.StateSeparating.CellRef.WriteFootprint.preserves {Ident : Type u} [CellSpec Ident] {α : Type (max u v)} {c : StateT (Heap Ident) Id α} (footprint : WriteFootprint c) (r : CellRef Ident) (hr : r.idfootprint.writes) :
                                                def VCVio.StateSeparating.CellRef.WriteFootprint.pure {Ident : Type u} [CellSpec Ident] {α : Type (max u v)} (x : α) :
                                                Instances For
                                                  Instances For
                                                    def VCVio.StateSeparating.CellRef.WriteFootprint.bind {Ident : Type u} [CellSpec Ident] {α β : Type (max u v)} {c : StateT (Heap Ident) Id α} {k : αStateT (Heap Ident) Id β} (footprint : WriteFootprint c) (kont : (a : α) → WriteFootprint (k a)) :
                                                    Instances For

                                                      Query-implementation cell frames #

                                                      def VCVio.StateSeparating.QueryImpl.PreservesCell {ι : Type uι} {spec : OracleSpec ι} {Ident₀ : Type u₀} [CellSpec Ident₀] {m : Type (max u₀ v) → Type u_1} [Monad m] [HasEvalSet m] (impl : QueryImpl spec (StateT (Heap Ident₀) m)) (r : CellRef Ident₀) :

                                                      A QueryImpl preserves a heap cell when each single query step leaves that cell unchanged on every support-reachable post-state. This is the support-level analogue of CellRef.Preserves for probabilistic handlers.

                                                      Instances For
                                                        def VCVio.StateSeparating.QueryImpl.WritesOnlyCells {ι : Type uι} {spec : OracleSpec ι} {Ident₀ : Type u₀} [CellSpec Ident₀] {m : Type (max u₀ v) → Type u_1} [Monad m] [HasEvalSet m] (impl : QueryImpl spec (StateT (Heap Ident₀) m)) (writes : spec.DomainSet Ident₀) :

                                                        A QueryImpl writes only the cells named by a per-query footprint when each query step support-preserves every cell outside its footprint.

                                                        Instances For
                                                          theorem VCVio.StateSeparating.QueryImpl.writesOnlyCells_mono {ι : Type uι} {spec : OracleSpec ι} {Ident₀ : Type u₀} [CellSpec Ident₀] {m : Type (max u₀ v) → Type u_1} [Monad m] [HasEvalSet m] {impl : QueryImpl spec (StateT (Heap Ident₀) m)} {writes₁ writes₂ : spec.DomainSet Ident₀} (himpl : WritesOnlyCells impl writes₁) (hsubset : ∀ (t : spec.Domain), writes₁ t writes₂ t) :
                                                          WritesOnlyCells impl writes₂
                                                          theorem VCVio.StateSeparating.QueryImpl.preservesCell_of_writesOnlyCells {ι : Type uι} {spec : OracleSpec ι} {Ident₀ : Type u₀} [CellSpec Ident₀] {m : Type (max u₀ v) → Type u_1} [Monad m] [HasEvalSet m] {impl : QueryImpl spec (StateT (Heap Ident₀) m)} {writes : spec.DomainSet Ident₀} {r : CellRef Ident₀} (himpl : WritesOnlyCells impl writes) (hr : ∀ (t : spec.Domain), r.idwrites t) :
                                                          structure VCVio.StateSeparating.QueryImpl.CellWriteFootprint {ι : Type uι} {spec : OracleSpec ι} {Ident₀ : Type u₀} [CellSpec Ident₀] {m : Type (max u₀ v) → Type u_1} [Monad m] [HasEvalSet m] (impl : QueryImpl spec (StateT (Heap Ident₀) m)) :
                                                          Type (max uι u₀)

                                                          A compositional cell-write footprint for a whole query implementation: every domain element gets a set of cells it may write, plus a support-level proof that no other cells change.

                                                          • writes : spec.DomainSet Ident₀

                                                            Per-query cells that may be written by the handler branch.

                                                          • sound : WritesOnlyCells impl self.writes

                                                            Soundness of the footprint.

                                                          Instances For
                                                            theorem VCVio.StateSeparating.QueryImpl.CellWriteFootprint.preservesCell {ι : Type uι} {spec : OracleSpec ι} {Ident₀ : Type u₀} [CellSpec Ident₀] {m : Type (max u₀ v) → Type u_1} [Monad m] [HasEvalSet m] {impl : QueryImpl spec (StateT (Heap Ident₀) m)} (footprint : CellWriteFootprint impl) (r : CellRef Ident₀) (hr : ∀ (t : spec.Domain), r.idfootprint.writes t) :
                                                            theorem VCVio.StateSeparating.OracleComp.simulateQ_run_cellPreserved {ι : Type uι} {spec : OracleSpec ι} {α : Type (max u₀ v)} {Ident₀ : Type u₀} [CellSpec Ident₀] {m : Type (max u₀ v) → Type u_1} [Monad m] [LawfulMonad m] [HasEvalSet m] (impl : QueryImpl spec (StateT (Heap Ident₀) m)) (r : CellRef Ident₀) (himpl : QueryImpl.PreservesCell impl r) (A : OracleComp spec α) (h : Heap Ident₀) (z : α × Heap Ident₀) :
                                                            z support ((simulateQ impl A).run h)r.get z.2 = r.get h

                                                            If every handler query preserves a cell, then interpreting any OracleComp through that handler preserves the cell.

                                                            theorem VCVio.StateSeparating.QueryImpl.PreservesCell.prob_changed_eq_zero {ι : Type uι} {spec : OracleSpec ι} {Ident₀ : Type u₀} [CellSpec Ident₀] {m : Type (max u₀ v) → Type u_1} [Monad m] [HasEvalSPMF m] {impl : QueryImpl spec (StateT (Heap Ident₀) m)} {r : CellRef Ident₀} (himpl : PreservesCell impl r) (t : spec.Domain) (h : Heap Ident₀) :
                                                            (probEvent ((impl t).run h) fun (z : spec.Range t × Heap Ident₀) => r.get z.2 r.get h) = 0
                                                            theorem VCVio.StateSeparating.QueryImpl.PreservesCell.prob_unchanged_eq_sub_probFailure {ι : Type uι} {spec : OracleSpec ι} {Ident₀ : Type u₀} [CellSpec Ident₀] {m : Type (max u₀ v) → Type u_1} [Monad m] [HasEvalSPMF m] {impl : QueryImpl spec (StateT (Heap Ident₀) m)} {r : CellRef Ident₀} (himpl : PreservesCell impl r) (t : spec.Domain) (h : Heap Ident₀) :
                                                            (probEvent ((impl t).run h) fun (z : spec.Range t × Heap Ident₀) => r.get z.2 = r.get h) = 1 - Pr[⊥ | (impl t).run h]
                                                            theorem VCVio.StateSeparating.QueryImpl.CellWriteFootprint.prob_changed_eq_zero {ι : Type uι} {spec : OracleSpec ι} {Ident₀ : Type u₀} [CellSpec Ident₀] {m : Type (max u₀ v) → Type u_1} [Monad m] [HasEvalSPMF m] {impl : QueryImpl spec (StateT (Heap Ident₀) m)} (footprint : CellWriteFootprint impl) (r : CellRef Ident₀) (hr : ∀ (t : spec.Domain), r.idfootprint.writes t) (t : spec.Domain) (h : Heap Ident₀) :
                                                            (probEvent ((impl t).run h) fun (z : spec.Range t × Heap Ident₀) => r.get z.2 r.get h) = 0
                                                            theorem VCVio.StateSeparating.QueryImpl.CellWriteFootprint.prob_unchanged_eq_sub_probFailure {ι : Type uι} {spec : OracleSpec ι} {Ident₀ : Type u₀} [CellSpec Ident₀] {m : Type (max u₀ v) → Type u_1} [Monad m] [HasEvalSPMF m] {impl : QueryImpl spec (StateT (Heap Ident₀) m)} (footprint : CellWriteFootprint impl) (r : CellRef Ident₀) (hr : ∀ (t : spec.Domain), r.idfootprint.writes t) (t : spec.Domain) (h : Heap Ident₀) :
                                                            (probEvent ((impl t).run h) fun (z : spec.Range t × Heap Ident₀) => r.get z.2 = r.get h) = 1 - Pr[⊥ | (impl t).run h]
                                                            theorem VCVio.StateSeparating.OracleComp.simulateQ_run_cellChange_prob_eq_zero {ι : Type uι} {spec : OracleSpec ι} {α : Type (max u₀ v)} {Ident₀ : Type u₀} [CellSpec Ident₀] {m : Type (max u₀ v) → Type u_1} [Monad m] [LawfulMonad m] [HasEvalSPMF m] (impl : QueryImpl spec (StateT (Heap Ident₀) m)) (r : CellRef Ident₀) (himpl : QueryImpl.PreservesCell impl r) (A : OracleComp spec α) (h : Heap Ident₀) :
                                                            (probEvent ((simulateQ impl A).run h) fun (z : α × Heap Ident₀) => r.get z.2 r.get h) = 0
                                                            theorem VCVio.StateSeparating.OracleComp.simulateQ_run_cellUnchanged_prob_eq_sub_probFailure {ι : Type uι} {spec : OracleSpec ι} {α : Type (max u₀ v)} {Ident₀ : Type u₀} [CellSpec Ident₀] {m : Type (max u₀ v) → Type u_1} [Monad m] [LawfulMonad m] [HasEvalSPMF m] (impl : QueryImpl spec (StateT (Heap Ident₀) m)) (r : CellRef Ident₀) (himpl : QueryImpl.PreservesCell impl r) (A : OracleComp spec α) (h : Heap Ident₀) :
                                                            (probEvent ((simulateQ impl A).run h) fun (z : α × Heap Ident₀) => r.get z.2 = r.get h) = 1 - Pr[⊥ | (simulateQ impl A).run h]
                                                            theorem VCVio.StateSeparating.OracleComp.simulateQ_run_cellUnchanged_prob_eq_one_of_probFailure_eq_zero {ι : Type uι} {spec : OracleSpec ι} {α : Type (max u₀ v)} {Ident₀ : Type u₀} [CellSpec Ident₀] {m : Type (max u₀ v) → Type u_1} [Monad m] [LawfulMonad m] [HasEvalSPMF m] (impl : QueryImpl spec (StateT (Heap Ident₀) m)) (r : CellRef Ident₀) (himpl : QueryImpl.PreservesCell impl r) (A : OracleComp spec α) (h : Heap Ident₀) (hnf : Pr[⊥ | (simulateQ impl A).run h] = 0) :
                                                            (probEvent ((simulateQ impl A).run h) fun (z : α × Heap Ident₀) => r.get z.2 = r.get h) = 1
                                                            theorem VCVio.StateSeparating.OracleComp.simulateQ_run_cellUnchanged_prob_eq_one {ι : Type uι} {spec : OracleSpec ι} {α : Type (max u₀ v)} {Ident₀ : Type u₀} [CellSpec Ident₀] {m : Type (max u₀ v) → Type u_1} [Monad m] [LawfulMonad m] [HasEvalPMF m] (impl : QueryImpl spec (StateT (Heap Ident₀) m)) (r : CellRef Ident₀) (himpl : QueryImpl.PreservesCell impl r) (A : OracleComp spec α) (h : Heap Ident₀) :
                                                            (probEvent ((simulateQ impl A).run h) fun (z : α × Heap Ident₀) => r.get z.2 = r.get h) = 1
                                                            theorem VCVio.StateSeparating.QueryImpl.CellWriteFootprint.simulateQ_run_cellPreserved {ι : Type uι} {spec : OracleSpec ι} {α : Type (max u₀ v)} {Ident₀ : Type u₀} [CellSpec Ident₀] {m : Type (max u₀ v) → Type u_1} [Monad m] [LawfulMonad m] [HasEvalSet m] {impl : QueryImpl spec (StateT (Heap Ident₀) m)} (footprint : CellWriteFootprint impl) (r : CellRef Ident₀) (hr : ∀ (t : spec.Domain), r.idfootprint.writes t) (A : OracleComp spec α) (h : Heap Ident₀) (z : α × Heap Ident₀) :
                                                            z support ((simulateQ impl A).run h)r.get z.2 = r.get h

                                                            A query-implementation cell-write footprint lifts through interpretation: if a cell is outside every per-query footprint, the interpreted computation preserves that cell.

                                                            theorem VCVio.StateSeparating.QueryImpl.CellWriteFootprint.simulateQ_run_cellChange_prob_eq_zero {ι : Type uι} {spec : OracleSpec ι} {α : Type (max u₀ v)} {Ident₀ : Type u₀} [CellSpec Ident₀] {m : Type (max u₀ v) → Type u_2} [Monad m] [LawfulMonad m] [HasEvalSPMF m] {impl : QueryImpl spec (StateT (Heap Ident₀) m)} (footprint : CellWriteFootprint impl) (r : CellRef Ident₀) (hr : ∀ (t : spec.Domain), r.idfootprint.writes t) (A : OracleComp spec α) (h : Heap Ident₀) :
                                                            (probEvent ((simulateQ impl A).run h) fun (z : α × Heap Ident₀) => r.get z.2 r.get h) = 0
                                                            theorem VCVio.StateSeparating.QueryImpl.CellWriteFootprint.simulateQ_run_cellUnchanged_prob_eq_sub_probFailure {ι : Type uι} {spec : OracleSpec ι} {α : Type (max u₀ v)} {Ident₀ : Type u₀} [CellSpec Ident₀] {m : Type (max u₀ v) → Type u_2} [Monad m] [LawfulMonad m] [HasEvalSPMF m] {impl : QueryImpl spec (StateT (Heap Ident₀) m)} (footprint : CellWriteFootprint impl) (r : CellRef Ident₀) (hr : ∀ (t : spec.Domain), r.idfootprint.writes t) (A : OracleComp spec α) (h : Heap Ident₀) :
                                                            (probEvent ((simulateQ impl A).run h) fun (z : α × Heap Ident₀) => r.get z.2 = r.get h) = 1 - Pr[⊥ | (simulateQ impl A).run h]
                                                            theorem VCVio.StateSeparating.QueryImpl.CellWriteFootprint.simulateQ_run_cellUnchanged_prob_eq_one_of_probFailure_eq_zero {ι : Type uι} {spec : OracleSpec ι} {α : Type (max u₀ v)} {Ident₀ : Type u₀} [CellSpec Ident₀] {m : Type (max u₀ v) → Type u_2} [Monad m] [LawfulMonad m] [HasEvalSPMF m] {impl : QueryImpl spec (StateT (Heap Ident₀) m)} (footprint : CellWriteFootprint impl) (r : CellRef Ident₀) (hr : ∀ (t : spec.Domain), r.idfootprint.writes t) (A : OracleComp spec α) (h : Heap Ident₀) (hnf : Pr[⊥ | (simulateQ impl A).run h] = 0) :
                                                            (probEvent ((simulateQ impl A).run h) fun (z : α × Heap Ident₀) => r.get z.2 = r.get h) = 1
                                                            theorem VCVio.StateSeparating.QueryImpl.CellWriteFootprint.simulateQ_run_cellUnchanged_prob_eq_one {ι : Type uι} {spec : OracleSpec ι} {α : Type (max u₀ v)} {Ident₀ : Type u₀} [CellSpec Ident₀] {m : Type (max u₀ v) → Type u_2} [Monad m] [LawfulMonad m] [HasEvalPMF m] {impl : QueryImpl spec (StateT (Heap Ident₀) m)} (footprint : CellWriteFootprint impl) (r : CellRef Ident₀) (hr : ∀ (t : spec.Domain), r.idfootprint.writes t) (A : OracleComp spec α) (h : Heap Ident₀) :
                                                            (probEvent ((simulateQ impl A).run h) fun (z : α × Heap Ident₀) => r.get z.2 = r.get h) = 1

                                                            Examples #

                                                            Three toy cells: a log counter, a cache counter, and an immutable flag.

                                                            Instances For

                                                              Query-handler write footprints #

                                                              A tiny external oracle interface for the support-based footprint demo.

                                                              Instances For

                                                                Every demo query returns unit; the interesting part is the heap effect.

                                                                Instances For

                                                                  A toy probabilistic handler with heap effects. Two branches write cells, and one branch reads the flag without modifying it.

                                                                  Instances For

                                                                    Per-query write footprint for demoImpl.

                                                                    Instances For

                                                                      Pack the handler-level footprint once, so later proofs need not unfold every query branch.

                                                                      Instances For

                                                                        The flag is outside every branch footprint, so each handler step preserves it.

                                                                        A tiny client computation that calls several branches of the demo handler.

                                                                        Instances For

                                                                          The handler footprint automatically lifts through simulateQ: the whole interpreted computation preserves the flag, not just a single query branch.

                                                                          Increment the cache counter and append one log entry. The program never writes flagRef.

                                                                          Instances For

                                                                            A compositional footprint for cacheAndLogStep. Reads contribute no writes, writes contribute singleton footprints, and binds union the footprints.

                                                                            Instances For

                                                                              The compositional footprint gives flag preservation without unfolding each state update in the final proof.

                                                                              A smaller example that uses the generic frame combinators directly: two writes outside the flag cell preserve the flag.

                                                                              Instances For

                                                                                A compositional footprint for the two-write program. The write set is computed by WriteFootprint.bind: first {cache}, then {log}.

                                                                                Instances For

                                                                                  Once the footprint says the write set is {cache, log}, flag preservation is a one-line frame application plus a membership proof.