\begin{code} {-# OPTIONS --safe #-} open import Algebra open import Prelude hiding ([_]) open import Relation.Binary module Data.Weighted.Cutoff {ℓ₁ ℓ₂ ℓ₃} {W : Type ℓ₁} (ord : TotalOrder W ℓ₂ ℓ₃) where open TotalOrder ord hiding (refl) open import Data.Weighted.Definition ⊓-semigroup open import Data.Weighted.Eliminators ⊓-semigroup open import Data.Weighted.CommutativeMonoid ⊓-semigroup open import Data.Weighted.Functor open import Path.Reasoning module _ {A : Type a} where _/_▹_ : W → W → A → Weighted A c / p ▹ x = if p ≤ᵇ c then p ▹ x ∷ ⟅⟆ else ⟅⟆ _//_▹_ : W → W → A → Weighted A c // p ▹ x = if p <ᵇ c then p ▹ x ∷ ⟅⟆ else ⟅⟆ _⊣-alg : W → A ⟶W A (w ⊣-alg) .act-w p x = w / p ▹ x (w ⊣-alg) .coh-w p q x with p ≤? w | q ≤? w | p ⊓ q ≤? w ... | no p≰w | no q≰w | no p⊓q≰w = refl ... | yes p≤w | yes q≤w | yes p⊓q≤w = dup p q x ⟅⟆ ... | yes p≤w | no q≰w | yes p⊓q≤w = cong (_▹ x ∷ ⟅⟆) (sym (⊓≤≡ p q ≲[ ≤[ p≤w ] ≲; ≤[ <⇒≤ (≰⇒> q≰w) ] ])) ... | no p≰w | yes q≤w | yes p⊓q≤w = cong (_▹ x ∷ ⟅⟆) (sym (⊓≤≡ q p ≲[ ≤[ q≤w ] ≲; ≤[ <⇒≤ (≰⇒> p≰w) ] ] ) ; ⊓-comm q p) ... | yes p≤w | _ | no p⊓q≰w = absurd (p⊓q≰w ≲[ ≤[ ⊓≤ p q ] ≲; ≤[ p≤w ] ]) ... | _ | yes q≤w | no p⊓q≰w = absurd (p⊓q≰w ≲[ ≡[ ⊓-comm p q ] ≲; ≤[ ⊓≤ q p ] ≲; ≤[ q≤w ] ]) ... | no p≰w | no q≰w | yes p⊓q≤w with p <? q ... | yes _ = absurd (p≰w p⊓q≤w) ... | no _ = absurd (q≰w p⊓q≤w) cutoff-lt-alg : W → Ψ[ xs ⦂ Weighted A ] ↦ Weighted A cutoff-lt-alg w .fst ⟅⟆ = ⟅⟆ cutoff-lt-alg w .fst (p ▹ x ∷ _ ⟨ xs ⟩) = w // p ▹ x ∪ xs cutoff-lt-alg w .snd .c-set _ = trunc cutoff-lt-alg w .snd .c-com p x q y _ xs = w // p ▹ x ∪ w // q ▹ y ∪ xs ≡˘⟨ ∪-assoc (w // p ▹ x) _ _ ⟩ (w // p ▹ x ∪ w // q ▹ y) ∪ xs ≡⟨ cong (_∪ xs) ( ∪-com (w // p ▹ x) _) ⟩ (w // q ▹ y ∪ w // p ▹ x) ∪ xs ≡⟨ ∪-assoc (w // q ▹ y) _ _ ⟩ w // q ▹ y ∪ w // p ▹ x ∪ xs ∎ cutoff-lt-alg w .snd .c-dup p q x _ xs with p <? w | q <? w | p ⊓ q <? w ... | no p≮w | no q≮w | no p⊓q≮w = refl ... | yes p<w | yes q<w | yes p⊓q<w = dup p q x xs ... | yes p<w | no q≮w | yes p⊓q<w = cong (_▹ x ∷ xs) (sym (⊓≤≡ p q (<⇒≤ ≲[ <[ p<w ] ≲; ≤[ ≮⇒≥ q≮w ] ]))) ... | no p≮w | yes q<w | yes p⊓q<w = cong (_▹ x ∷ xs) (sym (⊓≤≡ q p (<⇒≤ ≲[ <[ q<w ] ≲; ≤[ ≮⇒≥ p≮w ] ]) ) ; ⊓-comm q p) ... | yes p<w | _ | no p⊓q≮w = absurd (p⊓q≮w ≲[ ≤[ ⊓≤ p q ] ≲; <[ p<w ] ]) ... | _ | yes q<w | no p⊓q≮w = absurd (p⊓q≮w ≲[ ≡[ ⊓-comm p q ] ≲; ≤[ ⊓≤ q p ] ≲; <[ q<w ] ]) ... | no p≮w | no q≮w | yes p⊓q<w with p <? q ... | yes _ = absurd (p≮w p⊓q<w) ... | no _ = absurd (q≮w p⊓q<w) infixl 6 _⊢_ _⊢_ : Weighted A → W → Weighted A x ⊢ w = [ w ⊣-alg ]W↓ x infixl 6 _⊨_ _⊨_ : Weighted A → W → Weighted A x ⊨ w = ⟦ cutoff-lt-alg w ⟧ x ⊢-≥ : ∀ s v w → v ≥ w → s ⊢ v ⊢ w ≡ s ⊢ w ⊢-≥ s v w v≥w = ⟦ cutoff-≤-alg ⟧ s where cutoff-≤-alg : Ψ[ s ⦂ Weighted A ] ↦ s ⊢ v ⊢ w ≡ s ⊢ w cutoff-≤-alg .fst ⟅⟆ = refl cutoff-≤-alg .fst (p ▹ x ∷ xs ⟨ P⟨xs⟩ ⟩) with p ≤? v cutoff-≤-alg .fst (p ▹ x ∷ xs ⟨ P⟨xs⟩ ⟩) | no p≰v with p ≤? w cutoff-≤-alg .fst (p ▹ x ∷ xs ⟨ P⟨xs⟩ ⟩) | no p≰v | yes p≤w = absurd (p≰v (≤-trans p≤w v≥w)) cutoff-≤-alg .fst (p ▹ x ∷ xs ⟨ P⟨xs⟩ ⟩) | no p≰v | no p≰w = P⟨xs⟩ cutoff-≤-alg .fst (p ▹ x ∷ xs ⟨ P⟨xs⟩ ⟩) | yes p≤v with p ≤? w cutoff-≤-alg .fst (p ▹ x ∷ xs ⟨ P⟨xs⟩ ⟩) | yes p≤v | yes p≤w = cong (p ▹ x ∷_) P⟨xs⟩ cutoff-≤-alg .fst (p ▹ x ∷ xs ⟨ P⟨xs⟩ ⟩) | yes p≤v | no p≰w = P⟨xs⟩ cutoff-≤-alg .snd = prop-coh λ _ → trunc _ _ ⊢-ε : ∀ w → ⟅⟆ ⊢ w ≡ ⟅⟆ ⊢-ε w = refl ⊢-∪ : ∀ s t w → (s ∪ t) ⊢ w ≡ s ⊢ w ∪ t ⊢ w ⊢-∪ xs ys w = collect-∪ (w ⊣-alg) xs ys /≤ : ∀ w p x → p ≤ w → w / p ▹ x ≡ p ▹ x ∷ ⟅⟆ /≤ w p x p≤w with p ≤? w ... | yes _ = refl ... | no p≰w = absurd (p≰w p≤w) /≰ : ∀ w p x → p ≰ w → w / p ▹ x ≡ ⟅⟆ /≰ w p x p≰w with p ≤? w ... | yes p≤w = absurd (p≰w p≤w) ... | no _ = refl /▹-comm : ∀ w₁ w₂ p x → (w₁ / p ▹ x) ⊢ w₂ ≡ (w₂ / p ▹ x) ⊢ w₁ /▹-comm w₁ w₂ p x with p ≤? w₁ | p ≤? w₂ ... | yes p≤w₁ | yes p≤w₂ = cong (_∪ ⟅⟆) (/≤ w₂ p x p≤w₂ ; sym (/≤ w₁ p x p≤w₁)) ... | no p≰w₁ | no p≰w₂ = refl ... | no p≰w₁ | yes p≤w₂ = sym (cong (_∪ ⟅⟆) (/≰ w₁ p x p≰w₁)) ... | yes p≤w₁ | no p≰w₂ = cong (_∪ ⟅⟆) (/≰ w₂ p x p≰w₂) ⊢-com : ∀ s v w → s ⊢ v ⊢ w ≡ s ⊢ w ⊢ v ⊢-com s w₁ w₂ = ⟦ alg ⟧ s where alg : Ψ[ s ⦂ Weighted A ] ↦ s ⊢ w₁ ⊢ w₂ ≡ s ⊢ w₂ ⊢ w₁ alg .fst (p ▹ x ∷ xs ⟨ P⟨xs⟩ ⟩) = (p ▹ x ∷ xs) ⊢ w₁ ⊢ w₂ ≡⟨⟩ (w₁ / p ▹ x ∪ xs ⊢ w₁) ⊢ w₂ ≡⟨ ⊢-∪ (w₁ / p ▹ x) _ _ ⟩ w₁ / p ▹ x ⊢ w₂ ∪ xs ⊢ w₁ ⊢ w₂ ≡⟨ cong₂ _∪_ (/▹-comm w₁ w₂ p x) P⟨xs⟩ ⟩ w₂ / p ▹ x ⊢ w₁ ∪ xs ⊢ w₂ ⊢ w₁ ≡˘⟨ ⊢-∪ (w₂ / p ▹ x) _ _ ⟩ (p ▹ x ∷ xs) ⊢ w₂ ⊢ w₁ ∎ alg .fst ⟅⟆ = refl alg .snd = eq-coh ⊢-⊓ : \end{code} %<*cutoff-min> \begin{code}[number=code:cutoff-min] ∀ s v w → (s ⊢ v) ⊢ w ≡ s ⊢ (v ⊓ w) \end{code} %</cutoff-min> \begin{code} ⊢-⊓ s v w with v <? w ... | no v≮w = ⊢-≥ s v w (≮⇒≥ v≮w) ... | yes v<w = ⊢-com s v w ; ⊢-≥ s w v (<⇒≤ v<w) infixl 6 _∘⊢_ _∘⊢_ : (A → Weighted B) → W → A → Weighted B (k ∘⊢ w) x = k x ⊢ w infix 4 _⊑_ _⊑_ : Weighted A → Weighted A → Type- xs ⊑ ys = ∃ k × xs ≡ ys ⊢ k ⊑-antisym : {x y : Weighted A} → x ⊑ y → y ⊑ x → x ≡ y ⊑-antisym {x = x} {y} (k₁ , x≡y⊢k₁) (k₂ , y≡x⊢k₂) with k₁ ≤|≥ k₂ ... | inl k₁≤k₂ = x≡y⊢k₁ ; sym (⊢-≥ y _ _ k₁≤k₂) ; ⊢-com y k₂ k₁ ; sym (cong (_⊢ k₂) x≡y⊢k₁) ; sym y≡x⊢k₂ ... | inr k₂≤k₁ = x≡y⊢k₁ ; cong (_⊢ k₁) y≡x⊢k₂ ; ⊢-com x k₂ k₁ ; ⊢-≥ x _ _ k₂≤k₁ ; sym y≡x⊢k₂ ⊢-∪-idem : ∀ k (x : Weighted A) → x ∪ x ⊢ k ≡ x ⊢-∪-idem k = ⟦ alg k ⟧ where alg : ∀ k → Ψ[ x ⦂ Weighted A ] ↦ x ∪ x ⊢ k ≡ x alg k .fst ⟅⟆ = refl alg k .fst (w ▹ x ∷ xs ⟨ P⟨xs⟩ ⟩) with w ≤? k ... | yes w≤k = w ▹ x ∷ xs ∪ w ▹ x ∷ xs ⊢ k ≡˘⟨ cong (w ▹ x ∷_) (∪-cons w x xs (xs ⊢ k)) ⟩ w ▹ x ∷ w ▹ x ∷ xs ∪ xs ⊢ k ≡⟨ dup w w x (xs ∪ xs ⊢ k) ⟩ w ⊓ w ▹ x ∷ xs ∪ xs ⊢ k ≡⟨ cong (_▹ x ∷ xs ∪ xs ⊢ k) (⊓-idem w) ⟩ w ▹ x ∷ xs ∪ xs ⊢ k ≡⟨ cong (w ▹ x ∷_) P⟨xs⟩ ⟩ w ▹ x ∷ xs ∎ ... | no _ = cong (w ▹ x ∷_) P⟨xs⟩ alg k .snd = eq-coh ⊑-∪ : (x y : Weighted A) → x ⊑ y → x ∪ y ≡ y ⊑-∪ x y (k , x⊑y) = cong (_∪ y) x⊑y ; ∪-com (y ⊢ k) y ; ⊢-∪-idem k y \end{code}