module HoareLogic.Examples.Miscellaneous where open import DynamicallyChecked.Utilities open import DynamicallyChecked.Partiality open import DynamicallyChecked.Universe open import DynamicallyChecked.Rearrangement open import DynamicallyChecked.BiGUL open import HoareLogic.Semantics open import HoareLogic.Triple open import HoareLogic.Utilities open import Function open import Data.Empty open import Data.Product as Product open import Data.Sum as Sum open import Data.Bool open import Data.Maybe open import Data.Nat as Nat open import Data.Fin open import Data.List open import Relation.Nullary open import Relation.Nullary.Decidable open import Relation.Binary open import Relation.Binary.PropositionalEquality emb : {n : ℕ} {F : Functor n} {S V : U n} → (⟦ S ⟧ (μ F) → ⟦ V ⟧ (μ F)) → (⟦ S ⟧ (μ F) → ⟦ V ⟧ (μ F) → ⟦ S ⟧ (μ F)) → BiGUL F S V emb {V = V} g p = case (((λ s v → ⌊ U-dec V (g s) v ⌋) , normal (skip g) (λ _ → true)) ∷ ((λ _ _ → true) , adaptive p) ∷ []) emb-correctness : {n : ℕ} {F : Functor n} {S V : U n} (g : ⟦ S ⟧ (μ F) → ⟦ V ⟧ (μ F)) (p : ⟦ S ⟧ (μ F) → ⟦ V ⟧ (μ F) → ⟦ S ⟧ (μ F)) → ({s : ⟦ S ⟧ (μ F)} {v : ⟦ V ⟧ (μ F)} → g (p s v) ≡ v) → Triple Π (emb {F = F} {S} {V} g p) (λ { (s' , s , v) → g s' ≡ v × (g s ≡ v → s' ≡ s) × (g s ≢ v → s' ≡ p s v) }) emb-correctness g p PutGet = case (conseq (λ { (_ , eqn , _) → trueToWitness eqn }) skip (λ { {.s , s , v} (refl , _ , eqn , _) → (trueToWitness eqn , (λ _ → refl) , (λ g-s≢v → ⊥-elim (g-s≢v (trueToWitness eqn)))) , (eqn , tt) , refl , tt }) ∷ᴺ (λ { s v (_ , _ , feqn , _) → (tt , inj₁ (trueFromWitness PutGet)) , λ { s' (g-s'≡v , PutGet⇒s'≡p-s-v , _) → g-s'≡v , (λ g-s≡v → ⊥-elim (falseToWitness feqn g-s≡v)) , (λ _ → PutGet⇒s'≡p-s-v PutGet) } }) ∷ᴬ []) (λ _ → inj₂ (inj₁ refl)) emb-correctness' : {n : ℕ} {F : Functor n} {S V : U n} (g : ⟦ S ⟧ (μ F) → ⟦ V ⟧ (μ F)) (p : ⟦ S ⟧ (μ F) → ⟦ V ⟧ (μ F) → ⟦ S ⟧ (μ F)) → ({s : ⟦ S ⟧ (μ F)} {v : ⟦ V ⟧ (μ F)} → g (p s v) ≡ v) → ({s : ⟦ S ⟧ (μ F)} → p s (g s) ≡ s) → Triple Π (emb {F = F} {S} {V} g p) (λ { (s' , s , v) → s' ≡ p s v }) emb-correctness' g p PutGet GetPut = case (conseq (λ { (_ , eqn , _) → trueToWitness eqn }) skip (λ { {.s , s , v} (refl , _ , eqn , _) → trans (sym GetPut) (cong (p s) (trueToWitness eqn)) , (eqn , tt) , refl , tt }) ∷ᴺ (λ { s v (_ , _ , neqn , _) → (tt , inj₁ (trueFromWitness PutGet)) , (λ s' eq → trans eq (trans (cong (p (p s v)) (sym PutGet)) GetPut)) }) ∷ᴬ []) (λ _ → inj₂ (inj₁ refl)) emb-range : {n : ℕ} {F : Functor n} {S V : U n} (g : ⟦ S ⟧ (μ F) → ⟦ V ⟧ (μ F)) (p : ⟦ S ⟧ (μ F) → ⟦ V ⟧ (μ F) → ⟦ S ⟧ (μ F)) → TripleR Π (emb {F = F} {S} {V} g p) Π emb-range g p = conseq (λ _ → tt) (case ((conseq (λ { (eq , _) → tt , trueFromWitness eq , tt }) skip id) ∷ᴺ •∷ᴬ [])) (λ _ → inj₁ (tt , refl , tt)) eqCheck : {n : ℕ} {F : Functor n} {A : U n} → BiGUL F A (A ⊗ A) eqCheck = rearrS var (prod var var) (refl , refl) (return refl) replace eqCheck-correctness : {n : ℕ} {F : Functor n} {A : U n} → Triple (λ { (_ , (v , w)) → v ≡ w }) (eqCheck {F = F} {A}) (λ { (s' , _ , (v , w)) → s' ≡ v × s' ≡ w }) eqCheck-correctness = conseq (λ { {s , (v , w)} v≡w → s , refl , v≡w }) (rearrS (λ { (_ , (v , w)) → v ≡ w }) (λ { (s' , _ , (v , w)) → s' ≡ v × s' ≡ w }) (conseq (λ _ → tt) replace (λ { {._ , (s , t) , (v , w)} (refl , u , (u≡s , u≡t) , v≡w) → (v , u) , (refl , v≡w) , (refl , v≡w) , (u≡s , u≡t) }))) (λ { {s' , s , (v , w)} (((u , _) , (u≡v , u≡w) , s'≡u , _) , v≡w) → trans s'≡u u≡v , trans s'≡u u≡w }) eqCheck-range : {n : ℕ} {F : Functor n} {A : U n} → TripleR (λ { (_ , (v , w)) → v ≡ w }) (eqCheck {F = F} {A}) Π eqCheck-range = conseq (λ { {s , (v , w)} ((_ , _ , v≡w) , _) → v≡w }) (rearrS (λ { (_ , (v , w)) → v ≡ w }) (λ _ → ⊤) (conseq (λ { {(s , t) , (v , w)} (st≡vw , u , _ , u≡s , u≡t) → u , (u≡s , u≡t) , trans (sym (trans u≡s (cong proj₁ st≡vw))) (trans u≡t (cong proj₂ st≡vw)) }) replace (λ _ → tt))) (λ _ → _ , tt , refl) emptyF : Functor 0 emptyF () kℕ : U 0 kℕ = k ℕ Nat._≟_ replace² : BiGUL emptyF (kℕ ⊗ kℕ) (kℕ ⊗ kℕ) replace² = prod replace replace replace²-correctness : Triple Π replace² (λ { ((s' , t') , _ , (v , w)) → s' ≡ v × t' ≡ w }) replace²-correctness = conseq (λ _ → tt , tt) (prod replace replace) proj₁ replace²-range : TripleR Π replace² Π replace²-range = conseq (λ _ → tt) (prod replace replace) (λ _ → tt , tt) replace²-equal-view-correctness : Triple (uncurry _≡_ ∘ proj₂) replace² (uncurry _≡_ ∘ proj₁ ∩ uncurry _≡_ ∘ Product.map id proj₂) replace²-equal-view-correctness = conseq (λ _ → tt , tt) (prod replace replace) (λ { {(x' , y') , (x , y) , (z , w)} ((x'≡z , y'≡w) , z≡w) → trans x'≡z (trans z≡w (sym y'≡w)) , cong₂ _,_ x'≡z y'≡w }) replace²-equal-view-range : TripleR (uncurry _≡_ ∘ proj₂) replace² (uncurry _≡_) replace²-equal-view-range = conseq (λ { {(s , t) , (v , w)} ((s≡v , t≡w) , s≡t) → trans (sym s≡v) (trans s≡t t≡w) }) (prod replace replace) (λ _ → tt , tt) keepHeight : BiGUL emptyF (kℕ ⊗ kℕ) kℕ keepHeight = rearrV var (prod {H = one} var (k tt)) (refl , tt) (return refl) (prod replace (skip (const tt))) keepHeight-correctness : Triple Π keepHeight (λ { ((w' , h') , (_ , h) , v) → w' ≡ v × h' ≡ h }) keepHeight-correctness = conseq (λ _ → _ , tt , refl) (rearrV Π (λ { ((w' , h') , (_ , h) , v) → w' ≡ v × h' ≡ h }) (conseq (λ _ → tt , refl) (prod replace skip) (λ { {(.v , .h) , (w , h) , (v , _)} ((refl , refl) , _) → _ , (refl , refl) , refl , refl }))) (λ { {(w' , .h) , (w , h) , v} ((._ , (eq , refl) , refl) , _) → eq , refl }) keepHeight-range : TripleR Π keepHeight Π keepHeight-range = conseq (λ _ → tt) (rearrV Π (conseq (λ _ → _ , tt , refl , refl) (prod replace skip) (λ { tt → tt , tt }))) id produceSquare : BiGUL emptyF (kℕ ⊗ kℕ) kℕ produceSquare = case (((λ { (w , _) v → ⌊ w Nat.≟ v ⌋ }) , normal (skip proj₁) (const true)) ∷ (((λ _ _ → true) , adaptive (λ { _ v → (v , v) }))) ∷ []) produceSquare-correctness : Triple Π produceSquare (λ { ((w' , h') , (w , h) , v) → w' ≡ v × (w ≡ v → h' ≡ h) × (w ≢ v → w' ≡ h') }) produceSquare-correctness = case ((conseq (λ { {(w , h) , v} (_ , e , _) → trueToWitness e }) skip (λ { {.(w , h) , (w , h) , v} (refl , _ , e , _) → (trueToWitness e , (λ _ → refl) , (λ w≢v → ⊥-elim (w≢v (trueToWitness e)))) , (e , tt) , refl , tt })) ∷ᴺ (λ { (w , h) v (tt , _ , ne , _) → (tt , inj₁ (trueFromWitness refl)) , λ { (w' , h') (w'≡v , v≡v→h'≡v , _) → w'≡v , (λ w≡v → ⊥-elim (falseToWitness ne w≡v)) , (λ _ → trans w'≡v (sym (v≡v→h'≡v refl))) } }) ∷ᴬ []) (λ _ → inj₂ (inj₁ refl)) produceSquare-range : TripleR Π produceSquare Π produceSquare-range = conseq proj₁ (case ((conseq (λ { {(w , h) , v} (w≡v , _) → tt , trueFromWitness w≡v , tt }) skip (λ _ → tt)) ∷ᴺ •∷ᴬ [])) (λ _ → inj₁ (tt , refl , tt)) resetHeight : BiGUL emptyF (kℕ ⊗ kℕ) kℕ resetHeight = case (((λ { (w , _) v → ⌊ w Nat.≟ v ⌋ }) , normal (skip proj₁) (const true)) ∷ (((λ _ _ → true) , adaptive (λ { _ v → (v , zero) }))) ∷ []) resetHeight-correctness : Triple Π resetHeight (λ { ((w' , h') , (w , h) , v) → w' ≡ v × (w ≡ v → h' ≡ h) × (w ≢ v → h' ≡ zero) }) resetHeight-correctness = case ((conseq (λ { {(w , h) , v} (_ , e , _) → trueToWitness e }) skip (λ { {.(w , h) , (w , h) , v} (refl , _ , e , _) → (trueToWitness e , (λ _ → refl) , (λ w≢v → ⊥-elim (w≢v (trueToWitness e)))) , (e , tt) , refl , tt })) ∷ᴺ (λ { (w , h) v (tt , _ , ne , _) → (tt , inj₁ (trueFromWitness refl)) , λ { (w' , h') (w'≡v , v≡v→h'≡0 , _) → w'≡v , (λ w≡v → ⊥-elim (falseToWitness ne w≡v)) , (λ _ → v≡v→h'≡0 refl) } }) ∷ᴬ []) (λ _ → inj₂ (inj₁ refl)) resetHeight-range : TripleR Π resetHeight Π resetHeight-range = conseq proj₁ (case ((conseq (λ { {(w , h) , v} (w≡v , _) → tt , trueFromWitness w≡v , tt }) skip (λ _ → tt)) ∷ᴺ •∷ᴬ [])) (λ _ → inj₁ (tt , refl , tt)) alwaysResetHeight : BiGUL emptyF (kℕ ⊗ kℕ) kℕ alwaysResetHeight = rearrV var (prod var (k {G = kℕ} zero)) (refl , tt) (return refl) replace² alwaysResetHeight-correctness : Triple Π alwaysResetHeight (λ { ((w' , h') , _ , v) → w' ≡ v × h' ≡ zero }) alwaysResetHeight-correctness = conseq (λ _ → _ , tt , refl) (rearrV Π (λ { ((w' , h') , _ , v) → w' ≡ v × h' ≡ zero }) (conseq (λ _ → tt) replace²-correctness (λ { {(.u , .v) , (w , h) , (u , v)} ((refl , refl) , _ , _ , _ , 0≡v) → _ , (refl , sym 0≡v) , (refl , 0≡v) }))) (λ { ((_ , p , refl) , _) → p }) alwaysResetHeight-range : TripleR Π alwaysResetHeight ((_≡ zero) ∘ proj₂) alwaysResetHeight-range = conseq (λ _ → tt) (rearrV Π (conseq {Q = (_≡ zero) ∘ proj₂} (λ { ((_ , v≡0) , _) → _ , tt , refl , sym v≡0 }) (prod replace (conseq (λ { (s≡v , s≡0) → trans (sym s≡v) s≡0 }) replace (λ _ → tt))) (_,_ tt))) id just-lemma : {A : Set} {x y : A} → (Maybe A ∋ just x) ≡ just y → x ≡ y just-lemma refl = refl module _ (Rational : Set) (_≟_ : Decidable (_≡_ {A = Rational})) (zero : Rational) (mul : Rational → Rational → Rational) (div : Rational → (d : Rational) → Maybe Rational) (DivNonZero : (x y : Rational) → y ≢ zero → Σ[ z ∈ Rational ] div x y ≡ just z) (DivMul : (x y z : Rational) → div x y ≡ just z → mul y z ≡ x) (CrossEq : (a b c d : Rational) → mul d a ≡ mul c b → b ≢ zero → d ≢ zero → div a b ≡ div c d) where kQ : U 0 kQ = k Rational _≟_ fromJustOrZero : Maybe Rational → Rational fromJustOrZero (just x) = x fromJustOrZero nothing = zero keepRatio : BiGUL emptyF (kQ ⊗ kQ) kQ keepRatio = case (((λ { (w , _) _ → ⌊ w ≟ zero ⌋ }) , adaptive λ { (_ , h) v → (v , h) }) ∷ ((λ { (w , _) v → ⌊ w ≟ v ⌋ }) , normal (skip proj₁) (λ _ → true)) ∷ ((λ _ _ → true) , adaptive (λ { (w , h) v → (v , fromJustOrZero (div (mul h v) w)) })) ∷ []) keepRatio-correctness : Triple (λ { (_ , v) → v ≢ zero }) keepRatio (λ { ((w' , h') , (w , h) , v) → w' ≡ v × (w ≡ zero → h' ≡ h) × (w ≢ zero → div h' w' ≡ div h w) }) keepRatio-correctness = case ((λ { (w , h) v (v≢zero , w==zero , _) → (v≢zero , falseFromWitness v≢zero , inj₁ (trueFromWitness refl)) , (λ { (w' , h') (w'≡v , v≡zero→h'≡h , v≢zero→h'/w'≡h/v) → w'≡v , (λ w≡zero → let (x , h'/w'≡just-x) = DivNonZero h' w' (subst (_≢ zero) (sym w'≡v) v≢zero) (y , h/v≡just-y) = DivNonZero h v v≢zero in trans (sym (DivMul h' w' x h'/w'≡just-x)) (trans (trans (subst (λ a → mul w' x ≡ mul a x) w'≡v refl) (cong (mul v) (just-lemma (trans (sym h'/w'≡just-x) (trans (v≢zero→h'/w'≡h/v v≢zero) h/v≡just-y))))) (DivMul h v y h/v≡just-y))) , (λ w≢zero → ⊥-elim (w≢zero (trueToWitness w==zero))) }) }) ∷ᴬ conseq (λ { {(w , h) , v} (v≢zero , w==v , w/=zero , _) → trueToWitness w==v }) skip (λ { {.(w , h) , (w , h) , v} (refl , v≢zero , w==v , w/=zero , _) → (trueToWitness w==v , (λ _ → refl) , (λ _ → refl)) , (w==v , w/=zero , tt) , refl , tt }) ∷ᴺ (λ { (w , h) v (v≢zero , _ , w/=v , w/=zero , _) → (v≢zero , falseFromWitness v≢zero , inj₁ (trueFromWitness refl)) , (λ { (w' , h') → aux w' h' w h v (falseToWitness w/=zero) v≢zero }) }) ∷ᴬ []) (λ _ → inj₂ (inj₂ (inj₁ refl))) where aux : (w' h' w h v : Rational) → w ≢ zero → v ≢ zero → w' ≡ v × (v ≡ zero → h' ≡ fromJustOrZero (div (mul h v) w)) × (v ≢ zero → div h' w' ≡ div (fromJustOrZero (div (mul h v) w)) v) → w' ≡ v × (w ≡ zero → h' ≡ h) × (w ≢ zero → div h' w' ≡ div h w) aux w' h' w h v w≢zero v≢zero (w'≡v , v≡zero→ , v≢zero→) with DivNonZero (mul h v) w w≢zero aux w' h' w h v w≢zero v≢zero (w'≡v , v≡zero→ , v≢zero→) | x , eq rewrite eq = w'≡v , (λ w≡zero → ⊥-elim (w≢zero w≡zero)) , (λ _ → trans (v≢zero→ v≢zero) (CrossEq x v h w (DivMul (mul h v) w x eq) v≢zero w≢zero )) keepRatio-range : TripleR (λ { (_ , v) → v ≢ zero }) keepRatio (λ { (w' , _) → w' ≢ zero }) keepRatio-range = conseq proj₁ (case (•∷ᴬ (conseq (λ { {(w , h) , v} (w≡v , w≢zero) → subst (_≢ zero) w≡v w≢zero , trueFromWitness w≡v , falseFromWitness w≢zero , tt }) skip (λ _ → tt)) ∷ᴺ •∷ᴬ [])) (inj₁ ∘ (_, (refl , tt)))