File size: 10,105 Bytes
9425aed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
-- Loop Invariant: apply_single_qubit_gate
-- BOB Quantum Kernel β€” Single-Qubit Gate Application
-- Loop: do i = 0, state%dim - 1
-- Phase 2: Formal Structure (no proofs yet)
-- WORM-sealed observable bookkeeping

module Invariants.GateApplicationLoop where

open import Data.Nat using (β„•; _+_; _≀_; _<_; _β‰₯_; _≑_; zero; suc)
open import Data.Real using (ℝ; _+_; _*_; _-_; _<_; _≀_; _β‰₯_)
open import Data.Bool using (Bool; true; false)
open import Relation.Binary.PropositionalEquality using (_≑_; refl; cong)
open import Core.ErrorCode using (ErrorCode; BOB_SUCCESS)
open import Core.QuantumState using (QuantumState; Dimension; isValidDim; canApplyGate)
open import Core.Predicates using (basisStateInRange; qubitIndexValid; dimensionPreserved)
open import Core.BitCounting using (gate_exit_pairs_count; pairs_updated_j_equals_i)

-- ============================================================================
-- Loop Context: Gate Application Setup
-- ============================================================================

-- Gate matrix (2Γ—2)
record GateMatrix : Set where
  field
    entry_1_1 : β„‚  -- top-left
    entry_1_2 : β„‚  -- top-right
    entry_2_1 : β„‚  -- bottom-left
    entry_2_2 : β„‚  -- bottom-right
    is_unitary : Bool  -- verified in apply_single_qubit_gate precondition

-- Immutable context throughout loop
record GateContext : Set where
  field
    state : QuantumState         -- being mutated
    gate : GateMatrix            -- immutable operator
    qubit_index : β„•              -- target qubit (immutable)
    num_qubits : β„•               -- from state dimension
    dim : β„•                       -- state%dim (2^num_qubits)
    bit_mask : β„•                 -- precomputed: 1 << qubit_index

-- ============================================================================
-- Loop State at iteration i
-- ============================================================================

record GateLoopState : Set where
  field
    ctx : GateContext
    i : β„•                         -- basis state iterator [0, dim)
    -- Tracking updates
    num_amplitudes_processed : β„•  -- how many basis states examined
    num_pairs_updated : β„•         -- number of (state_0, state_1) pairs updated
    -- Gate application bookkeeping
    last_state_0_qubit_0 : Bool   -- was last examined state's qubit bit 0?
    error_status : β„•              -- 0 = BOB_SUCCESS

-- ============================================================================
-- Loop Invariant: What holds at each iteration i?
-- ============================================================================

record GateInvariant (s : GateLoopState) (i : β„•) : Set where
  field
    -- 1. Loop iterator in valid range: 0 ≀ i ≀ dim
    h_i_in_range : i ≀ GateContext.dim (GateLoopState.ctx s)

    -- 2. State remains valid
    h_state_valid : isValidDim (GateContext.state (GateLoopState.ctx s))

    -- 3. State can have gates applied
    h_state_can_apply : canApplyGate (GateContext.state (GateLoopState.ctx s))

    -- 4. Gate matrix is unitary (verified precondition)
    h_gate_unitary : GateMatrix.is_unitary (GateContext.gate (GateLoopState.ctx s)) ≑ true

    -- 5. Qubit index is valid
    h_qubit_valid : qubitIndexValid (GateContext.qubit_index (GateLoopState.ctx s)) (GateContext.num_qubits (GateLoopState.ctx s))

    -- 6. Number of basis states examined = i
    h_states_examined : GateLoopState.num_amplitudes_processed s ≑ i

    -- 7. For each processed basis state i where qubit bit is 0,
    --    the (state_0, state_1) pair has been updated
    h_pairs_updated :
      βˆ€ (j : β„•) β†’
      j < i β†’
      let qubit_bit = (j mod (2 * GateContext.bit_mask (GateLoopState.ctx s))) / GateContext.bit_mask (GateLoopState.ctx s)
      in qubit_bit ≑ 0 β†’
      -- Then: this pair was processed
      (GateLoopState.num_pairs_updated s β‰₯ (j / (2 * GateContext.bit_mask (GateLoopState.ctx s))) + 1)

    -- 8. Dimension preserved
    h_dim_preserved : dimensionPreserved (GateContext.dim (GateLoopState.ctx s)) (β„•.logβ‚‚ (GateContext.dim (GateLoopState.ctx s)))

    -- 9. Gate context unchanged
    h_ctx_immutable : βˆ€ j β†’ j < i β†’ GateContext.gate (GateLoopState.ctx s) ≑ GateContext.gate (GateLoopState.ctx s)

    -- 10. No errors
    h_error_clear : GateLoopState.error_status s ≑ 0

-- ============================================================================
-- Base Case: i = 0 (before loop starts)
-- ============================================================================

gate_base :
  (s : GateLoopState) β†’
  GateLoopState.i s ≑ 0 β†’
  isValidDim (GateContext.state (GateLoopState.ctx s)) β†’
  canApplyGate (GateContext.state (GateLoopState.ctx s)) β†’
  GateMatrix.is_unitary (GateContext.gate (GateLoopState.ctx s)) ≑ true β†’
  qubitIndexValid (GateContext.qubit_index (GateLoopState.ctx s)) (GateContext.num_qubits (GateLoopState.ctx s)) β†’
  GateLoopState.num_amplitudes_processed s ≑ 0 β†’
  GateLoopState.num_pairs_updated s ≑ 0 β†’
  GateLoopState.error_status s ≑ 0 β†’
  GateInvariant s 0

gate_base s h_i h_state_valid h_can_apply h_unitary h_qubit h_examined h_pairs h_error =
  record
    { h_i_in_range = zero
    ; h_state_valid = h_state_valid
    ; h_state_can_apply = h_can_apply
    ; h_gate_unitary = h_unitary
    ; h_qubit_valid = h_qubit
    ; h_states_examined = h_examined
    ; h_pairs_updated = Ξ» j h_j_lt_zero _ β†’ absurd (Β¬(<-zero j) h_j_lt_zero)
    ; h_dim_preserved = refl
    ; h_ctx_immutable = Ξ» j h_j_lt_zero β†’ absurd (Β¬(<-zero j) h_j_lt_zero)
    ; h_error_clear = h_error
    }
  where
    Β¬(<-zero : βˆ€ n β†’ Β¬(n < 0)
    Β¬(<-zero _ ()

-- ============================================================================
-- Inductive Step: i β†’ i+1
-- ============================================================================

-- One iteration of basis state processing
record GateIterationStep (s s' : GateLoopState) : Set where
  fields
    -- Context unchanged
    ctx_same : GateLoopState.ctx s ≑ GateLoopState.ctx s'

    -- Basis state iterator increments
    i_increments : GateLoopState.i s' ≑ GateLoopState.i s + 1

    -- Amplitudes processed count incremented
    states_processed_incremented : GateLoopState.num_amplitudes_processed s' ≑ GateLoopState.num_amplitudes_processed s + 1

    -- Pairs updated: either incremented or unchanged
    --   (incremented if this basis state's qubit bit was 0)
    pairs_updated_invariant :
      let i = GateLoopState.i s
          qubit_bit = (i mod (2 * GateContext.bit_mask (GateLoopState.ctx s))) / GateContext.bit_mask (GateLoopState.ctx s)
      in (qubit_bit ≑ 0 β†’
          GateLoopState.num_pairs_updated s' ≑ GateLoopState.num_pairs_updated s + 1) ∧
         (qubit_bit β‰  0 β†’
          GateLoopState.num_pairs_updated s' ≑ GateLoopState.num_pairs_updated s)

    -- new_amplitudes written for this iteration
    new_amplitudes_written : Bool

    -- No errors during iteration
    error_unchanged : GateLoopState.error_status s' ≑ 0

-- Inductive step
gate_step :
  (s s' : GateLoopState) (i : β„•) β†’
  GateInvariant s i β†’
  GateIterationStep s s' β†’
  GateInvariant s' (i + 1)

gate_step s s' i inv_i step =
  record
    { h_i_in_range = Nat.succ_le_of_lt (by-i-lt-dim-from-invariant inv_i)
    ; h_state_valid = GateInvariant.h_state_valid inv_i
    ; h_state_can_apply = GateInvariant.h_state_can_apply inv_i
    ; h_gate_unitary = GateInvariant.h_gate_unitary inv_i
    ; h_qubit_valid = GateInvariant.h_qubit_valid inv_i
    ; h_states_examined = cong suc (GateInvariant.h_states_examined inv_i)
    ; h_pairs_updated = Ξ» j h_j_lt_suc_i h_qubit_zero β†’
        let h_j_le_i = <-to-≀ h_j_lt_suc_i
        in case (decide (j ≑ i)) of Ξ» where
             (yes p) β†’
               -- j = i, and qubit_bit = 0, so this pair just got updated
               let (h_pairs_inc, _) = GateIterationStep.pairs_updated_invariant step
                   h_pairs_pred = h_pairs_inc h_qubit_zero
               in pairs_updated_j_equals_i i (GateContext.bit_mask (GateLoopState.ctx s)) h_qubit_zero
                    (Ξ» pairs β†’ h_pairs_pred)
             (no Β¬p) β†’
               -- j < i, use previous invariant
               let h_j_lt_i = ≀-to-< h_j_le_i Β¬p
               in GateInvariant.h_pairs_updated inv_i j h_j_lt_i h_qubit_zero
    ; h_dim_preserved = GateInvariant.h_dim_preserved inv_i
    ; h_ctx_immutable = Ξ» j h_j_lt β†’ GateInvariant.h_ctx_immutable inv_i j (≀-to-< (<-to-≀ h_j_lt) (by-step-i-increments))
    ; h_error_clear = GateIterationStep.error_unchanged step
    }

-- ============================================================================
-- Exit Condition: Loop termination (i = dim)
-- ============================================================================

-- All basis states processed
gate_exit :
  (s : GateLoopState) (i : β„•) β†’
  GateInvariant s i β†’
  i ≑ GateContext.dim (GateLoopState.ctx s) β†’
  -- Then:
  -- 1. All basis states examined
  (GateLoopState.num_amplitudes_processed s ≑ GateContext.dim (GateLoopState.ctx s)) ∧
  -- 2. All valid (state_0, state_1) pairs updated
  (GateLoopState.num_pairs_updated s ≑ GateContext.dim (GateLoopState.ctx s) / 2) ∧
  -- 3. new_amplitudes array complete and ready to swap
  (βˆ€ (i : β„•) β†’ i < GateContext.dim (GateLoopState.ctx s) β†’ basisStateInRange i (GateContext.dim (GateLoopState.ctx s))) ∧
  -- 4. No errors
  (GateLoopState.error_status s ≑ 0) ∧
  -- 5. State dimension preserved
  (dimensionPreserved (GateContext.dim (GateLoopState.ctx s)) (GateContext.dim (GateLoopState.ctx s)))

gate_exit s i inv_i h_done =
  ⟨ trans (GateInvariant.h_states_examined inv_i) h_done
  , gate_exit_pairs_count i (GateContext.dim (GateLoopState.ctx s))
      (GateContext.bit_mask (GateLoopState.ctx s)) h_done
      (by-dim-is-power-of-2)
      (GateLoopState.num_pairs_updated s)
  , Ξ» j h_j_lt β†’
      basisStateInRange j (GateContext.dim (GateLoopState.ctx s))
  , GateInvariant.h_error_clear inv_i
  , refl
  ⟩