| |
| |
| |
| |
| |
|
|
| 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) |
|
|
| |
| |
| |
|
|
| |
| record GateMatrix : Set where |
| field |
| entry_1_1 : β |
| entry_1_2 : β |
| entry_2_1 : β |
| entry_2_2 : β |
| is_unitary : Bool |
|
|
| |
| record GateContext : Set where |
| field |
| state : QuantumState |
| gate : GateMatrix |
| qubit_index : β |
| num_qubits : β |
| dim : β |
| bit_mask : β |
|
|
| |
| |
| |
|
|
| record GateLoopState : Set where |
| field |
| ctx : GateContext |
| i : β |
| |
| num_amplitudes_processed : β |
| num_pairs_updated : β |
| |
| last_state_0_qubit_0 : Bool |
| error_status : β |
|
|
| |
| |
| |
|
|
| record GateInvariant (s : GateLoopState) (i : β) : Set where |
| field |
| |
| h_i_in_range : i β€ GateContext.dim (GateLoopState.ctx s) |
|
|
| |
| h_state_valid : isValidDim (GateContext.state (GateLoopState.ctx s)) |
|
|
| |
| h_state_can_apply : canApplyGate (GateContext.state (GateLoopState.ctx s)) |
|
|
| |
| h_gate_unitary : GateMatrix.is_unitary (GateContext.gate (GateLoopState.ctx s)) β‘ true |
|
|
| |
| h_qubit_valid : qubitIndexValid (GateContext.qubit_index (GateLoopState.ctx s)) (GateContext.num_qubits (GateLoopState.ctx s)) |
|
|
| |
| h_states_examined : GateLoopState.num_amplitudes_processed s β‘ i |
|
|
| |
| |
| 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 β |
| |
| (GateLoopState.num_pairs_updated s β₯ (j / (2 * GateContext.bit_mask (GateLoopState.ctx s))) + 1) |
|
|
| |
| h_dim_preserved : dimensionPreserved (GateContext.dim (GateLoopState.ctx s)) (β.logβ (GateContext.dim (GateLoopState.ctx s))) |
|
|
| |
| h_ctx_immutable : β j β j < i β GateContext.gate (GateLoopState.ctx s) β‘ GateContext.gate (GateLoopState.ctx s) |
|
|
| |
| h_error_clear : GateLoopState.error_status s β‘ 0 |
|
|
| |
| |
| |
|
|
| 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 _ () |
|
|
| |
| |
| |
|
|
| |
| record GateIterationStep (s s' : GateLoopState) : Set where |
| fields |
| -- Context unchanged |
| ctx_same : GateLoopState.ctx s β‘ GateLoopState.ctx s' |
|
|
| |
| 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_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 : Bool |
|
|
| |
| 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 |
| β© |
| |