\begin{code}
{-# OPTIONS --safe --lossy-unification #-}
open import Prelude renaming ([_] to [_]⊩)
open import Algebra
open import Algebra.Monus
module Codata.Neighbours.Solves
{W : Type} (mon : WellFoundedMonus W)
(s : W)
(s≢ε : s ≢ WellFoundedMonus.ε mon)
where
open WellFoundedMonus mon
open Weight (weight W tapom)
open import Data.Weighted ⊕-semigroup hiding (⟪_⟫)
open import Data.Weighted.Monad (weight W tapom)
using
( _⋊_
; bind-alg
; wmap-alg
; ⋊-alg
; wmap
)
renaming (return to ηʷ)
import Data.Weighted.Monad (weight _ tapom) as WB
open import Data.Weighted.Functor
open import Data.Weighted.Cutoff totalOrder
open import Data.Weighted.CutoffMonus tmapom
open import Path.Reasoning
open import Codata.Neighbours mon
module Solution {X : Type} (eᵢ : (X → INeighbours (X ⊎ A) ⊎ A)) where
σ : INeighbours B → Neighbours B
σ = _⋊ₙ_ s
open Solve s s≢ε eᵢ
cut-to-<s : ∀ w wf p x → w < p ∙ s → cut-to w wf p x ≡ ⟅⟆
cut-to-<s w wf p x w<p∙s with p ∙ s ≤? w
... | no p∙s≰w = refl
... | yes p∙s≤w = absurd (w<p∙s p∙s≤w)
cut-<s : ∀ w wf → w < s → ∀ x → cut w wf x ≡ ⟅⟆
cut-<s w wf w<s = ⟦ alg ⟧
where
alg : Ψ[ x ⦂ Weighted (X ⊎ A) ] ↦ cut w wf x ≡ ⟅⟆
alg .snd = eq-coh
alg .fst ⟅⟆ = refl
alg .fst (p ▹ x ∷ xs ⟨ P⟨xs⟩ ⟩) = cong₂ _∪_ (cut-to-<s w wf p x ≲[ <[ w<s ] ≲; ≤[ x≤x∙y ] ≲; ≡[ comm s p ] ]) P⟨xs⟩
soln-step : ∀ w wf p v
→ (p≺w : p ≺ₛ w)
→ step w p p≺w wf v ≡ (solve ▿ η) v ⊩ p≺w .fst
soln-step w wf p (inr x) _ = refl
soln-step w (acc wf) p (inl x) p≺w = cong (λ e → find (p≺w .fst) e x) (isPropAcc _ _)
soln-cut-to : ∀ w wf p v → (p≺w : p ≺ₛ w) → cut-to w wf p v ≡ s ∙ p ⋊ (solve ▿ η) v ⊩ p≺w .fst
soln-cut-to w wf p v p≺w₁ with p ∙ s ≤? w
... | no p⊀w = absurd (p⊀w p≺w₁)
... | yes p≺w₂ =
p ∙ s ⋊ step w p p≺w₂ wf v ≡⟨ cong (_⋊ step w p p≺w₂ wf v) (comm p s) ⟩
s ∙ p ⋊ step w p p≺w₂ wf v ≡⟨ cong (s ∙ p ⋊_) (soln-step w wf p v p≺w₂) ⟩
s ∙ p ⋊ (solve ▿ η) v ⊩ p≺w₂ .fst ≡⟨ cong (λ e → s ∙ p ⋊ (solve ▿ η) v ⊩ e) (cancelˡ (p ∙ s) _ _ (sym (p≺w₂ .snd) ; p≺w₁ .snd)) ⟩
s ∙ p ⋊ (solve ▿ η) v ⊩ p≺w₁ .fst ∎
soln-compd : ∀ k w wf → w ≡ s ∙ k → ∀ p v → cut-to w wf p v ≡ W[ [ w ⊣-alg ]W-hom W∘ bind-alg (_⊩ w) W∘ wmap-alg (solve ▿ η) W∘ ⋊-alg s ]↓ (k / p ▹ v)
soln-compd k w wf w≡s∙k p v with p ≤? k
... | no p≰k = cut-to-<s w wf p v ≲[ ≡[ w≡s∙k ] ≲; <[ <-congˡ s p≰k ] ≲; ≡[ comm s p ] ]
... | yes (k₂ , k≡p∙k₂) =
cut-to w wf p v ≡⟨ soln-cut-to w wf p v (k₂ , (w≡s∙k ; cong (s ∙_) k≡p∙k₂ ; sym (assoc s p k₂) ; cong (_∙ k₂) (comm s p))) ⟩
s ∙ p ⋊ (solve ▿ η) v ⊩ k₂ ≡˘⟨ cong (s ∙ p ⋊_) (neighbourly ((solve ▿ η) v) w k₂ (p ∙ s , (w≡s∙k ; cong (s ∙_) k≡p∙k₂ ; sym (assoc s p k₂) ; cong (_∙ k₂) (comm s p) ; comm (p ∙ s) k₂))) ⟩
s ∙ p ⋊ (solve ▿ η) v ⊩ w ⊢ k₂ ≡˘⟨ ≤-⋊-⊢ (s ∙ p) ((solve ▿ η) v ⊩ w) w (k₂ , (w≡s∙k ; cong (s ∙_) k≡p∙k₂ ; sym (assoc s p k₂) )) ⟩
(s ∙ p ⋊ (solve ▿ η) v ⊩ w) ⊢ w ≡⟨⟩
W[ [ w ⊣-alg ]W-hom ]↓ (s ∙ p ⋊ (solve ▿ η) v ⊩ w) ≡˘⟨ ∪-idʳ _ ⟩
W[ [ w ⊣-alg ]W-hom W∘ bind-alg (_⊩ w) ]↓ (s ∙ p ▹ (solve ▿ η) v ∷ ⟅⟆) ≡˘⟨ ∪-idʳ _ ⟩
W[ [ w ⊣-alg ]W-hom W∘ bind-alg (_⊩ w) W∘ wmap-alg (solve ▿ η) ]↓ (s ∙ p ▹ v ∷ ⟅⟆) ≡˘⟨ ∪-idʳ _ ⟩
W[ [ w ⊣-alg ]W-hom W∘ bind-alg (_⊩ w) W∘ wmap-alg (solve ▿ η) W∘ ⋊-alg s ]↓ (p ▹ v ∷ ⟅⟆) ∎
solution′ : ∀ x w wf → find w wf x ≡ (μ ∘ mapₙ (solve ▿ η) ∘ (σ ▿ η ∘ inr) ∘ eᵢ) x ⊩ w
solution′ x w wf with eᵢ x
... | inr y = ηʷ y ≡˘⟨ return-⊢ y w ⟩
ηʷ y ⊢ w ≡˘⟨ cong (λ v → (v ▹ y ∷ ⟅⟆) ⊢ w) (ε∙ ε) ⟩
(ε ∙ ε ▹ y ∷ ⟅⟆) ⊢ w ≡⟨⟩
(μ ∘ mapₙ (solve ▿ η) ∘ (σ ▿ η ∘ inr)) (inr y) ⊩ w ∎
... | inl y with s ≤? w
... | no s≰w = cut-<s w wf s≰w (y ⊩ w)
... | yes (k , w≡s∙k) =
cut w wf (y ⊩ w)
≡⟨⟩
[ cut-alg w wf ]W↓ (y ⊩ w)
≡⟨ cong (λ e → W[ e ]↓ (y ⊩ w))
(W⟶-≡
[ cut-alg w wf ]W-hom
([ w ⊣-alg ]W-hom W∘ bind-alg (_⊩ w) W∘ wmap-alg (solve ▿ η) W∘ ⋊-alg s W∘ k ⊣-alg)
(soln-compd k w wf w≡s∙k)
(λ _ _ → refl)
refl) ⟩
W[ [ w ⊣-alg ]W-hom W∘ bind-alg (_⊩ w) W∘ wmap-alg (solve ▿ η) W∘ ⋊-alg s W∘ k ⊣-alg ]↓ (y ⊩ w)
≡⟨ W-comp-eq _ (k ⊣-alg) (y ⊩ w)
; W-comp-eq _ (⋊-alg s) (y ⊩ w ⊢ k)
; W-comp-eq _ (wmap-alg (solve ▿ η)) (s ⋊ (y ⊩ w ⊢ k))
; W-comp-eq _ (bind-alg (_⊩ w)) (wmap (solve ▿ η) (s ⋊ (y ⊩ w ⊢ k)))
⟩
wmap (solve ▿ η) (s ⋊ y ⊩ w ⊢ k) ⊪ w ⊢ w
≡⟨ cong (λ e → wmap (solve ▿ η) (s ⋊ e) ⊪ w ⊢ w) (neighbourly y w k (s , (w≡s∙k ; comm s k))) ⟩
wmap (solve ▿ η) (s ⋊ y ⊩ k) ⊪ w ⊢ w ∎
solution : ∀ x → solve x ≡ (μ ∘ mapₙ (solve ▿ η) ∘ (σ ▿ η ∘ inr) ∘ eᵢ) x
solution x = search≡ (λ w → solution′ x w (well-founded (s , s≢ε) w))
module _ {X : Type} (eᵢ : (X → INeighbours (X ⊎ A) ⊎ A)) where
open Solution eᵢ
open Solve {X = X} {A = A} s s≢ε
solution-disp :
\end{code}
%<*solution>
\begin{code}
∀ x → solve eᵢ x ≡ (μ ∘ mapₙ (solve eᵢ ▿ η) ∘ (σ ▿ η ∘ inr) ∘ eᵢ) x
\end{code}
%</solution>
\begin{code}
solution-disp = solution
open import Codata.Neighbours.Monad mon
open NeighboursMonad using (>>=-map)
open Monad neighboursMonad
open Functor neighboursFunctor using (map-id)
open import Codata.CIM hiding (μ; η)
μ″ : Neighbours (Neighbours A) → Neighbours A
μ″ x = x >>= id
map″ : (A → B) → Neighbours A → Neighbours B
map″ f x = x >>= return ∘ f
μ-lemma : μ {A = A} ≡ μ″
μ-lemma = funExt (λ x → sym (cong μ (map-id x)))
map-lemma : (f : A → B) → mapₙ f ≡ map″ f
map-lemma f = funExt (>>=-map f)
module _ {X A : Type} where
open Solve {X = X} {A = A} s s≢ε public
open Solution {A = A} {X = X} public
ideal : Ideal Neighbours INeighbours neighboursMonad neighboursFunctor
ideal .Ideal.mod .Module.μ′ = μ
ideal .Ideal.mod .Module.μ-η = funExt >>=-idʳ
ideal .Ideal.mod .Module.μ-μ = funExt (λ x → μ (μ x) ≡⟨ cong (_$ μ x) μ-lemma ; cong μ″ (cong (_$ x) μ-lemma) ; >>=-assoc x _ _ ⟩ μ (mapₙ (_>>= id) x) ∎)
ideal .Ideal.σ = _⋊ₙ_ s
ideal .Ideal.hom = funExt λ x → ( (s ⋊ₙ x) >>= id ) ≡⟨ sym (cong (_$ (s ⋊ₙ x)) μ-lemma) ; μ-⋊ s x ⟩ s ⋊ₙ (μ x) ∎
ideal .Ideal.natural f = funExt λ x →
s ⋊ₙ mapₙ f x ≡⟨ mapₙ-⋊ₙ f s x ⟩
mapₙ f (s ⋊ₙ x) ≡⟨ cong (_$ (s ⋊ₙ x)) (map-lemma f) ⟩
mmap f (s ⋊ₙ x) ∎
cim : CIM Neighbours INeighbours neighboursMonad neighboursFunctor
cim .CIM.ideal = ideal
cim .CIM._‡ = solve
cim .CIM.solution eᵢ = funExt (solution eᵢ)
; cong₂ _∘_ μ-lemma (cong (_∘ (σ eᵢ ▿ η ∘ inr) ∘ eᵢ) (map-lemma (solve eᵢ ▿ η)))
open CIM cim
open ComMonadPlus neighboursMonadPlus
infixl 8 _∗
_∗ : (A → INeighbours A) → A → Neighbours A
g ∗ = e† λ v → η (inr v) <|> η (inl (g v))
\end{code}