{-# OPTIONS --safe --cubical-compatible --guardedness --exact-split --double-check #-}
module ALMA.Base.Equivalence.LinearDynamics where
open import Agda.Primitive using (lzero)
open import Agda.Builtin.Equality using (_≡_; refl)
open import Agda.Builtin.Sigma using (Σ; _,_)
open import Data.Unit.Polymorphic.Base using (⊤; tt)
open import Data.Nat.Base using (ℕ; zero; suc; _+_; _≤_; z≤n; s≤s; _<_)
open import Data.Nat.Properties using (+-comm; +-identityʳ; +-suc)
open import Data.Product.Base using (proj₁; proj₂; _×_)
open import Relation.Binary.PropositionalEquality.Core using (sym; trans; cong)
open import Relation.Binary.Structures using (IsEquivalence)
open import Relation.Binary.PropositionalEquality.Properties using (module ≡-Reasoning)
open ≡-Reasoning
open import ALMA.Base.IndexedMType using (snd)
open import ALMA.Base.Equivalence.ScaleInvariant using (ScaleInvariant)
LinearDynamics : {a : _} {X : Set a} → (f : X → X) → X → X → Set lzero
LinearDynamics {a} {X} f = ScaleInvariant {Obs = ⊤ {lzero}} (λ x _ → f x)
module Iteration
{a : _} {X : Set a}
(f : X → X) where
_^[_] : X → ℕ → X
x ^[ zero ] = x
x ^[ suc n ] = f (x ^[ n ])
^-zero : ∀ x → x ^[ 0 ] ≡ x
^-zero x = refl
^-suc : ∀ x n → x ^[ suc n ] ≡ f (x ^[ n ])
^-suc x n = refl
^-suc-shift : ∀ x n → x ^[ suc n ] ≡ (f x) ^[ n ]
^-suc-shift x zero = refl
^-suc-shift x (suc n) = cong f (^-suc-shift x n)
^-+ : ∀ x m n → x ^[ m + n ] ≡ (x ^[ m ]) ^[ n ]
^-+ x m zero = cong (λ k → x ^[ k ]) (+-identityʳ m)
^-+ x m (suc n) = begin
x ^[ m + suc n ]
≡⟨ cong (λ k → x ^[ k ]) (+-suc m n) ⟩
x ^[ suc (m + n) ]
≡⟨ refl ⟩
f (x ^[ m + n ])
≡⟨ cong f (^-+ x m n) ⟩
f ((x ^[ m ]) ^[ n ])
≡⟨ refl ⟩
(x ^[ m ]) ^[ suc n ]
∎
module Coalgebra
{a : _} {X : Set a}
(f : X → X) where
open Iteration f
Sync : X → X → Set a
Sync x y = ∀ n → x ^[ n ] ≡ y ^[ n ]
sync-isEquivalence : IsEquivalence Sync
sync-isEquivalence = record
{ refl = λ {x} n → refl
; sym = λ p n → sym (p n)
; trans = λ p q n → trans (p n) (q n)
}
sync-char : ∀ {x y} → Sync x y → (x ≡ y) × Sync (f x) (f y)
sync-char {x} {y} p =
p 0 ,
(λ n → begin
(f x) ^[ n ]
≡⟨ sym (^-suc-shift x n) ⟩
x ^[ suc n ]
≡⟨ p (suc n) ⟩
y ^[ suc n ]
≡⟨ ^-suc-shift y n ⟩
(f y) ^[ n ]
∎)
sync-intro : ∀ {x y} → x ≡ y → Sync (f x) (f y) → Sync x y
sync-intro {x} {y} refl q zero = refl
sync-intro {x} {y} refl q (suc n) = begin
x ^[ suc n ]
≡⟨ ^-suc-shift x n ⟩
(f x) ^[ n ]
≡⟨ q n ⟩
(f y) ^[ n ]
≡⟨ sym (^-suc-shift y n) ⟩
y ^[ suc n ]
∎
sync-final
: (R : X → X → Set a)
→ (∀ {x y} → R x y → (x ≡ y) × R (f x) (f y))
→ ∀ {x y} → R x y → Sync x y
sync-final R step {x} {y} r zero = proj₁ (step r)
sync-final R step {x} {y} r (suc n) = begin
x ^[ suc n ]
≡⟨ ^-suc-shift x n ⟩
(f x) ^[ n ]
≡⟨ sync-final R step (proj₂ (step r)) n ⟩
(f y) ^[ n ]
≡⟨ sym (^-suc-shift y n) ⟩
y ^[ suc n ]
∎
sync-refl : ∀ x → Sync x x
sync-refl x = IsEquivalence.refl sync-isEquivalence
IsFixed : X → Set a
IsFixed x = f x ≡ x
IsPeriodic : X → Set a
IsPeriodic x = Σ ℕ (λ n → Σ (0 < n) (λ _ → x ^[ n ] ≡ x))
fixed→periodic : ∀ {x} → IsFixed x → IsPeriodic x
fixed→periodic {x} fx = 1 , (s≤s z≤n , fx)
periodic-stable
: ∀ {x} → IsPeriodic x
→ Σ ℕ (λ p → Σ (0 < p) (λ _ → ∀ k → (x ^[ k ]) ^[ p ] ≡ x ^[ k ]))
periodic-stable {x} (p , 0<p , eq) = p , 0<p , period-iter
where
period-iter : ∀ k → (x ^[ k ]) ^[ p ] ≡ x ^[ k ]
period-iter k = begin
(x ^[ k ]) ^[ p ]
≡⟨ sym (^-+ x k p) ⟩
x ^[ k + p ]
≡⟨ cong (λ j → x ^[ j ]) (+-comm k p) ⟩
x ^[ p + k ]
≡⟨ ^-+ x p k ⟩
(x ^[ p ]) ^[ k ]
≡⟨ cong (λ z → z ^[ k ]) eq ⟩
x ^[ k ]
∎
periodic-iterate
: ∀ {x} → IsPeriodic x
→ Σ ℕ (λ p → Σ (0 < p) (λ _ → ∀ n → x ^[ n + p ] ≡ x ^[ n ]))
periodic-iterate {x} per with periodic-stable {x} per
... | p , 0<p , iter = p , 0<p , period-law
where
period-law : ∀ n → x ^[ n + p ] ≡ x ^[ n ]
period-law n = begin
x ^[ n + p ]
≡⟨ ^-+ x n p ⟩
(x ^[ n ]) ^[ p ]
≡⟨ iter n ⟩
x ^[ n ]
∎
module LinearDynamics-Depth
{a : _} {X : Set a} {f : X → X} where
LD-depth : (n : ℕ) → (x y : X) → Set lzero
LD-depth zero x y = ⊤ {lzero}
LD-depth (suc n) x y = LD-depth n (f x) (f y)
ld→LD-depth : ∀ {x y} → LinearDynamics f x y
→ ∀ n → LD-depth n x y
ld→LD-depth p zero = tt
ld→LD-depth p (suc n) = ld→LD-depth (p .snd tt) n
LD-depth-mono : ∀ {m n} (m≤n : m ≤ n) {x y : X}
→ LD-depth n x y → LD-depth m x y
LD-depth-mono z≤n p = tt
LD-depth-mono (s≤s m≤n) {x} {y} p =
LD-depth-mono m≤n {x = f x} {y = f y} p