------------------------------------------------------------------------
-- The zero-one-many modality
------------------------------------------------------------------------

-- Based on Conor McBride's "I Got Plenty o’ Nuttin’".

-- It might make sense to replace some of the proofs with automated
-- proofs.

open import Tools.Bool using (Bool; true; false; if_then_else_; T)

module Graded.Modality.Instances.Zero-one-many
  -- Should πŸ™ be below 𝟘?
  (πŸ™β‰€πŸ˜ : Bool)
  where
import Tools.Algebra
open import Tools.Empty
open import Tools.Function
open import Tools.Level
open import Tools.Nat using (1+; Sequence)
open import Tools.Product
open import Tools.PropositionalEquality as PE
import Tools.Reasoning.PartialOrder
import Tools.Reasoning.PropositionalEquality
open import Tools.Relation
open import Tools.Sum using (_⊎_; inj₁; injβ‚‚)

import Graded.Modality
import Graded.Modality.Instances.LowerBounded as LowerBounded
import Graded.Modality.Properties.Addition as Addition
import Graded.Modality.Properties.Greatest-lower-bound as GLB
import Graded.Modality.Properties.Meet as Meet
import Graded.Modality.Properties.Multiplication as Multiplication
import Graded.Modality.Properties.PartialOrder as PartialOrder
import Graded.Modality.Properties.Star as Star
import Graded.Modality.Properties.Natrec as Natrec
import Graded.Modality.Properties.Subtraction as Subtraction
open import Graded.Modality.Variant lzero

------------------------------------------------------------------------
-- The type

-- Zero, one or many.

data Zero-one-many : Set where
  𝟘 πŸ™ Ο‰ : Zero-one-many

private variable
  n n₁ nβ‚‚ p p₁ pβ‚‚ q r result s s₁ sβ‚‚ z z₁ zβ‚‚ : Zero-one-many

open Graded.Modality Zero-one-many
open Tools.Algebra   Zero-one-many

-- A decision procedure for equality.

infix 10 _β‰Ÿ_

_β‰Ÿ_ : Decidable (_≑_ {A = Zero-one-many})
𝟘 β‰Ÿ 𝟘 = yes refl
𝟘 β‰Ÿ πŸ™ = no (Ξ» ())
𝟘 β‰Ÿ Ο‰ = no (Ξ» ())
πŸ™ β‰Ÿ 𝟘 = no (Ξ» ())
πŸ™ β‰Ÿ πŸ™ = yes refl
πŸ™ β‰Ÿ Ο‰ = no (Ξ» ())
Ο‰ β‰Ÿ 𝟘 = no (Ξ» ())
Ο‰ β‰Ÿ πŸ™ = no (Ξ» ())
Ο‰ β‰Ÿ Ο‰ = yes refl

------------------------------------------------------------------------
-- Meet

-- Some requirements of a meet operation.

Meet-requirements :
  (Zero-one-many β†’ Zero-one-many β†’ Zero-one-many) β†’ Set
Meet-requirements _∧_ =
  (𝟘 ∧ 𝟘 ≑ 𝟘) Γ—
  (πŸ™ ∧ πŸ™ ≑ πŸ™) Γ—
  (Ο‰ ∧ Ο‰ ≑ Ο‰) Γ—
  (𝟘 ∧ Ο‰ ≑ Ο‰) Γ—
  (Ο‰ ∧ 𝟘 ≑ Ο‰) Γ—
  (πŸ™ ∧ Ο‰ ≑ Ο‰) Γ—
  (Ο‰ ∧ πŸ™ ≑ Ο‰) Γ—
  (𝟘 ∧ πŸ™ β‰’ 𝟘) Γ—
  (πŸ™ ∧ 𝟘 β‰’ 𝟘)

-- The meet operation of a "Semiring-with-meet" for Zero-one-many for
-- which the zero is 𝟘, the one is πŸ™, ω ≀ p for all p
-- and πŸ˜Β βˆ§Β πŸ™Β β‰’Β πŸ˜ has to satisfy the Meet-requirements.

Meet-requirements-required :
  (M : Semiring-with-meet) β†’
  Semiring-with-meet.𝟘          M ≑ 𝟘 β†’
  Semiring-with-meet.πŸ™          M ≑ πŸ™ β†’
  Semiring-with-meet._∧_ M    𝟘 πŸ™ β‰’ 𝟘 β†’
  (βˆ€ p β†’ Semiring-with-meet._≀_ M Ο‰ p) β†’
  Meet-requirements (Semiring-with-meet._∧_ M)
Meet-requirements-required M@record{} refl refl πŸ˜βˆ§πŸ™β‰’πŸ˜ ω≀ =
    (𝟘 ∧ 𝟘  β‰‘βŸ¨ ∧-idem _ ⟩
     𝟘      ∎)
  , (πŸ™ ∧ πŸ™  β‰‘βŸ¨ ∧-idem _ ⟩
     πŸ™      ∎)
  , (Ο‰ ∧ Ο‰  β‰‘βŸ¨ ∧-idem _ ⟩
     Ο‰      ∎)
  , (𝟘 ∧ Ο‰  β‰‘βŸ¨ ∧-comm _ _ ⟩
     Ο‰ ∧ 𝟘  β‰‘Λ˜βŸ¨ ω≀ 𝟘 ⟩
     Ο‰      ∎)
  , (Ο‰ ∧ 𝟘  β‰‘Λ˜βŸ¨ ω≀ 𝟘 ⟩
     Ο‰      ∎)
  , (πŸ™ ∧ Ο‰  β‰‘βŸ¨ ∧-comm _ _ ⟩
     Ο‰ ∧ πŸ™  β‰‘Λ˜βŸ¨ ω≀ πŸ™ ⟩
     Ο‰      ∎)
  , (Ο‰ ∧ πŸ™  β‰‘Λ˜βŸ¨ ω≀ πŸ™ ⟩
     Ο‰      ∎)
  , πŸ˜βˆ§πŸ™β‰’πŸ˜
  , (Ξ» πŸ™βˆ§πŸ˜β‰‘πŸ˜ β†’ πŸ˜βˆ§πŸ™β‰’πŸ˜ (
       𝟘 ∧ πŸ™  β‰‘βŸ¨ ∧-comm _ _ ⟩
       πŸ™ ∧ 𝟘  β‰‘βŸ¨ πŸ™βˆ§πŸ˜β‰‘πŸ˜ ⟩
       𝟘      ∎))
  where
  open Semiring-with-meet M hiding (𝟘; πŸ™; Ο‰)
  open Meet M
  open PartialOrder M
  open Tools.Reasoning.PropositionalEquality

-- The result of πŸ˜Β βˆ§Β πŸ™ and πŸ™Β βˆ§Β πŸ˜.

πŸ˜βˆ§πŸ™ : Zero-one-many
πŸ˜βˆ§πŸ™ = if πŸ™β‰€πŸ˜ then πŸ™ else Ο‰

-- Meet.

infixr 43 _∧_

_∧_ : Zero-one-many β†’ Zero-one-many β†’ Zero-one-many
𝟘 ∧ 𝟘 = 𝟘
πŸ™ ∧ πŸ™ = πŸ™
𝟘 ∧ πŸ™ = πŸ˜βˆ§πŸ™
πŸ™ ∧ 𝟘 = πŸ˜βˆ§πŸ™
_ ∧ _ = Ο‰

-- If πŸ™β‰€πŸ˜ is true, then πŸ˜βˆ§πŸ™Β β‰‘Β πŸ™.

πŸ˜βˆ§πŸ™β‰‘πŸ™ : T πŸ™β‰€πŸ˜ β†’ πŸ˜βˆ§πŸ™ ≑ πŸ™
πŸ˜βˆ§πŸ™β‰‘πŸ™ = lemma _
  where
  lemma : βˆ€ b β†’ T b β†’ (if b then πŸ™ else Ο‰) ≑ πŸ™
  lemma true  _  = refl
  lemma false ()

-- If πŸ˜βˆ§πŸ™Β β‰‘Β πŸ™, then πŸ™β‰€πŸ˜ is true.

πŸ˜βˆ§πŸ™β‰‘πŸ™β†’πŸ™β‰€πŸ˜ : πŸ˜βˆ§πŸ™ ≑ πŸ™ β†’ T πŸ™β‰€πŸ˜
πŸ˜βˆ§πŸ™β‰‘πŸ™β†’πŸ™β‰€πŸ˜ = lemma _
  where
  lemma : βˆ€ b β†’ (if b then πŸ™ else Ο‰) ≑ πŸ™ β†’ T b
  lemma true  _  = _
  lemma false ()

-- If πŸ™β‰€πŸ˜ is false, then πŸ˜βˆ§πŸ™Β β‰‘Β Ο‰.

πŸ˜βˆ§πŸ™β‰‘Ο‰ : Β¬ T πŸ™β‰€πŸ˜ β†’ πŸ˜βˆ§πŸ™ ≑ Ο‰
πŸ˜βˆ§πŸ™β‰‘Ο‰ = lemma _
  where
  lemma : βˆ€ b β†’ Β¬ T b β†’ (if b then πŸ™ else Ο‰) ≑ Ο‰
  lemma false _  = refl
  lemma true  ¬⊀ = βŠ₯-elim (¬⊀ _)

-- If πŸ˜βˆ§πŸ™Β β‰’Β πŸ™, then πŸ™β‰€πŸ˜ is false.

πŸ˜βˆ§πŸ™β‰’πŸ™β†’πŸ™β‰°πŸ˜ : πŸ˜βˆ§πŸ™ β‰’ πŸ™ β†’ Β¬ T πŸ™β‰€πŸ˜
πŸ˜βˆ§πŸ™β‰’πŸ™β†’πŸ™β‰°πŸ˜ = lemma _
  where
  lemma : βˆ€ b β†’ (if b then πŸ™ else Ο‰) β‰’ πŸ™ β†’ Β¬ T b
  lemma true  πŸ™β‰’πŸ™ = Ξ» _ β†’ πŸ™β‰’πŸ™ refl
  lemma false _   = idαΆ 

-- The value of πŸ˜βˆ§πŸ™ is not 𝟘.

πŸ˜βˆ§πŸ™β‰’πŸ˜ : πŸ˜βˆ§πŸ™ β‰’ 𝟘
πŸ˜βˆ§πŸ™β‰’πŸ˜ = lemma _
  where
  lemma : βˆ€ b β†’ (if b then πŸ™ else Ο‰) β‰’ 𝟘
  lemma false ()
  lemma true  ()

-- One can prove that something holds for πŸ˜βˆ§πŸ™ by proving that it holds
-- for πŸ™ (under the assumption that πŸ˜βˆ§πŸ™ is πŸ™), and that it holds for Ο‰
-- (under the assumption that πŸ˜βˆ§πŸ™ is Ο‰).

πŸ˜βˆ§πŸ™-elim :
  βˆ€ {p} (P : Zero-one-many β†’ Set p) β†’
  (πŸ˜βˆ§πŸ™ ≑ πŸ™ β†’ P πŸ™) β†’
  (πŸ˜βˆ§πŸ™ ≑ Ο‰ β†’ P Ο‰) β†’
  P πŸ˜βˆ§πŸ™
πŸ˜βˆ§πŸ™-elim P one omega = lemma _ refl
  where
  lemma : βˆ€ p β†’ πŸ˜βˆ§πŸ™ ≑ p β†’ P p
  lemma 𝟘 πŸ˜βˆ§πŸ™β‰‘πŸ˜ = βŠ₯-elim (πŸ˜βˆ§πŸ™β‰’πŸ˜ πŸ˜βˆ§πŸ™β‰‘πŸ˜)
  lemma πŸ™ πŸ˜βˆ§πŸ™β‰‘πŸ™ = one πŸ˜βˆ§πŸ™β‰‘πŸ™
  lemma Ο‰ πŸ˜βˆ§πŸ™β‰‘Ο‰ = omega πŸ˜βˆ§πŸ™β‰‘Ο‰

-- πŸ˜Β βˆ§Β πŸ˜βˆ§πŸ™ is equal to πŸ˜βˆ§πŸ™.

𝟘∧[πŸ˜βˆ§πŸ™] : 𝟘 ∧ πŸ˜βˆ§πŸ™ ≑ πŸ˜βˆ§πŸ™
𝟘∧[πŸ˜βˆ§πŸ™] = πŸ˜βˆ§πŸ™-elim
  (Ξ» p β†’ 𝟘 ∧ p ≑ p)
  (Ξ» πŸ˜βˆ§πŸ™β‰‘πŸ™ β†’ πŸ˜βˆ§πŸ™β‰‘πŸ™)
  (Ξ» _ β†’ refl)

-- πŸ™Β βˆ§Β πŸ˜βˆ§πŸ™ is equal to πŸ˜βˆ§πŸ™.

πŸ™βˆ§[πŸ˜βˆ§πŸ™] : πŸ™ ∧ πŸ˜βˆ§πŸ™ ≑ πŸ˜βˆ§πŸ™
πŸ™βˆ§[πŸ˜βˆ§πŸ™] = πŸ˜βˆ§πŸ™-elim
  (Ξ» p β†’ πŸ™ ∧ p ≑ p)
  (Ξ» _ β†’ refl)
  (Ξ» _ β†’ refl)

-- The value Ο‰ is a right zero for _∧_.

∧-zeroΚ³ : RightZero Ο‰ _∧_
∧-zeroʳ 𝟘 = refl
∧-zeroΚ³ πŸ™ = refl
∧-zeroΚ³ Ο‰ = refl

-- The value Ο‰ is a zero for _∧_.

∧-zero : Zero Ο‰ _∧_
∧-zero = (Ξ» _ β†’ refl) , ∧-zeroΚ³

-- If p ∧ q isΒ πŸ™, then at least one of p and q isΒ πŸ™, and if the other
-- one is notΒ πŸ™, then it is 𝟘, and πŸ™Β β‰€Β πŸ˜.

βˆ§β‰‘πŸ™ :
  p ∧ q ≑ πŸ™ β†’
  p ≑ 𝟘 Γ— q ≑ πŸ™ Γ— T πŸ™β‰€πŸ˜ ⊎
  p ≑ πŸ™ Γ— q ≑ 𝟘 Γ— T πŸ™β‰€πŸ˜ ⊎
  p ≑ πŸ™ Γ— q ≑ πŸ™
βˆ§β‰‘πŸ™ {p = 𝟘} {q = πŸ™} eq = inj₁ (refl , refl , πŸ˜βˆ§πŸ™β‰‘πŸ™β†’πŸ™β‰€πŸ˜ eq)
βˆ§β‰‘πŸ™ {p = πŸ™} {q = 𝟘} eq = injβ‚‚ (inj₁ (refl , refl , πŸ˜βˆ§πŸ™β‰‘πŸ™β†’πŸ™β‰€πŸ˜ eq))
βˆ§β‰‘πŸ™ {p = πŸ™} {q = πŸ™} _  = injβ‚‚ (injβ‚‚ (refl , refl))
βˆ§β‰‘πŸ™ {p = 𝟘} {q = 𝟘} ()
βˆ§β‰‘πŸ™ {p = 𝟘} {q = Ο‰} ()
βˆ§β‰‘πŸ™ {p = πŸ™} {q = Ο‰} ()
βˆ§β‰‘πŸ™ {p = Ο‰}         ()

opaque

  -- πŸ™ ∧ p is not equal to 𝟘

  πŸ™βˆ§pβ‰’πŸ˜ : βˆ€ p β†’ πŸ™ ∧ p β‰’ 𝟘
  πŸ™βˆ§pβ‰’πŸ˜ 𝟘 = πŸ˜βˆ§πŸ™β‰’πŸ˜
  πŸ™βˆ§pβ‰’πŸ˜ πŸ™ = Ξ» ()
  πŸ™βˆ§pβ‰’πŸ˜ Ο‰ = Ξ» ()

------------------------------------------------------------------------
-- Ordering

-- Some requirements of an ordering relation.

Order-requirements : (Zero-one-many β†’ Zero-one-many β†’ Set) β†’ Set
Order-requirements _≀_ = (Ο‰ ≀ πŸ™) Γ— (Ο‰ ≀ 𝟘) Γ— Β¬ (𝟘 ≀ πŸ™)

-- The ordering relation of a "Semiring-with-meet" for Zero-one-many for
-- which the zero is 𝟘, the one is πŸ™ and pΒ βˆ§Β Ο‰ equals Ο‰ for all p
-- has to satisfy the Order-requirements.

Order-requirements-required :
  (M : Semiring-with-meet) β†’
  Semiring-with-meet.𝟘          M ≑ 𝟘 β†’
  Semiring-with-meet.πŸ™          M ≑ πŸ™ β†’
  Semiring-with-meet._∧_ M    𝟘 πŸ™ β‰’ 𝟘 β†’
  (βˆ€ p β†’ Semiring-with-meet._≀_ M Ο‰ p) β†’
  Order-requirements (Semiring-with-meet._≀_ M)
Order-requirements-required M@record{} refl refl πŸ˜βˆ§πŸ™β‰’πŸ˜ ω≀ =
  case Meet-requirements-required M refl refl πŸ˜βˆ§πŸ™β‰’πŸ˜ ω≀ of Ξ» where
    (_ , _ , _ , _ , Ο‰βŠ“πŸ˜β‰‘Ο‰ , _ , Ο‰βŠ“πŸ™β‰‘Ο‰ , πŸ˜βŠ“πŸ™β‰’πŸ˜ , _) β†’
        (Ο‰      β‰‘Λ˜βŸ¨ Ο‰βŠ“πŸ™β‰‘Ο‰ ⟩
         Ο‰ βŠ“ πŸ™  ∎)
      , (Ο‰      β‰‘Λ˜βŸ¨ Ο‰βŠ“πŸ˜β‰‘Ο‰ ⟩
         Ο‰ βŠ“ 𝟘  ∎)
      , (Ξ» πŸ˜β‰‘πŸ˜βŠ“πŸ™ β†’ πŸ˜βŠ“πŸ™β‰’πŸ˜ (
           𝟘 βŠ“ πŸ™  β‰‘Λ˜βŸ¨ πŸ˜β‰‘πŸ˜βŠ“πŸ™ ⟩
           𝟘      ∎))
  where
  open Semiring-with-meet M using () renaming (_∧_ to _βŠ“_)
  open Tools.Reasoning.PropositionalEquality

-- The inferred ordering relation.

infix 10 _≀_

_≀_ : Zero-one-many β†’ Zero-one-many β†’ Set
p ≀ q = p ≑ p ∧ q

-- The quantity Ο‰ is smaller than all others.

ω≀ : βˆ€ p β†’ Ο‰ ≀ p
ω≀ _ = refl

-- 𝟘 is maximal.

𝟘-maximal : 𝟘 ≀ p β†’ p ≑ 𝟘
𝟘-maximal {p = Ο‰} ()
𝟘-maximal {p = 𝟘} refl = refl
𝟘-maximal {p = πŸ™}      = πŸ˜βˆ§πŸ™-elim
  (Ξ» q β†’ 𝟘 ≑ q β†’ πŸ™ ≑ 𝟘)
  (Ξ» _ β†’ sym)
  (Ξ» _ ())

-- 𝟘 is not below πŸ˜βˆ§πŸ™.

πŸ˜β‰°πŸ˜βˆ§πŸ™ : Β¬ 𝟘 ≀ πŸ˜βˆ§πŸ™
πŸ˜β‰°πŸ˜βˆ§πŸ™ = πŸ˜βˆ§πŸ™β‰’πŸ˜ βˆ˜β†’ 𝟘-maximal

-- If πŸ™β‰€πŸ˜ is true, then πŸ™Β β‰€Β πŸ˜.

πŸ™β‰€πŸ˜β†’πŸ™β‰€πŸ˜ : T πŸ™β‰€πŸ˜ β†’ πŸ™ ≀ 𝟘
πŸ™β‰€πŸ˜β†’πŸ™β‰€πŸ˜ πŸ™β‰€πŸ˜ =
  πŸ™      β‰‘Λ˜βŸ¨ πŸ˜βˆ§πŸ™β‰‘πŸ™ πŸ™β‰€πŸ˜ ⟩
  πŸ™ ∧ 𝟘  ∎
  where
  open Tools.Reasoning.PropositionalEquality

-- If πŸ™β‰€πŸ˜ is false, then πŸ™ is maximal.

πŸ™-maximal : Β¬ T πŸ™β‰€πŸ˜ β†’ πŸ™ ≀ p β†’ p ≑ πŸ™
πŸ™-maximal {p = Ο‰} _   ()
πŸ™-maximal {p = πŸ™} _   refl = refl
πŸ™-maximal {p = 𝟘} πŸ™β‰°πŸ˜ πŸ™β‰€πŸ˜  = βŠ₯-elim (
  case
    πŸ™      β‰‘βŸ¨ πŸ™β‰€πŸ˜ ⟩
    πŸ™ ∧ 𝟘  β‰‘βŸ¨ πŸ˜βˆ§πŸ™β‰‘Ο‰ πŸ™β‰°πŸ˜ ⟩
    Ο‰      ∎
  of Ξ» ())
  where
  open Tools.Reasoning.PropositionalEquality

opaque

  -- Non-zero grades are less than or equal to πŸ™

  β‰’πŸ˜β†’β‰€πŸ™ : βˆ€ p β†’ p β‰’ 𝟘 β†’ p ≀ πŸ™
  β‰’πŸ˜β†’β‰€πŸ™ 𝟘 pβ‰’πŸ˜ = βŠ₯-elim (pβ‰’πŸ˜ refl)
  β‰’πŸ˜β†’β‰€πŸ™ πŸ™ pβ‰’πŸ˜ = refl
  β‰’πŸ˜β†’β‰€πŸ™ Ο‰ pβ‰’πŸ˜ = refl

------------------------------------------------------------------------
-- Addition

-- Addition.

infixr 40 _+_

_+_ : Zero-one-many β†’ Zero-one-many β†’ Zero-one-many
𝟘 + q = q
πŸ™ + 𝟘 = πŸ™
_ + _ = Ο‰

-- If πŸ™β‰€πŸ˜ is true, then _+_ is decreasing in its left argument.

+-decreasingΛ‘ : T πŸ™β‰€πŸ˜ β†’ βˆ€ p q β†’ p + q ≀ p
+-decreasingΛ‘ πŸ™β‰€πŸ˜ = Ξ» where
  𝟘 𝟘 β†’ refl
  𝟘 πŸ™ β†’ πŸ™β‰€πŸ˜β†’πŸ™β‰€πŸ˜ πŸ™β‰€πŸ˜
  𝟘 Ο‰ β†’ refl
  πŸ™ 𝟘 β†’ refl
  πŸ™ πŸ™ β†’ refl
  πŸ™ Ο‰ β†’ refl
  Ο‰ _ β†’ refl

-- If πŸ™β‰€πŸ˜ is not true, then _+_ is not decreasing in its left argument.

Β¬-+-decreasingΛ‘ : Β¬ T πŸ™β‰€πŸ˜ β†’ Β¬ (βˆ€ p q β†’ p + q ≀ p)
Β¬-+-decreasingΛ‘ πŸ™β‰°πŸ˜ hyp =
  case πŸ™-maximal {p = 𝟘} πŸ™β‰°πŸ˜ (hyp 𝟘 πŸ™) of Ξ» ()

-- The sum of two non-zero values is Ο‰.

β‰’πŸ˜+β‰’πŸ˜ : p β‰’ 𝟘 β†’ q β‰’ 𝟘 β†’ p + q ≑ Ο‰
β‰’πŸ˜+β‰’πŸ˜ {p = 𝟘}         πŸ˜β‰’πŸ˜ _   = βŠ₯-elim (πŸ˜β‰’πŸ˜ refl)
β‰’πŸ˜+β‰’πŸ˜ {p = πŸ™} {q = 𝟘} _   πŸ˜β‰’πŸ˜ = βŠ₯-elim (πŸ˜β‰’πŸ˜ refl)
β‰’πŸ˜+β‰’πŸ˜ {p = πŸ™} {q = πŸ™} _   _   = refl
β‰’πŸ˜+β‰’πŸ˜ {p = πŸ™} {q = Ο‰} _   _   = refl
β‰’πŸ˜+β‰’πŸ˜ {p = Ο‰}         _   _   = refl

-- If pΒ +Β q is πŸ™, then either p is πŸ™ and q is 𝟘, or q is πŸ™ and p is 𝟘.

+β‰‘πŸ™ : p + q ≑ πŸ™ β†’ p ≑ πŸ™ Γ— q ≑ 𝟘 ⊎ p ≑ 𝟘 Γ— q ≑ πŸ™
+β‰‘πŸ™ {p = 𝟘} {q = πŸ™} refl = injβ‚‚ (refl , refl)
+β‰‘πŸ™ {p = πŸ™} {q = 𝟘} refl = inj₁ (refl , refl)
+β‰‘πŸ™ {p = 𝟘} {q = 𝟘} ()
+β‰‘πŸ™ {p = 𝟘} {q = Ο‰} ()
+β‰‘πŸ™ {p = πŸ™} {q = πŸ™} ()
+β‰‘πŸ™ {p = πŸ™} {q = Ο‰} ()
+β‰‘πŸ™ {p = Ο‰}         ()

-- The value Ο‰ is a right zero for _+_.

+-zeroΚ³ : RightZero Ο‰ _+_
+-zeroʳ 𝟘 = refl
+-zeroΚ³ πŸ™ = refl
+-zeroΚ³ Ο‰ = refl

-- The value Ο‰ is a zero for _+_.

+-zero : Zero Ο‰ _+_
+-zero = (Ξ» _ β†’ refl) , +-zeroΚ³

------------------------------------------------------------------------
-- Multiplication

-- Multiplication.

infixr 45 _Β·_

_Β·_ : Zero-one-many β†’ Zero-one-many β†’ Zero-one-many
𝟘 · _ = 𝟘
_ · 𝟘 = 𝟘
πŸ™ Β· πŸ™ = πŸ™
_ Β· _ = Ο‰

-- Multiplication is idempotent.

Β·-idempotent : Idempotent _Β·_
·-idempotent 𝟘 = refl
Β·-idempotent πŸ™ = refl
Β·-idempotent Ο‰ = refl

-- Multiplication is commutative.

Β·-comm : Commutative _Β·_
Β·-comm = Ξ» where
  𝟘 𝟘 β†’ refl
  𝟘 πŸ™ β†’ refl
  𝟘 Ο‰ β†’ refl
  πŸ™ 𝟘 β†’ refl
  πŸ™ πŸ™ β†’ refl
  πŸ™ Ο‰ β†’ refl
  Ο‰ 𝟘 β†’ refl
  Ο‰ πŸ™ β†’ refl
  Ο‰ Ο‰ β†’ refl

-- If p is not 𝟘, then ω · p is equal to Ο‰.

Ο‰Β·β‰’πŸ˜ : p β‰’ 𝟘 β†’ Ο‰ Β· p ≑ Ο‰
Ο‰Β·β‰’πŸ˜ {p = 𝟘} πŸ˜β‰’πŸ˜ = βŠ₯-elim (πŸ˜β‰’πŸ˜ refl)
Ο‰Β·β‰’πŸ˜ {p = πŸ™} _   = refl
Ο‰Β·β‰’πŸ˜ {p = Ο‰} _   = refl

opaque

  -- If p is not 𝟘, then pΒ Β·Β Ο‰ is equal to Ο‰.

  β‰’πŸ˜Β·Ο‰ : p β‰’ 𝟘 β†’ p Β· Ο‰ ≑ Ο‰
  β‰’πŸ˜Β·Ο‰ {(𝟘)} πŸ˜β‰’πŸ˜ = βŠ₯-elim (πŸ˜β‰’πŸ˜ refl)
  β‰’πŸ˜Β·Ο‰ {(πŸ™)} _ = refl
  β‰’πŸ˜Β·Ο‰ {(Ο‰)} _ = refl

-- If p is not 𝟘, then πŸ™Β Β·Β p is not 𝟘.

πŸ™Β·β‰’πŸ˜ : p β‰’ 𝟘 β†’ πŸ™ Β· p β‰’ 𝟘
πŸ™Β·β‰’πŸ˜ {p = 𝟘} πŸ˜β‰’πŸ˜ = πŸ˜β‰’πŸ˜
πŸ™Β·β‰’πŸ˜ {p = πŸ™} πŸ™β‰’πŸ˜ = πŸ™β‰’πŸ˜
πŸ™Β·β‰’πŸ˜ {p = Ο‰} Ο‰β‰’πŸ˜ = Ο‰β‰’πŸ˜

-- The value of ω · p is notΒ πŸ™.

Ο‰Β·β‰’πŸ™ : Ο‰ Β· p β‰’ πŸ™
Ο‰Β·β‰’πŸ™ {p = 𝟘} ()
Ο‰Β·β‰’πŸ™ {p = πŸ™} ()
Ο‰Β·β‰’πŸ™ {p = Ο‰} ()

opaque

  -- The grade ω · (pΒ +Β q) is bounded by ω · q.

  ω·+≀ω·ʳ : βˆ€ p β†’ Ο‰ Β· (p + q) ≀ Ο‰ Β· q
  ω·+≀ω·ʳ {q = 𝟘} 𝟘 = refl
  ω·+≀ω·ʳ {q = πŸ™} 𝟘 = refl
  ω·+≀ω·ʳ {q = Ο‰} 𝟘 = refl
  ω·+≀ω·ʳ {q = 𝟘} πŸ™ = refl
  ω·+≀ω·ʳ {q = πŸ™} πŸ™ = refl
  ω·+≀ω·ʳ {q = Ο‰} πŸ™ = refl
  ω·+≀ω·ʳ         Ο‰ = refl

------------------------------------------------------------------------
-- The modality without the star operation

-- The zero-one-many semiring with meet

zero-one-many-semiring-with-meet : Semiring-with-meet
zero-one-many-semiring-with-meet = record
  { _+_          = _+_
  ; _Β·_          = _Β·_
  ; _∧_          = _∧_
  ; 𝟘            = 𝟘
  ; πŸ™            = πŸ™
  ; Ο‰            = Ο‰
  ; Ο‰β‰€πŸ™          = refl
  ; ω·+≀ω·ʳ      = Ξ» {p = p} β†’ ω·+≀ω·ʳ p
  ; is-𝟘?        = _β‰Ÿ 𝟘
  ; +-Β·-Semiring = record
    { isSemiringWithoutAnnihilatingZero = record
      { +-isCommutativeMonoid = record
        { isMonoid = record
          { isSemigroup = record
            { isMagma = record
              { isEquivalence = PE.isEquivalence
              ; βˆ™-cong = congβ‚‚ _+_
              }
            ; assoc = Ξ» where
                𝟘 _ _ β†’ refl
                πŸ™ 𝟘 _ β†’ refl
                πŸ™ πŸ™ 𝟘 β†’ refl
                πŸ™ πŸ™ πŸ™ β†’ refl
                πŸ™ πŸ™ Ο‰ β†’ refl
                πŸ™ Ο‰ _ β†’ refl
                Ο‰ _ _ β†’ refl
            }
          ; identity =
                (Ξ» _ β†’ refl)
              , comm∧idΛ‘β‡’idΚ³ +-comm (Ξ» _ β†’ refl)
          }
        ; comm = +-comm
        }
        ; *-cong = congβ‚‚ _Β·_
        ; *-assoc = Ξ» where
              𝟘 _ _ β†’ refl
              πŸ™ 𝟘 _ β†’ refl
              πŸ™ πŸ™ 𝟘 β†’ refl
              πŸ™ πŸ™ πŸ™ β†’ refl
              πŸ™ πŸ™ Ο‰ β†’ refl
              πŸ™ Ο‰ 𝟘 β†’ refl
              πŸ™ Ο‰ πŸ™ β†’ refl
              πŸ™ Ο‰ Ο‰ β†’ refl
              Ο‰ 𝟘 _ β†’ refl
              Ο‰ πŸ™ 𝟘 β†’ refl
              Ο‰ πŸ™ πŸ™ β†’ refl
              Ο‰ πŸ™ Ο‰ β†’ refl
              Ο‰ Ο‰ 𝟘 β†’ refl
              Ο‰ Ο‰ πŸ™ β†’ refl
              Ο‰ Ο‰ Ο‰ β†’ refl
        ; *-identity =
                Β·-identityΛ‘
              , comm∧idΛ‘β‡’idΚ³ Β·-comm Β·-identityΛ‘
      ; distrib =
            Β·-distrib-+Λ‘
          , comm∧distrΛ‘β‡’distrΚ³ Β·-comm Β·-distrib-+Λ‘
      }
    ; zero =
          (Ξ» _ β†’ refl)
        , comm∧zeΛ‘β‡’zeΚ³ Β·-comm (Ξ» _ β†’ refl)
    }
  ; ∧-Semilattice = record
    { isBand = record
      { isSemigroup = record
        { isMagma = record
          { isEquivalence = PE.isEquivalence
          ; βˆ™-cong        = congβ‚‚ _∧_
          }
        ; assoc = Ξ» where
            𝟘 𝟘 𝟘 β†’ refl
            𝟘 𝟘 πŸ™ β†’
              πŸ˜βˆ§πŸ™      β‰‘Λ˜βŸ¨ 𝟘∧[πŸ˜βˆ§πŸ™] ⟩
              𝟘 ∧ πŸ˜βˆ§πŸ™  ∎
            𝟘 𝟘 Ο‰ β†’ refl
            𝟘 πŸ™ 𝟘 β†’
              πŸ˜βˆ§πŸ™ ∧ 𝟘  β‰‘βŸ¨βŸ©
              πŸ˜βˆ§πŸ™ ∧ 𝟘  β‰‘βŸ¨ ∧-comm πŸ˜βˆ§πŸ™ _ ⟩
              𝟘 ∧ πŸ˜βˆ§πŸ™  ∎
            𝟘 πŸ™ πŸ™ β†’
              πŸ˜βˆ§πŸ™ ∧ πŸ™  β‰‘βŸ¨ ∧-comm πŸ˜βˆ§πŸ™ _ ⟩
              πŸ™ ∧ πŸ˜βˆ§πŸ™  β‰‘βŸ¨ πŸ™βˆ§[πŸ˜βˆ§πŸ™] ⟩
              πŸ˜βˆ§πŸ™      ∎
            𝟘 πŸ™ Ο‰ β†’
              πŸ˜βˆ§πŸ™ ∧ Ο‰  β‰‘βŸ¨ ∧-comm πŸ˜βˆ§πŸ™ _ ⟩
              Ο‰ ∧ πŸ˜βˆ§πŸ™  β‰‘βŸ¨βŸ©
              Ο‰        ∎
            𝟘 Ο‰ _ β†’ refl
            πŸ™ 𝟘 𝟘 β†’
              πŸ˜βˆ§πŸ™ ∧ 𝟘  β‰‘βŸ¨ ∧-comm πŸ˜βˆ§πŸ™ _ ⟩
              𝟘 ∧ πŸ˜βˆ§πŸ™  β‰‘βŸ¨ 𝟘∧[πŸ˜βˆ§πŸ™] ⟩
              πŸ˜βˆ§πŸ™      ∎
            πŸ™ 𝟘 πŸ™ β†’
              πŸ˜βˆ§πŸ™ ∧ πŸ™  β‰‘βŸ¨βŸ©
              πŸ˜βˆ§πŸ™ ∧ πŸ™  β‰‘βŸ¨ ∧-comm πŸ˜βˆ§πŸ™ _ ⟩
              πŸ™ ∧ πŸ˜βˆ§πŸ™  ∎
            πŸ™ 𝟘 Ο‰ β†’
              πŸ˜βˆ§πŸ™ ∧ Ο‰  β‰‘βŸ¨ ∧-comm πŸ˜βˆ§πŸ™ _ ⟩
              Ο‰ ∧ πŸ˜βˆ§πŸ™  β‰‘βŸ¨βŸ©
              Ο‰        ∎
            πŸ™ πŸ™ 𝟘 β†’
              πŸ˜βˆ§πŸ™      β‰‘Λ˜βŸ¨ πŸ™βˆ§[πŸ˜βˆ§πŸ™] ⟩
              πŸ™ ∧ πŸ˜βˆ§πŸ™  ∎
            πŸ™ πŸ™ πŸ™ β†’ refl
            πŸ™ πŸ™ Ο‰ β†’ refl
            πŸ™ Ο‰ _ β†’ refl
            Ο‰ _ _ β†’ refl
        }
      ; idem = Ξ» where
          𝟘 β†’ refl
          πŸ™ β†’ refl
          Ο‰ β†’ refl
      }
    ; comm = ∧-comm
    }
  ; ·-distrib-∧ =
        ·-distrib-∧ˑ
      , comm∧distrΛ‘β‡’distrΚ³ Β·-comm Β·-distrib-∧ˑ
  ; +-distrib-∧ =
        +-distrib-∧ˑ
      , comm∧distrΛ‘β‡’distrΚ³ +-comm +-distrib-∧ˑ
  }
  where
  open Tools.Reasoning.PropositionalEquality

  +-comm : Commutative _+_
  +-comm = Ξ» where
    𝟘 𝟘 β†’ refl
    𝟘 πŸ™ β†’ refl
    𝟘 Ο‰ β†’ refl
    πŸ™ 𝟘 β†’ refl
    πŸ™ πŸ™ β†’ refl
    πŸ™ Ο‰ β†’ refl
    Ο‰ 𝟘 β†’ refl
    Ο‰ πŸ™ β†’ refl
    Ο‰ Ο‰ β†’ refl

  Β·-identityΛ‘ : LeftIdentity πŸ™ _Β·_
  Β·-identityΛ‘ = Ξ» where
    𝟘 β†’ refl
    πŸ™ β†’ refl
    Ο‰ β†’ refl

  Β·-distrib-+Λ‘ : _Β·_ DistributesOverΛ‘ _+_
  Β·-distrib-+Λ‘ = Ξ» where
    𝟘 _ _ β†’ refl
    πŸ™ 𝟘 _ β†’ refl
    πŸ™ πŸ™ 𝟘 β†’ refl
    πŸ™ πŸ™ πŸ™ β†’ refl
    πŸ™ πŸ™ Ο‰ β†’ refl
    πŸ™ Ο‰ _ β†’ refl
    Ο‰ 𝟘 _ β†’ refl
    Ο‰ πŸ™ 𝟘 β†’ refl
    Ο‰ πŸ™ πŸ™ β†’ refl
    Ο‰ πŸ™ Ο‰ β†’ refl
    Ο‰ Ο‰ _ β†’ refl

  ∧-comm : Commutative _∧_
  ∧-comm = λ where
    𝟘 𝟘 β†’ refl
    𝟘 πŸ™ β†’ refl
    𝟘 Ο‰ β†’ refl
    πŸ™ 𝟘 β†’ refl
    πŸ™ πŸ™ β†’ refl
    πŸ™ Ο‰ β†’ refl
    Ο‰ 𝟘 β†’ refl
    Ο‰ πŸ™ β†’ refl
    Ο‰ Ο‰ β†’ refl

  ·-distrib-∧ˑ : _·_ DistributesOverˑ _∧_
  ·-distrib-∧ˑ = λ where
    𝟘 _ _ β†’ refl
    πŸ™ 𝟘 𝟘 β†’ refl
    πŸ™ 𝟘 πŸ™ β†’
      πŸ™ Β· πŸ˜βˆ§πŸ™  β‰‘βŸ¨ Β·-identityΛ‘ _ ⟩
      πŸ˜βˆ§πŸ™      ∎
    πŸ™ 𝟘 Ο‰ β†’ refl
    πŸ™ πŸ™ 𝟘 β†’
      πŸ™ Β· πŸ˜βˆ§πŸ™  β‰‘βŸ¨ Β·-identityΛ‘ _ ⟩
      πŸ˜βˆ§πŸ™      ∎
    πŸ™ πŸ™ πŸ™ β†’ refl
    πŸ™ πŸ™ Ο‰ β†’ refl
    πŸ™ Ο‰ _ β†’ refl
    Ο‰ 𝟘 𝟘 β†’ refl
    Ο‰ 𝟘 πŸ™ β†’
      Ο‰ Β· πŸ˜βˆ§πŸ™  β‰‘βŸ¨ Ο‰Β·β‰’πŸ˜ πŸ˜βˆ§πŸ™β‰’πŸ˜ ⟩
      Ο‰        ∎
    Ο‰ 𝟘 Ο‰ β†’ refl
    Ο‰ πŸ™ 𝟘 β†’
      Ο‰ Β· πŸ˜βˆ§πŸ™  β‰‘βŸ¨ Ο‰Β·β‰’πŸ˜ πŸ˜βˆ§πŸ™β‰’πŸ˜ ⟩
      Ο‰        ∎
    Ο‰ πŸ™ πŸ™ β†’ refl
    Ο‰ πŸ™ Ο‰ β†’ refl
    Ο‰ Ο‰ _ β†’ refl

  +-distrib-∧ˑ : _+_ DistributesOverˑ _∧_
  +-distrib-∧ˑ = λ where
    𝟘 _ _ β†’ refl
    πŸ™ 𝟘 𝟘 β†’ refl
    πŸ™ 𝟘 πŸ™ β†’
      πŸ™ + πŸ˜βˆ§πŸ™  β‰‘βŸ¨ β‰’πŸ˜+β‰’πŸ˜ (Ξ» ()) πŸ˜βˆ§πŸ™β‰’πŸ˜ ⟩
      Ο‰        ∎
    πŸ™ 𝟘 Ο‰ β†’ refl
    πŸ™ πŸ™ 𝟘 β†’
      πŸ™ + πŸ˜βˆ§πŸ™  β‰‘βŸ¨ β‰’πŸ˜+β‰’πŸ˜ (Ξ» ()) πŸ˜βˆ§πŸ™β‰’πŸ˜ ⟩
      Ο‰        ∎
    πŸ™ πŸ™ πŸ™ β†’ refl
    πŸ™ πŸ™ Ο‰ β†’ refl
    πŸ™ Ο‰ _ β†’ refl
    Ο‰ _ _ β†’ refl

instance

  zero-one-many-has-well-behaved-zero :
    Has-well-behaved-zero zero-one-many-semiring-with-meet
  zero-one-many-has-well-behaved-zero = record
    { non-trivial = Ξ» ()
    ; zero-product =  Ξ» where
        {p = 𝟘}         _  β†’ inj₁ refl
        {q = 𝟘}         _  β†’ injβ‚‚ refl
        {p = πŸ™} {q = πŸ™} ()
        {p = πŸ™} {q = Ο‰} ()
        {p = Ο‰} {q = πŸ™} ()
        {p = Ο‰} {q = Ο‰} ()
    ; +-positiveΛ‘ =  Ξ» where
        {p = 𝟘} {q = 𝟘} _  β†’ refl
        {p = 𝟘} {q = πŸ™} ()
        {p = 𝟘} {q = Ο‰} ()
        {p = πŸ™} {q = 𝟘} ()
        {p = πŸ™} {q = πŸ™} ()
        {p = πŸ™} {q = Ο‰} ()
        {p = Ο‰}         ()
    ; ∧-positiveˑ = λ where
        {p = 𝟘} {q = 𝟘} _     β†’ refl
        {p = 𝟘} {q = πŸ™} _     β†’ refl
        {p = πŸ™} {q = 𝟘} πŸ˜βˆ§πŸ™β‰‘πŸ˜ β†’
          βŠ₯-elim (
            case
              πŸ™  β‰‘βŸ¨ 𝟘-maximal (sym πŸ˜βˆ§πŸ™β‰‘πŸ˜) ⟩
              𝟘  ∎
            of Ξ» ())
        {p = 𝟘} {q = Ο‰} ()
        {p = πŸ™} {q = πŸ™} ()
        {p = πŸ™} {q = Ο‰} ()
        {p = Ο‰}         ()
    }
    where open Tools.Reasoning.PropositionalEquality

------------------------------------------------------------------------
-- Star

-- Some requirements of a star operation and a meet operation.

Star-requirements :
  (Zero-one-many β†’ Zero-one-many β†’ Zero-one-many β†’ Zero-one-many) β†’
  (Zero-one-many β†’ Zero-one-many β†’ Zero-one-many) β†’
  Set
Star-requirements _βŠ›_β–·_ _∧_ =
  let _≀_ : Zero-one-many β†’ Zero-one-many β†’ Set
      p ≀ q = p ≑ (p ∧ q)
  in
  (βˆ€ {q r} β†’                     (Ο‰ βŠ› q β–· r) ≑ Ο‰) Γ—
  (βˆ€ {p r} β†’                     (p βŠ› Ο‰ β–· r) ≑ Ο‰) Γ—
  (βˆ€ {p q} β†’ Β¬ (p ≑ 𝟘 Γ— q ≑ 𝟘) β†’ (p βŠ› q β–· Ο‰) ≑ Ο‰) Γ—
  (βˆ€ {r} β†’                       (𝟘 βŠ› 𝟘 β–· r) ≑ 𝟘) Γ—
  (βˆ€ {p} β†’                       (p βŠ› πŸ™ β–· πŸ™) ≑ Ο‰) Γ—
                                ((𝟘 βŠ› πŸ™ β–· 𝟘) ≀ (𝟘 ∧ πŸ™)) Γ—
                                ((πŸ™ βŠ› 𝟘 β–· 𝟘) ≀ (𝟘 ∧ πŸ™)) Γ—
                                ((πŸ™ βŠ› 𝟘 β–· πŸ™) ≀ πŸ™) Γ—
                                ((πŸ™ βŠ› πŸ™ β–· 𝟘) ≀ πŸ™)

-- A star operation for a Semiring-with-meet for Zero-one-many for
-- which the zero is 𝟘, the one is πŸ™, addition is _+_, multiplication
-- is _·_, and the meet operation is _∧_ has to satisfy the
-- Star-requirements (for _∧_) if certain conditions are satisfied.

Star-requirements-requiredβ€² :
  (M : Semiring-with-meet) β†’
  Semiring-with-meet.𝟘   M ≑ 𝟘 β†’
  Semiring-with-meet.πŸ™   M ≑ πŸ™ β†’
  Semiring-with-meet._+_ M ≑ _+_ β†’
  Semiring-with-meet._Β·_ M ≑ _Β·_ β†’
  Semiring-with-meet._∧_ M ≑ _∧_ β†’
  (_βŠ›_β–·_ :
   Zero-one-many β†’ Zero-one-many β†’ Zero-one-many β†’ Zero-one-many) β†’
  (βˆ€ p q r β†’ (p βŠ› q β–· r) ≀ q + r Β· (p βŠ› q β–· r)) β†’
  (βˆ€ p q r β†’ (p βŠ› q β–· r) ≀ p) β†’
  (βˆ€ r β†’ _Β·_ SubDistributesOverΚ³ (_βŠ›_β–· r) by _≀_) β†’
  Star-requirements _βŠ›_β–·_ _∧_
Star-requirements-requiredβ€²
  M@record{} refl refl refl refl refl star βŠ›-ineq₁ βŠ›-ineqβ‚‚
  Β·-sub-distribΚ³-βŠ› =
  case Meet-requirements-required M refl refl πŸ˜βˆ§πŸ™β‰’πŸ˜ ω≀ of Ξ» where
    (_ , _ , Ο‰βŠ“Ο‰β‰‘Ο‰ , _ , Ο‰βŠ“πŸ˜β‰‘Ο‰ , _ , Ο‰βŠ“πŸ™β‰‘Ο‰ , _ , _) β†’
        (Ξ» {_ _} β†’ Ο‰βŠ›β–·)
      , (Ξ» {_ _} β†’ βŠ›Ο‰β–·)
      , (Ξ» {_ _} β†’ βŠ›β–·Ο‰ _ _)
      , (Ξ» {r = r} β†’ ≀-antisym
           (begin
              𝟘 βŠ› 𝟘 β–· r  β‰€βŸ¨ βŠ›-ineqβ‚‚ _ _ _ ⟩
              𝟘          ∎)
           (begin
              𝟘              β‰‘Λ˜βŸ¨ Β·-zeroΚ³ _ ⟩
              𝟘 βŠ› 𝟘 β–· r Β· 𝟘  β‰€βŸ¨ Β·-sub-distribΚ³-βŠ› _ _ _ _ ⟩
              𝟘 βŠ› 𝟘 β–· r      ∎))
      , (Ξ» {p = p} β†’ ≀-antisym
           (begin
              p βŠ› πŸ™ β–· πŸ™          β‰€βŸ¨ βŠ›-ineq₁ _ _ _ ⟩
              πŸ™ + πŸ™ Β· p βŠ› πŸ™ β–· πŸ™  β‰ˆβŸ¨ β‰’πŸ˜+β‰’πŸ˜ (Ξ» ()) (πŸ™Β·β‰’πŸ˜ βŠ›πŸ™β–·) ⟩
              Ο‰                  ∎)
           (ω≀ (p βŠ› πŸ™ β–· πŸ™)))
      , ∧-greatest-lower-bound
          (βŠ›-ineqβ‚‚ _ _ _)
          (begin
             𝟘 βŠ› πŸ™ β–· 𝟘          β‰€βŸ¨ βŠ›-ineq₁ _ _ _ ⟩
             πŸ™ + 𝟘 Β· 𝟘 βŠ› πŸ™ β–· 𝟘  β‰‘βŸ¨βŸ©
             πŸ™                  ∎)
      , ∧-greatest-lower-bound
          (begin
             πŸ™ βŠ› 𝟘 β–· 𝟘          β‰€βŸ¨ βŠ›-ineq₁ _ _ _ ⟩
             𝟘 + 𝟘 Β· πŸ™ βŠ› 𝟘 β–· 𝟘  β‰‘βŸ¨βŸ©
             𝟘                  ∎)
          (βŠ›-ineqβ‚‚ _ _ _)
      , βŠ›-ineqβ‚‚ _ _ _
      , βŠ›-ineqβ‚‚ _ _ _
  where
  open Semiring-with-meet M hiding (𝟘; πŸ™; Ο‰; _+_; _Β·_; _∧_; _≀_)
  open PartialOrder M
  open Meet M
  open Tools.Reasoning.PartialOrder ≀-poset

  infix 50 _βŠ›_β–·_

  _βŠ›_β–·_ : Zero-one-many β†’ Zero-one-many β†’ Zero-one-many β†’ Zero-one-many
  _βŠ›_β–·_ = star

  Ο‰βŠ›β–· : Ο‰ βŠ› q β–· r ≑ Ο‰
  Ο‰βŠ›β–· {q = q} {r = r} = ≀-antisym
    (begin
       Ο‰ βŠ› q β–· r  β‰€βŸ¨ βŠ›-ineqβ‚‚ _ _ _ ⟩
       Ο‰          ∎)
    (ω≀ (Ο‰ βŠ› q β–· r))

  βŠ›Ο‰β–· : p βŠ› Ο‰ β–· r ≑ Ο‰
  βŠ›Ο‰β–· {p = p} {r = r} = ≀-antisym
    (begin
       p βŠ› Ο‰ β–· r          β‰€βŸ¨ βŠ›-ineq₁ _ _ _ ⟩
       Ο‰ + r Β· p βŠ› Ο‰ β–· r  β‰‘βŸ¨βŸ©
       Ο‰                  ∎)
    (ω≀ (p βŠ› Ο‰ β–· r))

  πŸ™βŠ›β–· : πŸ™ βŠ› q β–· r β‰’ 𝟘
  πŸ™βŠ›β–· {q = q} {r = r} πŸ™βŠ›β–·β‰‘πŸ˜ =
    case begin
      𝟘              β‰‘βŸ¨βŸ©
      𝟘 Β· Ο‰          β‰‘Λ˜βŸ¨ Β·-congΚ³ πŸ™βŠ›β–·β‰‘πŸ˜ ⟩
      πŸ™ βŠ› q β–· r Β· Ο‰  β‰€βŸ¨ Β·-sub-distribΚ³-βŠ› _ _ _ _ ⟩
      Ο‰ βŠ› q Β· Ο‰ β–· r  β‰‘βŸ¨ Ο‰βŠ›β–· ⟩
      Ο‰              ∎
    of Ξ» ()

  βŠ›πŸ™β–· : p βŠ› πŸ™ β–· r β‰’ 𝟘
  βŠ›πŸ™β–· {p = p} {r = r} βŠ›πŸ™β–·β‰‘πŸ˜ =
    case begin
      𝟘                β‰‘βŸ¨βŸ©
      𝟘 Β· Ο‰            β‰‘Λ˜βŸ¨ Β·-congΚ³ βŠ›πŸ™β–·β‰‘πŸ˜ ⟩
      p βŠ› πŸ™ β–· r Β· Ο‰    β‰€βŸ¨ Β·-sub-distribΚ³-βŠ› _ _ _ _ ⟩
      (p Β· Ο‰) βŠ› Ο‰ β–· r  β‰‘βŸ¨ βŠ›Ο‰β–· ⟩
      Ο‰                ∎
    of Ξ» ()

  βŠ›β–·Ο‰ : βˆ€ p q β†’ Β¬ (p ≑ 𝟘 Γ— q ≑ 𝟘) β†’ (p βŠ› q β–· Ο‰) ≑ Ο‰
  βŠ›β–·Ο‰ _ Ο‰ _      = βŠ›Ο‰β–·
  βŠ›β–·Ο‰ Ο‰ _ _      = Ο‰βŠ›β–·
  βŠ›β–·Ο‰ 𝟘 𝟘 Β¬β‰‘πŸ˜Γ—β‰‘πŸ˜ = βŠ₯-elim (Β¬β‰‘πŸ˜Γ—β‰‘πŸ˜ (refl , refl))
  βŠ›β–·Ο‰ p πŸ™ _      = ≀-antisym
    (begin
       p βŠ› πŸ™ β–· Ο‰          β‰€βŸ¨ βŠ›-ineq₁ _ _ _ ⟩
       πŸ™ + Ο‰ Β· p βŠ› πŸ™ β–· Ο‰  β‰ˆβŸ¨ +-congΛ‘ (Ο‰Β·β‰’πŸ˜ βŠ›πŸ™β–·) ⟩
       πŸ™ + Ο‰              β‰‘βŸ¨βŸ©
       Ο‰                  ∎)
    (ω≀ (p βŠ› πŸ™ β–· Ο‰))
  βŠ›β–·Ο‰ πŸ™ 𝟘 _ = ≀-antisym
    (begin
       πŸ™ βŠ› 𝟘 β–· Ο‰      β‰€βŸ¨ βŠ›-ineq₁ _ _ _ ⟩
       Ο‰ Β· πŸ™ βŠ› 𝟘 β–· Ο‰  β‰ˆβŸ¨ Ο‰Β·β‰’πŸ˜ πŸ™βŠ›β–· ⟩
       Ο‰              ∎)
    (ω≀ (πŸ™ βŠ› 𝟘 β–· Ο‰))

-- Every natrec-star operator for zero-one-many-semiring-with-meet has
-- to satisfy the Star-requirements (for _∧_).

Star-requirements-required :
  (has-star : Has-star zero-one-many-semiring-with-meet) β†’
  Star-requirements (Has-star._βŠ›_β–·_ has-star) _∧_
Star-requirements-required has-star =
  Star-requirements-requiredβ€²
    zero-one-many-semiring-with-meet refl refl refl refl refl
    _βŠ›_β–·_
    βŠ›-ineq₁
    βŠ›-ineqβ‚‚
    Β·-sub-distribΚ³-βŠ›
  where
  open Has-star has-star

------------------------------------------------------------------------
-- One variant of the modality

-- A natrec-star operator defined using the construction in
-- Graded.Modality.Instances.LowerBounded.

zero-one-many-lower-bounded-star :
  Has-star zero-one-many-semiring-with-meet
zero-one-many-lower-bounded-star =
  LowerBounded.has-star zero-one-many-semiring-with-meet Ο‰ ω≀

-- With this definition the result of pΒ βŠ›Β qΒ β–·Β r is 𝟘 when p and q are
-- 𝟘, and Ο‰ otherwise.

zero-one-many-lower-bounded-βŠ› :
  let open Has-star zero-one-many-lower-bounded-star in
  (βˆ€ r β†’ 𝟘 βŠ› 𝟘 β–· r ≑ 𝟘) Γ—
  (βˆ€ p q r β†’ Β¬ (p ≑ 𝟘 Γ— q ≑ 𝟘) β†’ p βŠ› q β–· r ≑ Ο‰)
zero-one-many-lower-bounded-βŠ› =
    (Ξ» _ β†’ refl)
  , (Ξ» where
       𝟘 𝟘 _ Β¬β‰‘πŸ˜Γ—β‰‘πŸ˜ β†’ βŠ₯-elim (Β¬β‰‘πŸ˜Γ—β‰‘πŸ˜ (refl , refl))
       𝟘 πŸ™ _ _      β†’
         Ο‰ Β· πŸ˜βˆ§πŸ™  β‰‘βŸ¨ Ο‰Β·β‰’πŸ˜ πŸ˜βˆ§πŸ™β‰’πŸ˜ ⟩
         Ο‰        ∎
       𝟘 Ο‰ _ _ β†’ refl
       πŸ™ 𝟘 _ _ β†’
         Ο‰ Β· πŸ˜βˆ§πŸ™  β‰‘βŸ¨ Ο‰Β·β‰’πŸ˜ πŸ˜βˆ§πŸ™β‰’πŸ˜ ⟩
         Ο‰        ∎
       πŸ™ πŸ™ _ _ β†’ refl
       πŸ™ Ο‰ _ _ β†’ refl
       Ο‰ _ _ _ β†’ refl)
  where
  open Has-star zero-one-many-lower-bounded-star
  open Tools.Reasoning.PropositionalEquality

------------------------------------------------------------------------
-- A variant of the modality with a "greatest" star operation

-- A "greatest" definition of the star operation.

infix 50 _βŠ›_β–·_

_βŠ›_β–·_ : Zero-one-many β†’ Zero-one-many β†’ Zero-one-many β†’ Zero-one-many
p βŠ› q β–· 𝟘 = p ∧ q
p βŠ› q β–· πŸ™ = p + Ο‰ Β· q
p βŠ› q β–· Ο‰ = Ο‰ Β· (p ∧ q)

-- This definition is not equal to the one obtained from
-- zero-one-many-lower-bounded-star.

lower-bounded≒greatest :
  Has-star._βŠ›_β–·_ zero-one-many-lower-bounded-star β‰’ _βŠ›_β–·_
lower-bounded≒greatest hyp =
  case cong (Ξ» f β†’ f πŸ™ πŸ™ 𝟘) hyp of Ξ» ()

-- A simplification lemma for the star operation.

Ο‰βŠ›β–· : βˆ€ r β†’ Ο‰ βŠ› q β–· r ≑ Ο‰
Ο‰βŠ›β–· 𝟘 = refl
Ο‰βŠ›β–· πŸ™ = refl
Ο‰βŠ›β–· Ο‰ = refl

-- A simplification lemma for the star operation.

βŠ›Ο‰β–· : βˆ€ r β†’ p βŠ› Ο‰ β–· r ≑ Ο‰
βŠ›Ο‰β–· {p = p} = Ξ» where
    𝟘 β†’
      p ∧ Ο‰  β‰‘βŸ¨ M.∧-comm p _ ⟩
      Ο‰ ∧ p  β‰‘βŸ¨βŸ©
      Ο‰      ∎
    πŸ™ β†’
      p + Ο‰  β‰‘βŸ¨ M.+-comm p _ ⟩
      Ο‰ + p  β‰‘βŸ¨βŸ©
      Ο‰      ∎
    Ο‰ β†’
      Ο‰ Β· (p ∧ Ο‰)  β‰‘βŸ¨ cong (_ Β·_) (M.∧-comm p _) ⟩
      Ο‰ Β· (Ο‰ ∧ p)  β‰‘βŸ¨βŸ©
      Ο‰            ∎
  where
  open Tools.Reasoning.PropositionalEquality
  module M = Semiring-with-meet zero-one-many-semiring-with-meet

-- A simplification lemma for the star operation.

πŸ˜βŠ›πŸ˜β–· : βˆ€ r β†’ 𝟘 βŠ› 𝟘 β–· r ≑ 𝟘
πŸ˜βŠ›πŸ˜β–· 𝟘 = refl
πŸ˜βŠ›πŸ˜β–· πŸ™ = refl
πŸ˜βŠ›πŸ˜β–· Ο‰ = refl

-- A simplification lemma for the star operation.

βŠ›β–·Ο‰ : βˆ€ p q β†’ Β¬ (p ≑ 𝟘 Γ— q ≑ 𝟘) β†’ (p βŠ› q β–· Ο‰) ≑ Ο‰
βŠ›β–·Ο‰ p Ο‰ _      = βŠ›Ο‰β–· {p = p} Ο‰
βŠ›β–·Ο‰ Ο‰ _ _      = refl
βŠ›β–·Ο‰ 𝟘 𝟘 Β¬β‰‘πŸ˜Γ—β‰‘πŸ˜ = βŠ₯-elim (Β¬β‰‘πŸ˜Γ—β‰‘πŸ˜ (refl , refl))
βŠ›β–·Ο‰ 𝟘 πŸ™ _      = Ο‰Β·β‰’πŸ˜ πŸ˜βˆ§πŸ™β‰’πŸ˜
βŠ›β–·Ο‰ πŸ™ πŸ™ _      = refl
βŠ›β–·Ο‰ πŸ™ 𝟘 _      = Ο‰Β·β‰’πŸ˜ πŸ˜βˆ§πŸ™β‰’πŸ˜

-- A simplification lemma for the star operation.

βŠ›πŸ™β–·πŸ™ : βˆ€ p β†’ p βŠ› πŸ™ β–· πŸ™ ≑ Ο‰
βŠ›πŸ™β–·πŸ™ 𝟘 = refl
βŠ›πŸ™β–·πŸ™ πŸ™ = refl
βŠ›πŸ™β–·πŸ™ Ο‰ = refl

-- A simplification lemma for the star operation.

βŠ›πŸ˜βˆ§πŸ™β–·πŸ™ : βˆ€ p β†’ p βŠ› πŸ˜βˆ§πŸ™ β–· πŸ™ ≑ Ο‰
βŠ›πŸ˜βˆ§πŸ™β–·πŸ™ 𝟘 = πŸ˜βˆ§πŸ™-elim (Ξ» q β†’ 𝟘 βŠ› q β–· πŸ™ ≑ Ο‰) (Ξ» _ β†’ refl) (Ξ» _ β†’ refl)
βŠ›πŸ˜βˆ§πŸ™β–·πŸ™ πŸ™ = πŸ˜βˆ§πŸ™-elim (Ξ» q β†’ πŸ™ βŠ› q β–· πŸ™ ≑ Ο‰) (Ξ» _ β†’ refl) (Ξ» _ β†’ refl)
βŠ›πŸ˜βˆ§πŸ™β–·πŸ™ Ο‰ = refl

-- A simplification lemma for the star operation.

πŸ˜βŠ›πŸ˜βˆ§πŸ™β–·πŸ˜ : 𝟘 βŠ› πŸ˜βˆ§πŸ™ β–· 𝟘 ≑ πŸ˜βˆ§πŸ™
πŸ˜βŠ›πŸ˜βˆ§πŸ™β–·πŸ˜ = πŸ˜βˆ§πŸ™-elim
  (Ξ» q β†’ 𝟘 βŠ› q β–· 𝟘 ≑ q)
  (Ξ» πŸ˜βˆ§πŸ™β‰‘πŸ™ β†’ πŸ˜βˆ§πŸ™β‰‘πŸ™)
  (Ξ» _ β†’ refl)

-- A simplification lemma for the star operation.

πŸ™βŠ›πŸ˜βˆ§πŸ™β–·πŸ˜ : πŸ™ βŠ› πŸ˜βˆ§πŸ™ β–· 𝟘 ≑ πŸ˜βˆ§πŸ™
πŸ™βŠ›πŸ˜βˆ§πŸ™β–·πŸ˜ = πŸ˜βˆ§πŸ™-elim
  (Ξ» q β†’ πŸ™ βŠ› q β–· 𝟘 ≑ q)
  (Ξ» _ β†’ refl)
  (Ξ» _ β†’ refl)

-- The natrec-star operator returns results that are at least as large
-- as those of any other natrec-star operator for
-- zero-one-many-semiring-with-meet.

βŠ›-greatest :
  (has-star : Has-star zero-one-many-semiring-with-meet) β†’
  βˆ€ p q r β†’ Has-star._βŠ›_β–·_ has-star p q r ≀ p βŠ› q β–· r
βŠ›-greatest has-star =
  case Star-requirements-required has-star of Ξ» where
    (Ο‰βŠ›β–·β€² , βŠ›Ο‰β–·β€² , βŠ›β–·β€²Ο‰ ,
     πŸ˜βŠ›πŸ˜β–·β€² , βŠ›πŸ™β–·β€²πŸ™ , πŸ˜βŠ›πŸ™β–·β€²πŸ˜ , πŸ™βŠ›πŸ˜β–·β€²πŸ˜ , πŸ™βŠ›πŸ˜β–·β€²πŸ™ , πŸ™βŠ›πŸ™β–·β€²πŸ˜) β†’ Ξ» where
      Ο‰ q r β†’ begin
        Ο‰ βŠ› q β–·β€² r  β‰ˆβŸ¨ Ο‰βŠ›β–·β€² ⟩
        Ο‰           β‰ˆΛ˜βŸ¨ Ο‰βŠ›β–· r ⟩
        Ο‰ βŠ› q β–· r   ∎
      p Ο‰ r β†’ begin
        p βŠ› Ο‰ β–·β€² r  β‰ˆβŸ¨ βŠ›Ο‰β–·β€² ⟩
        Ο‰           β‰ˆΛ˜βŸ¨ βŠ›Ο‰β–· r ⟩
        p βŠ› Ο‰ β–· r   ∎
      𝟘 𝟘 r β†’ begin
        𝟘 βŠ› 𝟘 β–·β€² r  β‰ˆβŸ¨ πŸ˜βŠ›πŸ˜β–·β€² ⟩
        𝟘           β‰ˆΛ˜βŸ¨ πŸ˜βŠ›πŸ˜β–· r ⟩
        𝟘 βŠ› 𝟘 β–· r   ∎
      𝟘 πŸ™ Ο‰ β†’ begin
        𝟘 βŠ› πŸ™ β–·β€² Ο‰  β‰ˆβŸ¨ βŠ›β–·β€²Ο‰ (Ξ» { (_ , ()) }) ⟩
        Ο‰           β‰ˆΛ˜βŸ¨ βŠ›β–·Ο‰ 𝟘 πŸ™ (Ξ» { (_ , ()) }) ⟩
        𝟘 βŠ› πŸ™ β–· Ο‰   ∎
      πŸ™ q Ο‰ β†’ begin
        πŸ™ βŠ› q β–·β€² Ο‰  β‰ˆβŸ¨ βŠ›β–·β€²Ο‰ (Ξ» { (() , _) }) ⟩
        Ο‰           β‰ˆΛ˜βŸ¨ βŠ›β–·Ο‰ πŸ™ q (Ξ» { (() , _) }) ⟩
        πŸ™ βŠ› q β–· Ο‰   ∎
      p πŸ™ πŸ™ β†’ begin
        p βŠ› πŸ™ β–·β€² πŸ™  β‰ˆβŸ¨ βŠ›πŸ™β–·β€²πŸ™ ⟩
        Ο‰           β‰ˆΛ˜βŸ¨ βŠ›πŸ™β–·πŸ™ p ⟩
        p βŠ› πŸ™ β–· πŸ™   ∎
      𝟘 πŸ™ 𝟘 β†’ begin
        𝟘 βŠ› πŸ™ β–·β€² 𝟘  β‰€βŸ¨ πŸ˜βŠ›πŸ™β–·β€²πŸ˜ ⟩
        𝟘 ∧ πŸ™       ∎
      πŸ™ 𝟘 𝟘 β†’ begin
        πŸ™ βŠ› 𝟘 β–·β€² 𝟘  β‰€βŸ¨ πŸ™βŠ›πŸ˜β–·β€²πŸ˜ ⟩
        𝟘 ∧ πŸ™       ∎
      πŸ™ 𝟘 πŸ™ β†’ begin
        πŸ™ βŠ› 𝟘 β–·β€² πŸ™  β‰€βŸ¨ πŸ™βŠ›πŸ˜β–·β€²πŸ™ ⟩
        πŸ™           ∎
      πŸ™ πŸ™ 𝟘 β†’ begin
        πŸ™ βŠ› πŸ™ β–·β€² 𝟘  β‰€βŸ¨ πŸ™βŠ›πŸ™β–·β€²πŸ˜ ⟩
        πŸ™           ∎
  where
  open Has-star has-star renaming (_βŠ›_β–·_ to _βŠ›_β–·β€²_)
  open PartialOrder zero-one-many-semiring-with-meet
  open Tools.Reasoning.PartialOrder ≀-poset

-- The "greatest" star operator defined above is a proper natrec-star
-- operator.

zero-one-many-greatest-star : Has-star zero-one-many-semiring-with-meet
zero-one-many-greatest-star = record
  { _βŠ›_β–·_                   = _βŠ›_β–·_
  ; βŠ›-ineq                  = βŠ›-ineq₁ , βŠ›-ineqβ‚‚
  ; +-sub-interchangeable-βŠ› = +-sub-interchangeable-βŠ›
  ; Β·-sub-distribΚ³-βŠ›        = Ξ» r _ _ _ β†’
                                ≀-reflexive (Β·-distribΚ³-βŠ› r _ _ _)
  ; βŠ›-sub-distrib-∧         = Ξ» r β†’
      (Ξ» _ _ _ β†’ ≀-reflexive (βŠ›-distribΛ‘-∧ r _ _ _))
    , (Ξ» _ _ _ β†’ ≀-reflexive (βŠ›-distribΚ³-∧ r _ _ _))
  }
  where
  semiring-with-meet = zero-one-many-semiring-with-meet

  open Semiring-with-meet semiring-with-meet
    hiding (𝟘; πŸ™; Ο‰; _+_; _Β·_; _∧_; _≀_)
  open PartialOrder semiring-with-meet
  open Addition semiring-with-meet
  open Meet semiring-with-meet
  open Multiplication semiring-with-meet

  βŠ›-ineq₁ : βˆ€ p q r β†’ p βŠ› q β–· r ≀ q + r Β· p βŠ› q β–· r
  βŠ›-ineq₁ p = Ξ» where
      q 𝟘 β†’ begin
        p ∧ q  β‰€βŸ¨ ∧-decreasingΚ³ p _ ⟩
        q      β‰ˆΛ˜βŸ¨ +-identityΚ³ _ ⟩
        q + 𝟘  ∎
      𝟘 πŸ™ β†’ begin
        p βŠ› 𝟘 β–· πŸ™      β‰ˆΛ˜βŸ¨ Β·-identityΛ‘ _ ⟩
        πŸ™ Β· p βŠ› 𝟘 β–· πŸ™  ∎
      πŸ™ πŸ™ β†’ begin
        p + Ο‰            β‰ˆβŸ¨ +-zeroΚ³ _ ⟩
        Ο‰                β‰‘βŸ¨βŸ©
        πŸ™ + πŸ™ Β· Ο‰        β‰ˆΛ˜βŸ¨ cong (Ξ» p β†’ πŸ™ + πŸ™ Β· p) (+-zeroΚ³ p) ⟩
        πŸ™ + πŸ™ Β· (p + Ο‰)  ∎
      Ο‰ πŸ™ β†’ begin
        p + Ο‰  β‰ˆβŸ¨ +-zeroΚ³ _ ⟩
        Ο‰      ∎
      𝟘 Ο‰ β†’ begin
        Ο‰ Β· (p ∧ 𝟘)        β‰‘βŸ¨βŸ©
        (Ο‰ Β· Ο‰) Β· (p ∧ 𝟘)  β‰ˆβŸ¨ Β·-assoc _ _ _ ⟩
        Ο‰ Β· Ο‰ Β· (p ∧ 𝟘)    ∎
      πŸ™ Ο‰ β†’ begin
        Ο‰ Β· (p ∧ πŸ™)          β‰ˆβŸ¨ Β·-distribΛ‘-∧ _ p _ ⟩
        Ο‰ Β· p ∧ Ο‰            β‰ˆβŸ¨ ∧-comm (Ο‰ Β· p) _ ⟩
        Ο‰ ∧ Ο‰ Β· p            β‰‘βŸ¨βŸ©
        Ο‰                    β‰‘βŸ¨βŸ©
        πŸ™ + Ο‰ Β· Ο‰            β‰ˆβŸ¨ cong (Ξ» p β†’ _ + Ο‰ Β· p) (∧-comm _ (Ο‰ Β· p)) ⟩
        πŸ™ + Ο‰ Β· (Ο‰ Β· p ∧ Ο‰)  β‰ˆΛ˜βŸ¨ cong (Ξ» p β†’ _ + Ο‰ Β· p) (Β·-distribΛ‘-∧ Ο‰ p _) ⟩
        πŸ™ + Ο‰ Β· Ο‰ Β· (p ∧ πŸ™)  ∎
      Ο‰ Ο‰ β†’ begin
        Ο‰ Β· (p ∧ Ο‰)  β‰ˆβŸ¨ Β·-distribΛ‘-∧ _ p _ ⟩
        Ο‰ Β· p ∧ Ο‰    β‰€βŸ¨ ∧-decreasingΚ³ (Ο‰ Β· p) _ ⟩
        Ο‰            ∎
    where
    open Tools.Reasoning.PartialOrder ≀-poset

  βŠ›-ineqβ‚‚ : βˆ€ p q r β†’ (p βŠ› q β–· r) ≀ p
  βŠ›-ineqβ‚‚ p = Ξ» where
      q 𝟘 β†’ begin
        p ∧ q  β‰€βŸ¨ ∧-decreasingΛ‘ p _ ⟩
        p      ∎
      𝟘 πŸ™ β†’ begin
        p + 𝟘  β‰ˆβŸ¨ +-identityΚ³ _ ⟩
        p      ∎
      πŸ™ πŸ™ β†’ begin
        p + Ο‰  β‰ˆβŸ¨ +-zeroΚ³ _ ⟩
        Ο‰      β‰€βŸ¨ ω≀ p ⟩
        p      ∎
      Ο‰ πŸ™ β†’ begin
        p + Ο‰  β‰ˆβŸ¨ +-zeroΚ³ _ ⟩
        Ο‰      β‰€βŸ¨ ω≀ p ⟩
        p      ∎
      q Ο‰ β†’ begin
        Ο‰ Β· (p ∧ q)    β‰ˆβŸ¨ Β·-distribΛ‘-∧ _ p _ ⟩
        Ο‰ Β· p ∧ Ο‰ Β· q  β‰€βŸ¨ ∧-decreasingΛ‘ (Ο‰ Β· p) _ ⟩
        Ο‰ Β· p          β‰€βŸ¨ Β·-monotoneΛ‘ (ω≀ πŸ™) ⟩
        πŸ™ Β· p          β‰ˆβŸ¨ Β·-identityΛ‘ _ ⟩
        p              ∎
    where
    open Tools.Reasoning.PartialOrder ≀-poset

  +-sub-interchangeable-βŠ› : βˆ€ r β†’ _+_ SubInterchangeable (_βŠ›_β–· r) by _≀_
  +-sub-interchangeable-βŠ› = Ξ» where
      𝟘 p q pβ€² qβ€² β†’ begin
        (p ∧ q) + (pβ€² ∧ qβ€²)  β‰€βŸ¨ +-sub-interchangeable-∧ p _ _ _ ⟩
        (p + pβ€²) ∧ (q + qβ€²)  ∎
      πŸ™ p q pβ€² qβ€² β†’ begin
        (p + Ο‰ Β· q) + (pβ€² + Ο‰ Β· qβ€²)  β‰ˆβŸ¨ +-assoc p _ _ ⟩
        p + (Ο‰ Β· q + (pβ€² + Ο‰ Β· qβ€²))  β‰ˆΛ˜βŸ¨ cong (p +_) (+-assoc (Ο‰ Β· q) _ _) ⟩
        p + ((Ο‰ Β· q + pβ€²) + Ο‰ Β· qβ€²)  β‰ˆβŸ¨ cong (Ξ» q β†’ p + (q + _)) (+-comm _ pβ€²) ⟩
        p + ((pβ€² + Ο‰ Β· q) + Ο‰ Β· qβ€²)  β‰ˆβŸ¨ cong (p +_) (+-assoc pβ€² _ _) ⟩
        p + (pβ€² + (Ο‰ Β· q + Ο‰ Β· qβ€²))  β‰ˆΛ˜βŸ¨ +-assoc p _ _ ⟩
        (p + pβ€²) + (Ο‰ Β· q + Ο‰ Β· qβ€²)  β‰ˆΛ˜βŸ¨ cong (_ +_) (Β·-distribΛ‘-+ Ο‰ q _) ⟩
        (p + pβ€²) + Ο‰ Β· (q + qβ€²)      ∎
      Ο‰ p q pβ€² qβ€² β†’ begin
        Ο‰ Β· (p ∧ q) + Ο‰ Β· (pβ€² ∧ qβ€²)  β‰ˆΛ˜βŸ¨ Β·-distribΛ‘-+ Ο‰ (p ∧ q) (pβ€² ∧ qβ€²) ⟩
        Ο‰ Β· ((p ∧ q) + (pβ€² ∧ qβ€²))    β‰€βŸ¨ Β·-monotoneΚ³ (+-sub-interchangeable-∧ p q pβ€² qβ€²) ⟩
        Ο‰ Β· ((p + pβ€²) ∧ (q + qβ€²))    ∎
    where
    open Tools.Reasoning.PartialOrder ≀-poset

  Β·-distribΚ³-βŠ› : βˆ€ r β†’ _Β·_ DistributesOverΚ³ (_βŠ›_β–· r)
  Β·-distribΚ³-βŠ› = Ξ» where
      𝟘 q p pβ€² β†’
        (p ∧ pβ€²) Β· q    β‰‘βŸ¨ Β·-distribΚ³-∧ _ p _ ⟩
        p Β· q ∧ pβ€² Β· q  ∎
      πŸ™ q p pβ€² β†’
        (p + Ο‰ Β· pβ€²) Β· q      β‰‘βŸ¨ Β·-distribΚ³-+ _ p _ ⟩
        p Β· q + (Ο‰ Β· pβ€²) Β· q  β‰‘βŸ¨ cong (_ +_) (Β·-assoc Ο‰ pβ€² _) ⟩
        p Β· q + Ο‰ Β· pβ€² Β· q    ∎
      Ο‰ q p pβ€² β†’
        (Ο‰ Β· (p ∧ pβ€²)) Β· q    β‰‘βŸ¨ Β·-assoc _ _ _ ⟩
        Ο‰ Β· (p ∧ pβ€²) Β· q      β‰‘βŸ¨ cong (_ Β·_) (Β·-distribΚ³-∧ _ p _) ⟩
        Ο‰ Β· (p Β· q ∧ pβ€² Β· q)  ∎
    where
    open Tools.Reasoning.PropositionalEquality

  βŠ›-distribΛ‘-∧ : βˆ€ r β†’ (_βŠ›_β–· r) DistributesOverΛ‘ _∧_
  βŠ›-distribΛ‘-∧ = Ξ» where
      𝟘 p _ _ β†’
        lemma p _ _
      πŸ™ p q qβ€² β†’
        p + Ο‰ Β· (q ∧ qβ€²)            β‰‘βŸ¨ cong (_ +_) (Β·-distribΛ‘-∧ Ο‰ q _) ⟩
        p + (Ο‰ Β· q ∧ Ο‰ Β· qβ€²)        β‰‘βŸ¨ +-distribΛ‘-∧ p _ _ ⟩
        (p + Ο‰ Β· q) ∧ (p + Ο‰ Β· qβ€²)  ∎
      Ο‰ p q qβ€² β†’
        Ο‰ Β· (p ∧ q ∧ qβ€²)            β‰‘βŸ¨ cong (_ Β·_) (lemma p _ _) ⟩
        Ο‰ Β· ((p ∧ q) ∧ (p ∧ qβ€²))    β‰‘βŸ¨ Β·-distribΛ‘-∧ Ο‰ (p ∧ _) _ ⟩
        Ο‰ Β· (p ∧ q) ∧ Ο‰ Β· (p ∧ qβ€²)  ∎
    where
    open Tools.Reasoning.PropositionalEquality

    lemma = Ξ» p q qβ€² β†’
      p ∧ (q ∧ qβ€²)        β‰‘Λ˜βŸ¨ cong (_∧ _) (∧-idem p) ⟩
      (p ∧ p) ∧ (q ∧ qβ€²)  β‰‘βŸ¨ ∧-assoc p _ _ ⟩
      p ∧ (p ∧ (q ∧ qβ€²))  β‰‘Λ˜βŸ¨ cong (p ∧_) (∧-assoc p _ _) ⟩
      p ∧ ((p ∧ q) ∧ qβ€²)  β‰‘βŸ¨ cong (Ξ» q β†’ p ∧ (q ∧ _)) (∧-comm p _) ⟩
      p ∧ ((q ∧ p) ∧ qβ€²)  β‰‘βŸ¨ cong (p ∧_) (∧-assoc q _ _) ⟩
      p ∧ (q ∧ (p ∧ qβ€²))  β‰‘Λ˜βŸ¨ ∧-assoc p _ _ ⟩
      (p ∧ q) ∧ (p ∧ qβ€²)  ∎

  βŠ›-distribΚ³-∧ : βˆ€ r β†’ (_βŠ›_β–· r) DistributesOverΚ³ _∧_
  βŠ›-distribΚ³-∧ = Ξ» where
      𝟘 q p pβ€² β†’
        lemma _ p _
      πŸ™ q p pβ€² β†’
        (p ∧ pβ€²) + Ο‰ Β· q            β‰‘βŸ¨ +-distribΚ³-∧ _ p _ ⟩
        (p + Ο‰ Β· q) ∧ (pβ€² + Ο‰ Β· q)  ∎
      Ο‰ q p pβ€² β†’
        Ο‰ Β· ((p ∧ pβ€²) ∧ q)          β‰‘βŸ¨ cong (_ Β·_) (lemma _ p _) ⟩
        Ο‰ Β· ((p ∧ q) ∧ (pβ€² ∧ q))    β‰‘βŸ¨ Β·-distribΛ‘-∧ Ο‰ (p ∧ _) _ ⟩
        Ο‰ Β· (p ∧ q) ∧ Ο‰ Β· (pβ€² ∧ q)  ∎
    where
    open Tools.Reasoning.PropositionalEquality

    lemma = Ξ» q p pβ€² β†’
      (p ∧ pβ€²) ∧ q        β‰‘βŸ¨ ∧-comm _ q ⟩
      q ∧ (p ∧ pβ€²)        β‰‘βŸ¨ βŠ›-distribΛ‘-∧ 𝟘 q _ _ ⟩
      (q ∧ p) ∧ (q ∧ pβ€²)  β‰‘βŸ¨ congβ‚‚ _∧_ (∧-comm q _) (∧-comm q _) ⟩
      (p ∧ q) ∧ (pβ€² ∧ q)  ∎

-- The natrec-star operator obtained from
-- zero-one-many-lower-bounded-star is not the (pointwise) greatest
-- one.

Β¬-lower-bounded-greatest :
  Β¬ ((has-star : Has-star zero-one-many-semiring-with-meet) β†’
     βˆ€ p q r β†’
     Has-star._βŠ›_β–·_ has-star                         p q r ≀
     Has-star._βŠ›_β–·_ zero-one-many-lower-bounded-star p q r)
Β¬-lower-bounded-greatest hyp =
  case hyp zero-one-many-greatest-star πŸ™ πŸ™ 𝟘 of Ξ» ()

-- The "greatest" natrec-star operator defined above provides a
-- possible nr function.

zero-one-many-greatest-star-nr : Has-nr zero-one-many-semiring-with-meet
zero-one-many-greatest-star-nr =
  Star.has-nr _ ⦃ has-star = zero-one-many-greatest-star ⦄

opaque

  -- The nr function given by the "greatest" natrec-star operator does
  -- not give a "factoring" nr function.

  Β¬zero-one-many-greatest-star-factoring-nr :
    Β¬ Is-factoring-nr zero-one-many-greatest-star-nr
  Β¬zero-one-many-greatest-star-factoring-nr factoring = case πŸ™β‰‘Ο‰ of Ξ» ()
    where
    open Has-nr zero-one-many-greatest-star-nr
    open Is-factoring-nr factoring
    open Semiring-with-meet zero-one-many-semiring-with-meet
      hiding (𝟘; πŸ™; Ο‰; _+_; _Β·_)
    open Tools.Reasoning.PropositionalEquality
    πŸ™β‰‘Ο‰ : πŸ™ ≑ Ο‰
    πŸ™β‰‘Ο‰ = begin
      πŸ™                            β‰‘βŸ¨βŸ©
      nr 𝟘 πŸ™ πŸ™ 𝟘 πŸ™                β‰‘βŸ¨ nr-factoring {z = πŸ™} {s = 𝟘} ⟩
      nrβ‚‚ 𝟘 πŸ™ Β· πŸ™ + nr 𝟘 πŸ™ πŸ™ 𝟘 𝟘 β‰‘βŸ¨βŸ©
      nrβ‚‚ 𝟘 πŸ™ Β· πŸ™ + πŸ˜βˆ§πŸ™ + 𝟘       β‰‘βŸ¨ +-cong (Β·-identityΚ³ _) (+-identityΚ³ πŸ˜βˆ§πŸ™) ⟩
      nrβ‚‚ 𝟘 πŸ™ + πŸ˜βˆ§πŸ™               β‰‘βŸ¨ β‰’πŸ˜+β‰’πŸ˜ nrβ‚‚β‰’πŸ˜ πŸ˜βˆ§πŸ™β‰’πŸ˜ ⟩
      Ο‰ ∎

------------------------------------------------------------------------
-- A variant of the modality with a custom nr function

-- An nr function for Zero-one-many.
--
-- The value of nr p 𝟘 z s n is defined in the following way:
--
-- * If pΒ =Β πŸ™, then there are no (non-erased) recursive calls, and the
--   argument is used exactly once in the successor case (excluding
--   erased uses):
--
--     f zero    = f_z
--     f (suc m) = f_s m
--
--   Let us use nΒ +Β z for the zero case, and nΒ +Β s for the successor
--   case: the result is a conservative approximation of these two
--   values (their meet).
--
-- * If p = 𝟘, then there are no (non-erased) recursive
--   calls, and the argument is not used (in non-erased positions) in
--   the successor case:
--
--     f zero    = f_z
--     f (suc m) = f_s
--
--   Let us again use nΒ +Β z for the zero case. If affine types are
--   used, then we use nΒ +Β s for the successor case again, but if
--   linear types are used, then we use ω · nΒ +Β s: the argument is not
--   used linearly in the successor case, because it is not used at
--   all, so if n is πŸ™, then the result should be Ο‰ (not πŸ™, because
--   the function is not linear, and not 𝟘, because that would amount
--   to an erased match on a natural number).
--
-- * If pΒ =Β Ο‰, then there are no (non-erased) recursive calls. In the
--   successor case the argument is used an unlimited number of times,
--   so we use ω · nΒ +Β s. In the zero case we use nΒ +Β z, as before.
--
-- All of these cases can be expressed in the following way (note that
-- πŸ™Β βˆ§Β πŸ˜ is πŸ™ for affine types and Ο‰ for linear types):
--
--   nr p 𝟘 z s n = ((πŸ™ ∧ p) Β· n + s) ∧ (n + z)
--
-- The value of nrΒ pΒ πŸ™Β zΒ sΒ n is defined in the following way:
--
-- * If p = 𝟘, then we have linear or affine recursion: the argument
--   is used linearly or affinely (n), the successor case can occur an
--   unlimited number of times (ω · s), and the zero case occurs at
--   most once (z).
--
-- * If pΒ =Β πŸ™ or pΒ =Β Ο‰, then there is recursion (ω · s), the argument
--   can be used in each recursive call (ω · n), and the zero case
--   occurs at most once (z).
--
-- We get the following definition:
--
--   nr p πŸ™ z s n = (πŸ™ + p) Β· n + Ο‰ Β· s + z
--
-- Finally we use the following definition for nrΒ p ω zΒ sΒ n:
--
--   nr _ Ο‰ z s n = Ο‰ Β· (n + s + z)
--
-- There is recursion (ω · s), in the successor case there can be
-- multiple recursive calls (ω · n), and the zero case can occur
-- multiple times (ω · z).

nr :
  Zero-one-many β†’ Zero-one-many β†’
  Zero-one-many β†’ Zero-one-many β†’ Zero-one-many β†’ Zero-one-many
nr p 𝟘 z s n = ((πŸ™ ∧ p) Β· n + s) ∧ (n + z)
nr p πŸ™ z s n = (πŸ™ + p) Β· n + Ο‰ Β· s + z
nr _ Ο‰ z s n = Ο‰ Β· (n + s + z)

-- An alternative implementation of nr.

nrβ€² :
  Zero-one-many β†’ Zero-one-many β†’
  Zero-one-many β†’ Zero-one-many β†’ Zero-one-many β†’ Zero-one-many
nrβ€² _ _ 𝟘 𝟘 𝟘 = 𝟘
nrβ€² _ 𝟘 πŸ™ πŸ™ 𝟘 = πŸ™
nrβ€² _ 𝟘 πŸ™ 𝟘 𝟘 = πŸ™ ∧ 𝟘
nrβ€² _ πŸ™ πŸ™ 𝟘 𝟘 = πŸ™
nrβ€² _ 𝟘 𝟘 πŸ™ 𝟘 = πŸ™ ∧ 𝟘
nrβ€² πŸ™ 𝟘 𝟘 𝟘 πŸ™ = πŸ™
nrβ€² 𝟘 𝟘 𝟘 𝟘 πŸ™ = πŸ™ ∧ 𝟘
nrβ€² 𝟘 πŸ™ 𝟘 𝟘 πŸ™ = πŸ™
nrβ€² _ _ _ _ _ = Ο‰

-- A type used in the implementation of Nr.

data Nr-Ο‰ : (p r z s n : Zero-one-many) β†’ Set where
  nr≑ω₁  : Nr-Ο‰ p r Ο‰ s n
  nr≑ω₂  : Nr-Ο‰ p r z Ο‰ n
  nr≑ω₃  : Nr-Ο‰ p r z s Ο‰
  nr≑ω₄  : Nr-Ο‰ p Ο‰ πŸ™ s n
  nr≑ω₅  : Nr-Ο‰ p Ο‰ 𝟘 πŸ™ n
  nr≑ω₆  : Nr-Ο‰ p Ο‰ 𝟘 𝟘 πŸ™
  nr≑ω₇  : Nr-Ο‰ Ο‰ 𝟘 𝟘 𝟘 πŸ™
  nrβ‰‘Ο‰β‚ˆ  : Nr-Ο‰ Ο‰ πŸ™ 𝟘 𝟘 πŸ™
  nr≑ω₉  : Nr-Ο‰ πŸ™ πŸ™ 𝟘 𝟘 πŸ™
  nr≑ω₁₀ : Nr-Ο‰ p 𝟘 𝟘 πŸ™ πŸ™
  nr≑ω₁₁ : Nr-Ο‰ p πŸ™ z πŸ™ n
  nr≑ω₁₂ : Nr-Ο‰ p 𝟘 πŸ™ s πŸ™
  nr≑ω₁₃ : Nr-Ο‰ p πŸ™ πŸ™ 𝟘 πŸ™

-- Another type used in the implementation of Nr.

data Nr-πŸ™βˆ§πŸ˜ : (p r z s n : Zero-one-many) β†’ Set where
  nrβ‰‘πŸ™βˆ§πŸ˜β‚ : Nr-πŸ™βˆ§πŸ˜ p 𝟘 πŸ™ 𝟘 𝟘
  nrβ‰‘πŸ™βˆ§πŸ˜β‚‚ : Nr-πŸ™βˆ§πŸ˜ p 𝟘 𝟘 πŸ™ 𝟘
  nrβ‰‘πŸ™βˆ§πŸ˜β‚ƒ : Nr-πŸ™βˆ§πŸ˜ 𝟘 𝟘 𝟘 𝟘 πŸ™

-- A view of the functions nr and nrβ€².

data Nr : (p r z s n result : Zero-one-many) β†’ Set where
  nrβ‰‘πŸ˜   :                    result ≑ 𝟘     β†’ Nr p r 𝟘 𝟘 𝟘 result
  nrβ‰‘πŸ™β‚  :                    result ≑ πŸ™     β†’ Nr p 𝟘 πŸ™ πŸ™ 𝟘 result
  nrβ‰‘πŸ™β‚‚  :                    result ≑ πŸ™     β†’ Nr p πŸ™ πŸ™ 𝟘 𝟘 result
  nrβ‰‘πŸ™β‚ƒ  :                                     Nr πŸ™ 𝟘 𝟘 𝟘 πŸ™ πŸ™
  nrβ‰‘πŸ™β‚„  :                                     Nr 𝟘 πŸ™ 𝟘 𝟘 πŸ™ πŸ™
  nrβ‰‘πŸ™βˆ§πŸ˜ : Nr-πŸ™βˆ§πŸ˜ p r z s n β†’ result ≑ πŸ™ ∧ 𝟘 β†’ Nr p r z s n result
  nr≑ω   : Nr-Ο‰ p r z s n   β†’ result ≑ Ο‰     β†’ Nr p r z s n result

-- The view is correctly defined for nrβ€².

nrβ€²-view : βˆ€ p r z s n β†’ Nr p r z s n (nrβ€² p r z s n)
nrβ€²-view = Ξ» where
  _ _ 𝟘 𝟘 𝟘 β†’ nrβ‰‘πŸ˜ refl
  _ 𝟘 πŸ™ πŸ™ 𝟘 β†’ nrβ‰‘πŸ™β‚ refl
  _ πŸ™ πŸ™ 𝟘 𝟘 β†’ nrβ‰‘πŸ™β‚‚ refl
  πŸ™ 𝟘 𝟘 𝟘 πŸ™ β†’ nrβ‰‘πŸ™β‚ƒ
  𝟘 πŸ™ 𝟘 𝟘 πŸ™ β†’ nrβ‰‘πŸ™β‚„
  _ 𝟘 πŸ™ 𝟘 𝟘 β†’ nrβ‰‘πŸ™βˆ§πŸ˜ nrβ‰‘πŸ™βˆ§πŸ˜β‚ refl
  _ 𝟘 𝟘 πŸ™ 𝟘 β†’ nrβ‰‘πŸ™βˆ§πŸ˜ nrβ‰‘πŸ™βˆ§πŸ˜β‚‚ refl
  𝟘 𝟘 𝟘 𝟘 πŸ™ β†’ nrβ‰‘πŸ™βˆ§πŸ˜ nrβ‰‘πŸ™βˆ§πŸ˜β‚ƒ refl
  _ _ Ο‰ _ _ β†’ nr≑ω nr≑ω₁ refl
  _ _ 𝟘 Ο‰ _ β†’ nr≑ω nr≑ω₂ refl
  _ 𝟘 πŸ™ Ο‰ _ β†’ nr≑ω nr≑ω₂ refl
  _ πŸ™ πŸ™ Ο‰ _ β†’ nr≑ω nr≑ω₂ refl
  _ _ 𝟘 𝟘 Ο‰ β†’ nr≑ω nr≑ω₃ refl
  _ 𝟘 𝟘 πŸ™ Ο‰ β†’ nr≑ω nr≑ω₃ refl
  _ 𝟘 πŸ™ 𝟘 Ο‰ β†’ nr≑ω nr≑ω₃ refl
  _ πŸ™ πŸ™ 𝟘 Ο‰ β†’ nr≑ω nr≑ω₃ refl
  _ 𝟘 πŸ™ πŸ™ Ο‰ β†’ nr≑ω nr≑ω₃ refl
  _ Ο‰ πŸ™ _ _ β†’ nr≑ω nr≑ω₄ refl
  _ Ο‰ 𝟘 πŸ™ _ β†’ nr≑ω nr≑ω₅ refl
  𝟘 Ο‰ 𝟘 𝟘 πŸ™ β†’ nr≑ω nr≑ω₆ refl
  πŸ™ Ο‰ 𝟘 𝟘 πŸ™ β†’ nr≑ω nr≑ω₆ refl
  Ο‰ Ο‰ 𝟘 𝟘 πŸ™ β†’ nr≑ω nr≑ω₆ refl
  Ο‰ 𝟘 𝟘 𝟘 πŸ™ β†’ nr≑ω nr≑ω₇ refl
  Ο‰ πŸ™ 𝟘 𝟘 πŸ™ β†’ nr≑ω nrβ‰‘Ο‰β‚ˆ refl
  πŸ™ πŸ™ 𝟘 𝟘 πŸ™ β†’ nr≑ω nr≑ω₉ refl
  _ 𝟘 𝟘 πŸ™ πŸ™ β†’ nr≑ω nr≑ω₁₀ refl
  _ πŸ™ 𝟘 πŸ™ _ β†’ nr≑ω nr≑ω₁₁ refl
  _ πŸ™ πŸ™ πŸ™ _ β†’ nr≑ω nr≑ω₁₁ refl
  _ 𝟘 πŸ™ 𝟘 πŸ™ β†’ nr≑ω nr≑ω₁₂ refl
  _ 𝟘 πŸ™ πŸ™ πŸ™ β†’ nr≑ω nr≑ω₁₂ refl
  _ πŸ™ πŸ™ 𝟘 πŸ™ β†’ nr≑ω nr≑ω₁₃ refl

-- The functions nr and nrβ€² are pointwise equal.

nr≑nrβ€² : βˆ€ p r β†’ nr p r z s n ≑ nrβ€² p r z s n
nr≑nrβ€² p r = lemma _ _ _ _ _ (nrβ€²-view p r _ _ _)
  where
  open Semiring-with-meet zero-one-many-semiring-with-meet
    hiding (𝟘; πŸ™; Ο‰; _+_; _Β·_; _∧_)
  open Tools.Reasoning.PropositionalEquality

  lemma :
    βˆ€ p r z s n β†’ Nr p r z s n (nrβ€² p r z s n) β†’
    nr p r z s n ≑ nrβ€² p r z s n
  lemma p 𝟘 .𝟘 .𝟘 .𝟘 (nrβ‰‘πŸ˜ _) =
    ((πŸ™ ∧ p) Β· 𝟘 + 𝟘) ∧ 𝟘  β‰‘βŸ¨ cong (_∧ _) (+-identityΚ³ ((πŸ™ ∧ p) Β· _)) ⟩
    ((πŸ™ ∧ p) Β· 𝟘) ∧ 𝟘      β‰‘βŸ¨ cong (_∧ _) (Β·-zeroΚ³ (πŸ™ ∧ p)) ⟩
    𝟘 ∧ 𝟘                  β‰‘βŸ¨βŸ©
    𝟘                      ∎
  lemma p πŸ™ .𝟘 .𝟘 .𝟘 (nrβ‰‘πŸ˜ _) =
    (πŸ™ + p) Β· 𝟘 + 𝟘  β‰‘βŸ¨ +-identityΚ³ _ ⟩
    (πŸ™ + p) Β· 𝟘      β‰‘βŸ¨ Β·-zeroΚ³ _ ⟩
    𝟘                ∎
  lemma _ Ο‰ .𝟘 .𝟘 .𝟘 (nrβ‰‘πŸ˜ _) =
    𝟘  ∎
  lemma p .𝟘 .πŸ™ .πŸ™ .𝟘 (nrβ‰‘πŸ™β‚ _) =
    ((πŸ™ ∧ p) Β· 𝟘 + πŸ™) ∧ πŸ™  β‰‘βŸ¨ cong ((_∧ _) βˆ˜β†’ (_+ _)) (Β·-zeroΚ³ (πŸ™ ∧ p)) ⟩
    (𝟘 + πŸ™) ∧ πŸ™            β‰‘βŸ¨βŸ©
    πŸ™                      ∎
  lemma p .πŸ™ .πŸ™ .𝟘 .𝟘 (nrβ‰‘πŸ™β‚‚ _) =
    (πŸ™ + p) Β· 𝟘 + πŸ™  β‰‘βŸ¨ cong (_+ _) (Β·-zeroΚ³ (πŸ™ + p)) ⟩
    𝟘 + πŸ™            β‰‘βŸ¨βŸ©
    πŸ™                ∎
  lemma .πŸ™ .𝟘 .𝟘 .𝟘 .πŸ™ nrβ‰‘πŸ™β‚ƒ =
    πŸ™  ∎
  lemma .𝟘 .πŸ™ .𝟘 .𝟘 .πŸ™ nrβ‰‘πŸ™β‚„ =
    πŸ™  ∎
  lemma p .𝟘 .πŸ™ .𝟘 .𝟘 (nrβ‰‘πŸ™βˆ§πŸ˜ nrβ‰‘πŸ™βˆ§πŸ˜β‚ _) =
    ((πŸ™ ∧ p) Β· 𝟘 + 𝟘) ∧ πŸ™  β‰‘βŸ¨ cong (_∧ _) (+-identityΚ³ ((πŸ™ ∧ p) Β· _)) ⟩
    ((πŸ™ ∧ p) Β· 𝟘) ∧ πŸ™      β‰‘βŸ¨ cong (_∧ _) (Β·-zeroΚ³ (πŸ™ ∧ p)) ⟩
    𝟘 ∧ πŸ™                  ∎
  lemma p .𝟘 .𝟘 .πŸ™ .𝟘 (nrβ‰‘πŸ™βˆ§πŸ˜ nrβ‰‘πŸ™βˆ§πŸ˜β‚‚ _) =
    ((πŸ™ ∧ p) Β· 𝟘 + πŸ™) ∧ 𝟘  β‰‘βŸ¨ cong ((_∧ _) βˆ˜β†’ (_+ _)) (Β·-zeroΚ³ (πŸ™ ∧ p)) ⟩
    πŸ™ ∧ 𝟘                  β‰‘βŸ¨βŸ©
    𝟘 ∧ πŸ™                  ∎
  lemma .𝟘 .𝟘 .𝟘 .𝟘 .πŸ™ (nrβ‰‘πŸ™βˆ§πŸ˜ nrβ‰‘πŸ™βˆ§πŸ˜β‚ƒ _) =
    ((𝟘 ∧ πŸ™) Β· πŸ™ + 𝟘) ∧ πŸ™  β‰‘βŸ¨ cong (_∧ _) (+-identityΚ³ (πŸ˜βˆ§πŸ™ Β· _)) ⟩
    (𝟘 ∧ πŸ™) Β· πŸ™ ∧ πŸ™        β‰‘βŸ¨ cong (_∧ _) (Β·-identityΚ³ πŸ˜βˆ§πŸ™) ⟩
    (𝟘 ∧ πŸ™) ∧ πŸ™            β‰‘βŸ¨ ∧-assoc 𝟘 πŸ™ _ ⟩
    𝟘 ∧ (πŸ™ ∧ πŸ™)            β‰‘βŸ¨βŸ©
    𝟘 ∧ πŸ™                  ∎
  lemma p 𝟘 .Ο‰ s n (nr≑ω nr≑ω₁ _) =
    ((πŸ™ ∧ p) Β· n + s) ∧ (n + Ο‰)  β‰‘βŸ¨ cong (((πŸ™ ∧ p) Β· _ + _) ∧_) (+-zeroΚ³ _) ⟩
    ((πŸ™ ∧ p) Β· n + s) ∧ Ο‰        β‰‘βŸ¨ ∧-zeroΚ³ ((πŸ™ ∧ p) Β· _ + _) ⟩
    Ο‰                            ∎
  lemma p πŸ™ .Ο‰ s n (nr≑ω nr≑ω₁ _) =
    (πŸ™ + p) Β· n + Ο‰ Β· s + Ο‰  β‰‘βŸ¨ cong ((πŸ™ + p) Β· _ +_) (+-zeroΚ³ _) ⟩
    (πŸ™ + p) Β· n + Ο‰          β‰‘βŸ¨ +-zeroΚ³ _ ⟩
    Ο‰                        ∎
  lemma p Ο‰ .Ο‰ s n (nr≑ω nr≑ω₁ _) =
    Ο‰ Β· (n + s + Ο‰)      β‰‘βŸ¨ Β·-distribΛ‘-+ _ n _ ⟩
    Ο‰ Β· n + Ο‰ Β· (s + Ο‰)  β‰‘βŸ¨ cong (Ο‰ Β· n +_) (Β·-distribΛ‘-+ _ s _) ⟩
    Ο‰ Β· n + Ο‰ Β· s + Ο‰    β‰‘βŸ¨ cong (Ο‰ Β· n +_) (+-zeroΚ³ _) ⟩
    Ο‰ Β· n + Ο‰            β‰‘βŸ¨ +-zeroΚ³ _ ⟩
    Ο‰                    ∎
  lemma p 𝟘 z .Ο‰ n (nr≑ω nr≑ω₂ ≑ω) =
    ((πŸ™ ∧ p) Β· n + Ο‰) ∧ (n + z)  β‰‘βŸ¨ cong (_∧ _) (+-zeroΚ³ ((πŸ™ ∧ p) Β· _)) ⟩
    Ο‰ ∧ (n + z)                  β‰‘βŸ¨βŸ©
    Ο‰                            β‰‘Λ˜βŸ¨ ≑ω ⟩
    nrβ€² p 𝟘 z Ο‰ n                ∎
  lemma p πŸ™ z .Ο‰ n (nr≑ω nr≑ω₂ ≑ω) =
    (πŸ™ + p) Β· n + Ο‰  β‰‘βŸ¨ +-zeroΚ³ _ ⟩
    Ο‰                β‰‘Λ˜βŸ¨ ≑ω ⟩
    nrβ€² p πŸ™ z Ο‰ n    ∎
  lemma p Ο‰ z .Ο‰ n (nr≑ω nr≑ω₂ ≑ω) =
    Ο‰ Β· (n + Ο‰)    β‰‘βŸ¨ Β·-distribΛ‘-+ _ n _ ⟩
    Ο‰ Β· n + Ο‰      β‰‘βŸ¨ +-zeroΚ³ _ ⟩
    Ο‰              β‰‘Λ˜βŸ¨ ≑ω ⟩
    nrβ€² p Ο‰ z Ο‰ n  ∎
  lemma p 𝟘 z s .Ο‰ (nr≑ω nr≑ω₃ ≑ω) =
    ((πŸ™ ∧ p) Β· Ο‰ + s) ∧ Ο‰  β‰‘βŸ¨ ∧-zeroΚ³ ((πŸ™ ∧ p) Β· _ + _) ⟩
    Ο‰                      β‰‘Λ˜βŸ¨ ≑ω ⟩
    nrβ€² p 𝟘 z s Ο‰          ∎
  lemma p πŸ™ z s .Ο‰ (nr≑ω nr≑ω₃ ≑ω) =
    (πŸ™ + p) Β· Ο‰ + Ο‰ Β· s + z  β‰‘βŸ¨ cong (_+ _) (Β·-distribΚ³-+ _ πŸ™ p) ⟩
    (Ο‰ + p Β· Ο‰) + Ο‰ Β· s + z  β‰‘βŸ¨βŸ©
    Ο‰                        β‰‘Λ˜βŸ¨ ≑ω ⟩
    nrβ€² p πŸ™ z s Ο‰            ∎
  lemma p Ο‰ z s .Ο‰ (nr≑ω nr≑ω₃ ≑ω) =
    Ο‰              β‰‘Λ˜βŸ¨ ≑ω ⟩
    nrβ€² p Ο‰ z s Ο‰  ∎
  lemma p .Ο‰ .πŸ™ s n (nr≑ω nr≑ω₄ _) =
    Ο‰ Β· (n + s + πŸ™)    β‰‘Λ˜βŸ¨ cong (Ο‰ Β·_) (+-assoc n _ _) ⟩
    Ο‰ Β· ((n + s) + πŸ™)  β‰‘βŸ¨ Β·-distribΛ‘-+ _ (n + _) _ ⟩
    Ο‰ Β· (n + s) + Ο‰    β‰‘βŸ¨ +-zeroΚ³ _ ⟩
    Ο‰                  ∎
  lemma p .Ο‰ .𝟘 .πŸ™ n (nr≑ω nr≑ω₅ _) =
    Ο‰ Β· (n + πŸ™)  β‰‘βŸ¨ Β·-distribΛ‘-+ _ n _ ⟩
    Ο‰ Β· n + Ο‰    β‰‘βŸ¨ +-zeroΚ³ _ ⟩
    Ο‰            ∎
  lemma p .Ο‰ .𝟘 .𝟘 .πŸ™ (nr≑ω nr≑ω₆ ≑ω) =
    Ο‰              β‰‘Λ˜βŸ¨ ≑ω ⟩
    nrβ€² p Ο‰ 𝟘 𝟘 πŸ™  ∎
  lemma .Ο‰ 𝟘 .𝟘 .𝟘 .πŸ™ (nr≑ω nr≑ω₇ _) =
    Ο‰  ∎
  lemma .Ο‰ πŸ™ .𝟘 .𝟘 .πŸ™ (nr≑ω nrβ‰‘Ο‰β‚ˆ _) =
    Ο‰  ∎
  lemma .πŸ™ .πŸ™ .𝟘 .𝟘 .πŸ™ (nr≑ω nr≑ω₉ _) =
    Ο‰  ∎
  lemma p .𝟘 .𝟘 .πŸ™ .πŸ™ (nr≑ω nr≑ω₁₀ _) =
    ((πŸ™ ∧ p) Β· πŸ™ + πŸ™) ∧ πŸ™  β‰‘βŸ¨ cong ((_∧ _) βˆ˜β†’ (_+ _)) (Β·-distribΚ³-∧ _ πŸ™ p) ⟩
    ((πŸ™ ∧ p Β· πŸ™) + πŸ™) ∧ πŸ™  β‰‘βŸ¨ cong ((_∧ _) βˆ˜β†’ (_+ _) βˆ˜β†’ (πŸ™ ∧_)) (Β·-identityΚ³ p) ⟩
    ((πŸ™ ∧ p) + πŸ™) ∧ πŸ™      β‰‘βŸ¨ cong (_∧ _) (+-distribΚ³-∧ _ πŸ™ p) ⟩
    (Ο‰ ∧ (p + πŸ™)) ∧ πŸ™      β‰‘βŸ¨βŸ©
    Ο‰                      ∎
  lemma p .πŸ™ z .πŸ™ n (nr≑ω nr≑ω₁₁ ≑ω) =
    (πŸ™ + p) Β· n + Ο‰  β‰‘βŸ¨ +-zeroΚ³ _ ⟩
    Ο‰                β‰‘Λ˜βŸ¨ ≑ω ⟩
    nrβ€² p πŸ™ z πŸ™ n    ∎
  lemma p .𝟘 .πŸ™ s .πŸ™ (nr≑ω nr≑ω₁₂ ≑ω) =
    ((πŸ™ ∧ p) Β· πŸ™ + s) ∧ Ο‰  β‰‘βŸ¨ ∧-zeroΚ³ ((πŸ™ ∧ p) Β· _ + _) ⟩
    Ο‰                      β‰‘Λ˜βŸ¨ ≑ω ⟩
    nrβ€² p 𝟘 πŸ™ s πŸ™          ∎
  lemma p .πŸ™ .πŸ™ .𝟘 .πŸ™ (nr≑ω nr≑ω₁₃ _) =
    (πŸ™ + p) Β· πŸ™ + πŸ™  β‰‘βŸ¨ cong (_+ _) (Β·-distribΚ³-+ _ πŸ™ p) ⟩
    (πŸ™ + p Β· πŸ™) + πŸ™  β‰‘βŸ¨ cong (_+ _) (+-comm _ (p Β· _)) ⟩
    (p Β· πŸ™ + πŸ™) + πŸ™  β‰‘βŸ¨ +-assoc (p Β· _) _ _ ⟩
    p Β· πŸ™ + Ο‰        β‰‘βŸ¨ +-zeroΚ³ _ ⟩
    Ο‰                ∎

-- The view is correctly defined for nr.

nr-view : βˆ€ p r z s n β†’ Nr p r z s n (nr p r z s n)
nr-view p r z s n =             $⟨ nrβ€²-view _ _ _ _ _ ⟩
  Nr p r z s n (nrβ€² p r z s n)  β†’βŸ¨ subst (Nr _ _ _ _ _) (sym (nr≑nrβ€² p r)) ⟩
  Nr p r z s n (nr p r z s n)   β–‘

-- The value of nr p r z s n is 𝟘 iff z, s and n are all zero.

nr-𝟘 : βˆ€ p r β†’ nr p r z s n ≑ 𝟘 ⇔ (z ≑ 𝟘 Γ— s ≑ 𝟘 Γ— n ≑ 𝟘)
nr-𝟘 p r =
    lemma₁ (nr-view _ _ _ _ _)
  , Ξ» { (refl , refl , refl) β†’ lemmaβ‚‚ p r }
  where
  open Semiring-with-meet zero-one-many-semiring-with-meet
    hiding (𝟘; πŸ™; _+_; _Β·_; _∧_)
  open Tools.Reasoning.PropositionalEquality

  lemma₁ : Nr p r z s n result β†’ result ≑ 𝟘 β†’ z ≑ 𝟘 Γ— s ≑ 𝟘 Γ— n ≑ 𝟘
  lemma₁ (nrβ‰‘πŸ˜ _)         refl = refl , refl , refl
  lemma₁ (nrβ‰‘πŸ™βˆ§πŸ˜ _ πŸ˜β‰‘πŸ˜βˆ§πŸ™) refl = βŠ₯-elim (πŸ˜βˆ§πŸ™β‰’πŸ˜ (sym πŸ˜β‰‘πŸ˜βˆ§πŸ™))
  lemma₁ (nrβ‰‘πŸ™β‚ ())       refl
  lemma₁ (nrβ‰‘πŸ™β‚‚ ())       refl
  lemma₁ nrβ‰‘πŸ™β‚ƒ            ()
  lemma₁ nrβ‰‘πŸ™β‚„            ()
  lemma₁ (nr≑ω _ ())      refl

  lemmaβ‚‚ : βˆ€ p r β†’ nr p r 𝟘 𝟘 𝟘 ≑ 𝟘
  lemmaβ‚‚ = Ξ» where
    _ Ο‰ β†’ refl
    Ο‰ πŸ™ β†’ refl
    πŸ™ πŸ™ β†’ refl
    𝟘 πŸ™ β†’ refl
    Ο‰ 𝟘 β†’ refl
    πŸ™ 𝟘 β†’ refl
    𝟘 𝟘 β†’
      ((𝟘 ∧ πŸ™) Β· 𝟘 + 𝟘) ∧ 𝟘  β‰‘βŸ¨ cong (_∧ _) (+-identityΚ³ (πŸ˜βˆ§πŸ™ Β· _)) ⟩
      ((𝟘 ∧ πŸ™) Β· 𝟘) ∧ 𝟘      β‰‘βŸ¨ cong (_∧ _) (Β·-zeroΚ³ πŸ˜βˆ§πŸ™) ⟩
      𝟘 ∧ 𝟘                  β‰‘βŸ¨βŸ©
      𝟘                      ∎

-- An nr function can be defined for zero-one-many-semiring-with-meet.

zero-one-many-has-nr : Has-nr zero-one-many-semiring-with-meet
zero-one-many-has-nr = record
  { nr          = nr
  ; nr-monotone = Ξ» {p = p} {r = r} β†’ nr-monotone p r
  ; nr-Β·        = Ξ» {p = p} {r = r} β†’ nr-Β· p r
  ; nr-+        = Ξ» {p = p} {r = r} β†’ nr-+ p r
  ; nr-positive = Ξ» {p = p} {r = r} β†’ nr-𝟘 p r .proj₁
  ; nr-zero     = Ξ» {n = _} {p = p} {r = r} nβ‰€πŸ˜ β†’ nr-zero p r nβ‰€πŸ˜
  ; nr-suc      = Ξ» {p = p} {r = r} β†’ nr-suc p r
  }
  where
  open Semiring-with-meet zero-one-many-semiring-with-meet
    hiding (𝟘; πŸ™; Ο‰; _+_; _Β·_; _∧_; _≀_)
  open Addition zero-one-many-semiring-with-meet
  open Meet zero-one-many-semiring-with-meet
  open Multiplication zero-one-many-semiring-with-meet
  open PartialOrder zero-one-many-semiring-with-meet

  nr-monotone :
    βˆ€ p r β†’
    z₁ ≀ zβ‚‚ β†’ s₁ ≀ sβ‚‚ β†’ n₁ ≀ nβ‚‚ β†’
    nr p r z₁ s₁ n₁ ≀ nr p r zβ‚‚ sβ‚‚ nβ‚‚
  nr-monotone = Ξ» where
    p 𝟘 z₁≀zβ‚‚ s₁≀sβ‚‚ n₁≀nβ‚‚ β†’
      ∧-monotone (+-monotone (Β·-monotoneΚ³ {r = πŸ™ ∧ p} n₁≀nβ‚‚) s₁≀sβ‚‚)
        (+-monotone n₁≀nβ‚‚ z₁≀zβ‚‚)
    p πŸ™ z₁≀zβ‚‚ s₁≀sβ‚‚ n₁≀nβ‚‚ β†’
      +-monotone (Β·-monotoneΚ³ {r = πŸ™ + p} n₁≀nβ‚‚)
        (+-monotone (Β·-monotoneΚ³ s₁≀sβ‚‚) z₁≀zβ‚‚)
    _ Ο‰ z₁≀zβ‚‚ s₁≀sβ‚‚ n₁≀nβ‚‚ β†’
      Β·-monotoneΚ³ (+-monotone n₁≀nβ‚‚ (+-monotone s₁≀sβ‚‚ z₁≀zβ‚‚))

  nr-Β· : βˆ€ p r β†’ nr p r z s n Β· q ≀ nr p r (z Β· q) (s Β· q) (n Β· q)
  nr-Β· {z = z} {s = s} {n = n} {q = q} p = Ξ» where
      𝟘 β†’ begin
        (((πŸ™ ∧ p) Β· n + s) ∧ (n + z)) Β· q              β‰‘βŸ¨ Β·-distribΚ³-∧ _ ((πŸ™ ∧ p) Β· _ + _) _ ⟩
        ((πŸ™ ∧ p) Β· n + s) Β· q ∧ (n + z) Β· q            β‰‘βŸ¨ ∧-cong (Β·-distribΚ³-+ _ ((πŸ™ ∧ p) Β· _) _)
                                                            (·-distribʳ-+ _ n _) ⟩
        (((πŸ™ ∧ p) Β· n) Β· q + s Β· q) ∧ (n Β· q + z Β· q)  β‰‘βŸ¨ ∧-congΚ³ (+-congΚ³ (Β·-assoc (πŸ™ ∧ p) _ _)) ⟩
        ((πŸ™ ∧ p) Β· (n Β· q) + s Β· q) ∧ (n Β· q + z Β· q)  ∎
      πŸ™ β†’ begin
        ((πŸ™ + p) Β· n + Ο‰ Β· s + z) Β· q            β‰‘βŸ¨ Β·-distribΚ³-+ _ ((πŸ™ + p) Β· _) _ ⟩
        ((πŸ™ + p) Β· n) Β· q + (Ο‰ Β· s + z) Β· q      β‰‘βŸ¨ +-congΛ‘ (Β·-distribΚ³-+ _ (Ο‰ Β· s) _) ⟩
        ((πŸ™ + p) Β· n) Β· q + (Ο‰ Β· s) Β· q + z Β· q  β‰‘βŸ¨ +-cong (Β·-assoc (πŸ™ + p) _ _)
                                                      (+-congΚ³ (Β·-assoc Ο‰ s _)) ⟩
        (πŸ™ + p) Β· (n Β· q) + Ο‰ Β· (s Β· q) + z Β· q  ∎
      Ο‰ β†’ begin
        (Ο‰ Β· (n + s + z)) Β· q        β‰‘βŸ¨ Β·-assoc _ _ _ ⟩
        Ο‰ Β· ((n + s + z) Β· q)        β‰‘βŸ¨ Β·-congΛ‘ (Β·-distribΚ³-+ _ n _) ⟩
        Ο‰ Β· (n Β· q + (s + z) Β· q)    β‰‘βŸ¨ Β·-congΛ‘ (+-congΛ‘ (Β·-distribΚ³-+ _ s _)) ⟩
        Ο‰ Β· (n Β· q + s Β· q + z Β· q)  ∎
    where
    open Tools.Reasoning.PartialOrder ≀-poset

  nr-+ :
    βˆ€ p r β†’
    nr p r z₁ s₁ n₁ + nr p r zβ‚‚ sβ‚‚ nβ‚‚ ≀
    nr p r (z₁ + zβ‚‚) (s₁ + sβ‚‚) (n₁ + nβ‚‚)
  nr-+ {z₁ = z₁} {s₁ = s₁} {n₁ = n₁} {zβ‚‚ = zβ‚‚} {sβ‚‚ = sβ‚‚} {nβ‚‚ = nβ‚‚} p =
    Ξ» where
      𝟘 β†’ begin
        (((πŸ™ ∧ p) Β· n₁ + s₁) ∧ (n₁ + z₁)) +
        (((πŸ™ ∧ p) Β· nβ‚‚ + sβ‚‚) ∧ (nβ‚‚ + zβ‚‚))                            β‰€βŸ¨ +-sub-interchangeable-∧ ((πŸ™ ∧ p) Β· _ + _) _ _ _ ⟩

        (((πŸ™ ∧ p) Β· n₁ + s₁) + ((πŸ™ ∧ p) Β· nβ‚‚ + sβ‚‚)) ∧
        ((n₁ + z₁) + (nβ‚‚ + zβ‚‚))                                      β‰‘βŸ¨ ∧-cong (+-sub-interchangeable-+ ((πŸ™ ∧ p) Β· _) _ _ _)
                                                                          (+-sub-interchangeable-+ n₁ _ _ _) ⟩
        (((πŸ™ ∧ p) Β· n₁ + (πŸ™ ∧ p) Β· nβ‚‚) + (s₁ + sβ‚‚)) ∧
        ((n₁ + nβ‚‚) + (z₁ + zβ‚‚))                                      β‰‘Λ˜βŸ¨ ∧-congΚ³ (+-congΚ³ (Β·-distribΛ‘-+ (πŸ™ ∧ p) _ _)) ⟩

        ((πŸ™ ∧ p) Β· (n₁ + nβ‚‚) + (s₁ + sβ‚‚)) ∧ ((n₁ + nβ‚‚) + (z₁ + zβ‚‚))  ∎
      πŸ™ β†’ begin
        ((πŸ™ + p) Β· n₁ + Ο‰ Β· s₁ + z₁) + ((πŸ™ + p) Β· nβ‚‚ + Ο‰ Β· sβ‚‚ + zβ‚‚)    β‰‘βŸ¨ +-sub-interchangeable-+ ((πŸ™ + p) Β· _) _ _ _ ⟩
        ((πŸ™ + p) Β· n₁ + (πŸ™ + p) Β· nβ‚‚) + (Ο‰ Β· s₁ + z₁) + (Ο‰ Β· sβ‚‚ + zβ‚‚)  β‰‘βŸ¨ +-cong (sym (Β·-distribΛ‘-+ (πŸ™ + p) _ _))
                                                                            (+-sub-interchangeable-+ (Ο‰ Β· s₁) _ _ _) ⟩
        (πŸ™ + p) Β· (n₁ + nβ‚‚) + (Ο‰ Β· s₁ + Ο‰ Β· sβ‚‚) + (z₁ + zβ‚‚)            β‰‘Λ˜βŸ¨ +-congΛ‘ {x = (πŸ™ + p) Β· _}
                                                                             (+-congΚ³ (Β·-distribΛ‘-+ Ο‰ s₁ _)) ⟩
        (πŸ™ + p) Β· (n₁ + nβ‚‚) + Ο‰ Β· (s₁ + sβ‚‚) + (z₁ + zβ‚‚)                ∎
      Ο‰ β†’ begin
        Ο‰ Β· (n₁ + s₁ + z₁) + Ο‰ Β· (nβ‚‚ + sβ‚‚ + zβ‚‚)  β‰‘Λ˜βŸ¨ Β·-distribΛ‘-+ _ (n₁ + _) _ ⟩
        Ο‰ Β· ((n₁ + s₁ + z₁) + (nβ‚‚ + sβ‚‚ + zβ‚‚))    β‰‘βŸ¨ Β·-congΛ‘ lemma ⟩
        Ο‰ Β· ((n₁ + nβ‚‚) + (s₁ + sβ‚‚) + (z₁ + zβ‚‚))  ∎
    where
    lemma =
      (n₁ + s₁ + z₁) + (nβ‚‚ + sβ‚‚ + zβ‚‚)    β‰‘βŸ¨ +-sub-interchangeable-+ n₁ _ _ _ ⟩
      (n₁ + nβ‚‚) + (s₁ + z₁) + (sβ‚‚ + zβ‚‚)  β‰‘βŸ¨ +-congΛ‘ {x = n₁ + _}
                                              (+-sub-interchangeable-+ s₁ _ _ _) ⟩
      (n₁ + nβ‚‚) + (s₁ + sβ‚‚) + (z₁ + zβ‚‚)  ∎
      where
      open Tools.Reasoning.PropositionalEquality

    open Tools.Reasoning.PartialOrder ≀-poset

  nr-zero : βˆ€ p r β†’ n ≀ 𝟘 β†’ nr p r z s n ≀ z
  nr-zero {n = n} {z = z} {s = s} p r nβ‰€πŸ˜ =
    case nr-view p r z s n of Ξ» where
      (nrβ‰‘πŸ˜ β‰‘πŸ˜) β†’ begin
        nr p r 𝟘 𝟘 𝟘  β‰‘βŸ¨ β‰‘πŸ˜ ⟩
        𝟘             ∎
      (nrβ‰‘πŸ™β‚ β‰‘πŸ™) β†’ begin
        nr p 𝟘 πŸ™ πŸ™ 𝟘  β‰‘βŸ¨ β‰‘πŸ™ ⟩
        πŸ™             ∎
      (nrβ‰‘πŸ™β‚‚ β‰‘πŸ™) β†’ begin
        nr p πŸ™ πŸ™ 𝟘 𝟘  β‰‘βŸ¨ β‰‘πŸ™ ⟩
        πŸ™             ∎
      nrβ‰‘πŸ™β‚ƒ β†’ begin
        πŸ™  β‰€βŸ¨ nβ‰€πŸ˜ ⟩
        𝟘  ∎
      nrβ‰‘πŸ™β‚„ β†’ begin
        πŸ™  β‰€βŸ¨ nβ‰€πŸ˜ ⟩
        𝟘  ∎
      (nrβ‰‘πŸ™βˆ§πŸ˜ nrβ‰‘πŸ™βˆ§πŸ˜β‚ β‰‘πŸ˜βˆ§πŸ™) β†’ begin
        ((πŸ™ ∧ p) Β· 𝟘 + 𝟘) ∧ πŸ™  β‰‘βŸ¨ β‰‘πŸ˜βˆ§πŸ™ ⟩
        𝟘 ∧ πŸ™                  β‰€βŸ¨ ∧-decreasingΚ³ 𝟘 πŸ™ ⟩
        πŸ™                      ∎
      (nrβ‰‘πŸ™βˆ§πŸ˜ nrβ‰‘πŸ™βˆ§πŸ˜β‚‚ β‰‘πŸ˜βˆ§πŸ™) β†’ begin
        ((πŸ™ ∧ p) Β· 𝟘 + πŸ™) ∧ 𝟘  β‰‘βŸ¨ β‰‘πŸ˜βˆ§πŸ™ ⟩
        𝟘 ∧ πŸ™                  β‰€βŸ¨ ∧-decreasingΛ‘ 𝟘 πŸ™ ⟩
        𝟘                      ∎
      (nrβ‰‘πŸ™βˆ§πŸ˜ nrβ‰‘πŸ™βˆ§πŸ˜β‚ƒ β‰‘πŸ˜βˆ§πŸ™) β†’ begin
        ((𝟘 ∧ πŸ™) Β· πŸ™ + 𝟘) ∧ πŸ™  β‰‘βŸ¨ β‰‘πŸ˜βˆ§πŸ™ ⟩
        𝟘 ∧ πŸ™                  β‰€βŸ¨ ∧-decreasingΛ‘ 𝟘 πŸ™ ⟩
        𝟘                      ∎
      (nr≑ω _ ≑ω) β†’ begin
        nr p r z s n  β‰‘βŸ¨ ≑ω ⟩
        Ο‰             β‰€βŸ¨ refl ⟩
        z             ∎
    where
    open Tools.Reasoning.PartialOrder ≀-poset

  nr-suc : βˆ€ p r β†’ nr p r z s n ≀ s + p Β· n + r Β· nr p r z s n
  nr-suc {z = z} {s = s} {n = n} p r =
    case nr-view p r z s n of Ξ» where
      (nrβ‰‘πŸ˜ β‰‘πŸ˜) β†’ begin
        nr p r 𝟘 𝟘 𝟘                  β‰‘βŸ¨ β‰‘πŸ˜ ⟩
        𝟘                             β‰‘Λ˜βŸ¨ Β·-zeroΚ³ _ ⟩
        r Β· 𝟘                         β‰‘Λ˜βŸ¨ +-identityΛ‘ _ ⟩
        𝟘 + r Β· 𝟘                     β‰‘Λ˜βŸ¨ +-cong (Β·-zeroΚ³ p) (Β·-congΛ‘ β‰‘πŸ˜) ⟩
        p Β· 𝟘 + r Β· nr p r 𝟘 𝟘 𝟘      β‰‘βŸ¨βŸ©
        𝟘 + p · 𝟘 + r · nr p r 𝟘 𝟘 𝟘  ∎
      (nrβ‰‘πŸ™β‚ β‰‘πŸ™) β†’ begin
        nr p 𝟘 πŸ™ πŸ™ 𝟘                  β‰‘βŸ¨ β‰‘πŸ™ ⟩
        πŸ™                             β‰‘βŸ¨βŸ©
        πŸ™ + 𝟘 + 𝟘                     β‰‘Λ˜βŸ¨ +-congΛ‘ (+-congΚ³ {x = 𝟘} (Β·-zeroΚ³ p)) ⟩
        πŸ™ + p Β· 𝟘 + 𝟘                 β‰‘βŸ¨βŸ©
        πŸ™ + p Β· 𝟘 + 𝟘 Β· nr p 𝟘 πŸ™ πŸ™ 𝟘  ∎
      (nrβ‰‘πŸ™β‚‚ _) β†’ begin
        nr p πŸ™ πŸ™ 𝟘 𝟘                  β‰‘βŸ¨βŸ©
        𝟘 + nr p πŸ™ πŸ™ 𝟘 𝟘              β‰‘Λ˜βŸ¨ +-cong (Β·-zeroΚ³ p) (Β·-identityΛ‘ _) ⟩
        p Β· 𝟘 + πŸ™ Β· nr p πŸ™ πŸ™ 𝟘 𝟘      β‰‘Λ˜βŸ¨ +-identityΛ‘ _ ⟩
        𝟘 + p Β· 𝟘 + πŸ™ Β· nr p πŸ™ πŸ™ 𝟘 𝟘  ∎
      nrβ‰‘πŸ™β‚ƒ β†’ begin
        nr πŸ™ 𝟘 𝟘 𝟘 πŸ™                  β‰‘βŸ¨βŸ©
        πŸ™                             β‰‘βŸ¨βŸ©
        𝟘 + πŸ™ Β· πŸ™ + 𝟘 Β· nr πŸ™ 𝟘 𝟘 𝟘 πŸ™  ∎
      nrβ‰‘πŸ™β‚„ β†’ begin
        nr 𝟘 πŸ™ 𝟘 𝟘 πŸ™                  β‰‘βŸ¨βŸ©
        πŸ™                             β‰‘βŸ¨βŸ©
        𝟘 + 𝟘 Β· πŸ™ + πŸ™ Β· nr πŸ™ 𝟘 𝟘 𝟘 πŸ™  ∎
      (nrβ‰‘πŸ™βˆ§πŸ˜ nrβ‰‘πŸ™βˆ§πŸ˜β‚ β‰‘πŸ˜βˆ§πŸ™) β†’ begin
        ((πŸ™ ∧ p) Β· 𝟘 + 𝟘) ∧ πŸ™  β‰‘βŸ¨ β‰‘πŸ˜βˆ§πŸ™ ⟩
        𝟘 ∧ πŸ™                  β‰€βŸ¨ ∧-decreasingΛ‘ 𝟘 πŸ™ ⟩
        𝟘                      β‰‘Λ˜βŸ¨ Β·-zeroΚ³ _ ⟩
        p Β· 𝟘                  β‰‘Λ˜βŸ¨ +-identityΚ³ _ ⟩
        p · 𝟘 + 𝟘              ∎
      (nrβ‰‘πŸ™βˆ§πŸ˜ nrβ‰‘πŸ™βˆ§πŸ˜β‚‚ β‰‘πŸ˜βˆ§πŸ™) β†’ begin
        ((πŸ™ ∧ p) Β· 𝟘 + πŸ™) ∧ 𝟘  β‰‘βŸ¨ β‰‘πŸ˜βˆ§πŸ™ ⟩
        𝟘 ∧ πŸ™                  β‰€βŸ¨ ∧-decreasingΚ³ 𝟘 πŸ™ ⟩
        πŸ™                      β‰‘Λ˜βŸ¨ +-identityΚ³ _ ⟩
        πŸ™ + 𝟘                  β‰‘Λ˜βŸ¨ cong (_ +_) (Β·-zeroΚ³ p) ⟩
        πŸ™ + p Β· 𝟘              β‰‘Λ˜βŸ¨ cong (_ +_) (+-identityΚ³ (p Β· _)) ⟩
        πŸ™ + p Β· 𝟘 + 𝟘          ∎
      (nrβ‰‘πŸ™βˆ§πŸ˜ nrβ‰‘πŸ™βˆ§πŸ˜β‚ƒ β‰‘πŸ˜βˆ§πŸ™) β†’ begin
        ((𝟘 ∧ πŸ™) Β· πŸ™ + 𝟘) ∧ πŸ™  β‰‘βŸ¨ β‰‘πŸ˜βˆ§πŸ™ ⟩
        𝟘 ∧ πŸ™                  β‰€βŸ¨ ∧-decreasingΛ‘ 𝟘 πŸ™ ⟩
        𝟘                      ∎
      (nr≑ω _ ≑ω) β†’ begin
        nr p r z s n                  β‰‘βŸ¨ ≑ω ⟩
        Ο‰                             β‰€βŸ¨ refl ⟩
        s + p · n + r · nr p r z s n  ∎
    where
    open Tools.Reasoning.PartialOrder ≀-poset

opaque

  -- The nr function defined above is factoring.

  zero-one-many-has-factoring-nr :
    Is-factoring-nr zero-one-many-has-nr
  zero-one-many-has-factoring-nr = record
    { nrβ‚‚ = nrβ‚‚
    ; nrβ‚‚β‰’πŸ˜ = Ξ» {p} {r} β†’ πŸ™βˆ§pβ‰’πŸ˜ (r + p)
    ; nr-factoring = Ξ» {p} {r} {z} {s} {n} β†’ nr-factoring p r z s n
    }
    where
    open Tools.Reasoning.PropositionalEquality
    open Semiring-with-meet zero-one-many-semiring-with-meet
           hiding (𝟘; πŸ™; Ο‰; _+_; _Β·_; _∧_)
    nrβ‚‚ : Opβ‚‚ Zero-one-many
    nrβ‚‚ p r = πŸ™ ∧ (r + p)
    πŸ™+pβ‰‘πŸ™βˆ§πŸ™+p : βˆ€ p β†’ πŸ™ + p ≑ πŸ™ ∧ (πŸ™ + p)
    πŸ™+pβ‰‘πŸ™βˆ§πŸ™+p 𝟘 = refl
    πŸ™+pβ‰‘πŸ™βˆ§πŸ™+p πŸ™ = refl
    πŸ™+pβ‰‘πŸ™βˆ§πŸ™+p Ο‰ = refl
    lemma : βˆ€ p q r β†’ p β‰’ 𝟘 β†’ (p + q) ∧ (πŸ™ + r) ≑ p + q ∧ r
    lemma 𝟘 q r pβ‰’πŸ˜ = βŠ₯-elim (pβ‰’πŸ˜ refl)
    lemma πŸ™ q r pβ‰’πŸ˜ = sym (+-distribΛ‘-∧ πŸ™ q r)
    lemma Ο‰ q r pβ‰’πŸ˜ = refl
    nr-factoring : (p r z s n : Zero-one-many) β†’ nr p r z s n ≑ nrβ‚‚ p r Β· n + nr p r z s 𝟘
    nr-factoring p 𝟘 z s 𝟘
      rewrite Β·-zeroΚ³ (πŸ™ ∧ p) = refl
    nr-factoring p 𝟘 z s πŸ™
      rewrite Β·-zeroΚ³ (πŸ™ ∧ p) rewrite Β·-identityΚ³ (πŸ™ ∧ p) = lemma (πŸ™ ∧ p) s z (πŸ™βˆ§pβ‰’πŸ˜ p)
    nr-factoring p 𝟘 z s Ο‰
      rewrite Β·-distribΚ³-∧ Ο‰ πŸ™ p = refl
    nr-factoring p πŸ™ z s n rewrite Β·-zeroΚ³ (πŸ™ + p) =
      +-congΚ³ (Β·-congΚ³ (πŸ™+pβ‰‘πŸ™βˆ§πŸ™+p p))
    nr-factoring p Ο‰ z s n = Β·-distribΛ‘-+ Ο‰ n (s + z)

opaque

  -- The nr function returns results that are at least as large as those
  -- of any other factoring nr function for zero-one-many-semiring-with-meet.

  nr-greatest-factoring :
    (has-nr : Has-nr zero-one-many-semiring-with-meet)
    (is-factoring-nr : Is-factoring-nr has-nr) β†’
    βˆ€ p r z s n β†’ Has-nr.nr has-nr p r z s n ≀ nr p r z s n
  nr-greatest-factoring has-nr is-factoring-nr = Ξ» where
      p r Ο‰ s n β†’ lemma $ begin
        nrβ€³ p r Ο‰ s n                β‰‘βŸ¨ nr-factoring ⟩
        nrβ‚‚β€³ p r Β· n + nrβ€³ p r Ο‰ s 𝟘 β‰€βŸ¨ +-monotoneΚ³ (nr-zero refl) ⟩
        nrβ‚‚β€³ p r Β· n + Ο‰             β‰‘βŸ¨ +-zeroΚ³ _ ⟩
        Ο‰                            ∎
      p r z Ο‰ n β†’ lemma $ begin
        nrβ€³ p r z Ο‰ n                 β‰€βŸ¨ nr-suc ⟩
        Ο‰ + p Β· n + r Β· nrβ€³ p r z Ο‰ n β‰‘βŸ¨βŸ©
        Ο‰                             ∎
      p r z s Ο‰ β†’ lemma $ begin
        nrβ€³ p r z s Ο‰                β‰‘βŸ¨ nr-factoring ⟩
        nrβ‚‚β€³ p r Β· Ο‰ + nrβ€³ p r z s 𝟘 β‰‘βŸ¨ +-congΚ³ (β‰’πŸ˜Β·Ο‰ nrβ‚‚β‰’πŸ˜) ⟩
        Ο‰                            ∎
      p r 𝟘 𝟘 𝟘 β†’ begin
        nrβ€³ p r 𝟘 𝟘 𝟘 β‰‘βŸ¨ nrβ€³-𝟘 ⦃ has-nr ⦄ ⟩
        𝟘             β‰‘Λ˜βŸ¨ nr-𝟘 p r .projβ‚‚ (refl , refl , refl)  ⟩
        nr p r 𝟘 𝟘 𝟘  ∎
      Ο‰ r z s πŸ™ β†’ lemma $ begin
        nrβ€³ Ο‰ r z s πŸ™             β‰€βŸ¨ nr-suc ⟩
        s + Ο‰ + r Β· nrβ€³ Ο‰ r z s πŸ™ β‰‘βŸ¨βŸ©
        s + Ο‰                     β‰‘βŸ¨ +-zeroΚ³ s ⟩
        Ο‰                         ∎
      πŸ™ r z πŸ™ πŸ™ β†’ lemma $ begin
        nrβ€³ πŸ™ r z πŸ™ πŸ™              β‰€βŸ¨ nr-suc ⟩
        πŸ™ + πŸ™ + r Β· nrβ€³ πŸ™ r z πŸ™ πŸ™ β‰‘Λ˜βŸ¨ +-assoc πŸ™ πŸ™ (r Β· nrβ€³ πŸ™ r z πŸ™ πŸ™) ⟩
        Ο‰ + r Β· nrβ€³ πŸ™ r z πŸ™ πŸ™      β‰‘βŸ¨βŸ©
        Ο‰                           ∎
      p r 𝟘 πŸ™ πŸ™ β†’ nrβ€³przsπŸ™β‰€ Ξ» ()
      p r πŸ™ s πŸ™ β†’ nrβ€³przsπŸ™β‰€ Ξ» ()
      p Ο‰ πŸ™ 𝟘 𝟘 β†’ nrβ€³pω≀ Ξ» ()
      p Ο‰ z πŸ™ 𝟘 β†’ nrβ€³pω≀ Ξ» ()
      p Ο‰ z s πŸ™ β†’ nrβ€³pω≀ Ξ» ()
      πŸ™ πŸ™ z s πŸ™ β†’ lemma $ begin
        nrβ€³ πŸ™ πŸ™ z s πŸ™              β‰€βŸ¨ nr-suc ⟩
        s + πŸ™ + πŸ™ Β· nrβ€³ πŸ™ πŸ™ z s πŸ™ β‰‘βŸ¨ +-congΛ‘ {s} (+-congΛ‘ {πŸ™} (Β·-identityΛ‘ (nrβ€³ πŸ™ πŸ™ z s πŸ™))) ⟩
        s + πŸ™ + nrβ€³ πŸ™ πŸ™ z s πŸ™     β‰‘βŸ¨ +-congΛ‘ {s} (β‰’πŸ˜+β‰’πŸ˜ {πŸ™} {nrβ€³ πŸ™ πŸ™ z s πŸ™} (Ξ» ())
                                        Ξ» nrβ€³β‰‘πŸ˜ β†’ case nrβ€³-positive nrβ€³β‰‘πŸ˜ of Ξ» ()) ⟩
        s + Ο‰                      β‰‘βŸ¨ +-zeroΚ³ s ⟩
        Ο‰                          ∎
      p πŸ™ z πŸ™ n β†’ lemma $ begin
        nrβ€³ p πŸ™ z πŸ™ n                  β‰€βŸ¨ nr-suc ⟩
        πŸ™ + p Β· n + πŸ™ Β· nrβ€³ p πŸ™ z πŸ™ n β‰‘βŸ¨ +-congΛ‘ {πŸ™} (+-congΛ‘ {p Β· n} (Β·-identityΛ‘ _)) ⟩
        πŸ™ + p Β· n + nrβ€³ p πŸ™ z πŸ™ n     β‰‘βŸ¨ +-congΛ‘ {πŸ™} (+-comm (p Β· n) (nrβ€³ p πŸ™ z πŸ™ n)) ⟩
        πŸ™ + nrβ€³ p πŸ™ z πŸ™ n + p Β· n     β‰‘Λ˜βŸ¨ +-assoc πŸ™ (nrβ€³ p πŸ™ z πŸ™ n) (p Β· n) ⟩
        (πŸ™ + nrβ€³ p πŸ™ z πŸ™ n) + p Β· n   β‰‘βŸ¨ +-congΚ³ {p Β· n} (β‰’πŸ˜+β‰’πŸ˜ {πŸ™} {nrβ€³ p πŸ™ z πŸ™ n} (Ξ» ())
                                            Ξ» nrβ€³β‰‘πŸ˜ β†’ case nrβ€³-positive nrβ€³β‰‘πŸ˜ of Ξ» ()) ⟩
        Ο‰ + p Β· n                      β‰‘βŸ¨βŸ©
        Ο‰                              ∎
      𝟘 𝟘 𝟘 𝟘 πŸ™ β†’ begin
        nrβ€³ 𝟘 𝟘 𝟘 𝟘 πŸ™ β‰€βŸ¨ ∧-greatest-lower-bound {q = 𝟘} {πŸ™} nr-suc
                            (β‰’πŸ˜β†’β‰€πŸ™ (nrβ€³ 𝟘 𝟘 𝟘 𝟘 πŸ™) (Ξ» nrβ€³β‰‘πŸ˜ β†’ case nrβ€³-positive nrβ€³β‰‘πŸ˜ of Ξ» ())) ⟩
        πŸ˜βˆ§πŸ™           β‰‘βŸ¨βŸ©
        nrβ€² 𝟘 𝟘 𝟘 𝟘 πŸ™ β‰‘Λ˜βŸ¨ nr≑nrβ€² {𝟘} {𝟘} {πŸ™} 𝟘 𝟘 ⟩
        nr  𝟘 𝟘 𝟘 𝟘 πŸ™ ∎
      πŸ™ 𝟘 𝟘 𝟘 πŸ™ β†’ begin
        nrβ€³ πŸ™ 𝟘 𝟘 𝟘 πŸ™ β‰€βŸ¨ nr-suc ⟩
        πŸ™              β‰‘βŸ¨βŸ©
        nr  πŸ™ 𝟘 𝟘 𝟘 πŸ™ ∎
      𝟘 πŸ™ 𝟘 𝟘 πŸ™ β†’ begin
        nrβ€³ 𝟘 πŸ™ 𝟘 𝟘 πŸ™ β‰€βŸ¨ β‰’πŸ˜β†’β‰€πŸ™ (nrβ€³ 𝟘 πŸ™ 𝟘 𝟘 πŸ™) (Ξ» nrβ€³β‰‘πŸ˜ β†’ case nrβ€³-positive nrβ€³β‰‘πŸ˜ of Ξ» ()) ⟩
        πŸ™              β‰‘βŸ¨βŸ©
        nr  𝟘 πŸ™ 𝟘 𝟘 πŸ™ ∎
      p 𝟘 𝟘 πŸ™ 𝟘 β†’ begin
        nrβ€³ p 𝟘 𝟘 πŸ™ 𝟘 β‰€βŸ¨ ∧-greatest-lower-bound {q = 𝟘} {πŸ™} (nr-zero refl) nr-sucβ€² ⟩
        πŸ˜βˆ§πŸ™           β‰‘βŸ¨βŸ©
        nrβ€² p 𝟘 𝟘 πŸ™ 𝟘 β‰‘Λ˜βŸ¨ nr≑nrβ€² {𝟘} {πŸ™} {𝟘} p 𝟘 ⟩
        nr  p 𝟘 𝟘 πŸ™ 𝟘 ∎
      p 𝟘 πŸ™ 𝟘 𝟘 β†’ begin
        nrβ€³ p 𝟘 πŸ™ 𝟘 𝟘 β‰€βŸ¨ ∧-greatest-lower-bound {q = 𝟘} {πŸ™} nr-sucβ€² (nr-zero refl) ⟩
        πŸ˜βˆ§πŸ™           β‰‘βŸ¨βŸ©
        nrβ€² p 𝟘 πŸ™ 𝟘 𝟘 β‰‘Λ˜βŸ¨ nr≑nrβ€² {πŸ™} {𝟘} {𝟘} p 𝟘  ⟩
        nr  p 𝟘 πŸ™ 𝟘 𝟘 ∎
      p 𝟘 πŸ™ πŸ™ 𝟘 β†’ begin
        nrβ€³ p 𝟘 πŸ™ πŸ™ 𝟘 β‰€βŸ¨ nr-sucβ€² ⟩
        πŸ™              β‰‘βŸ¨βŸ©
        nrβ€² p 𝟘 πŸ™ πŸ™ 𝟘 β‰‘Λ˜βŸ¨ nr≑nrβ€² {πŸ™} {πŸ™} {𝟘} p 𝟘 ⟩
        nr  p 𝟘 πŸ™ πŸ™ 𝟘 ∎
      p πŸ™ πŸ™ 𝟘 𝟘 β†’ begin
        nrβ€³ p πŸ™ πŸ™ 𝟘 𝟘 β‰€βŸ¨ nr-zero refl ⟩
        πŸ™              β‰‘βŸ¨βŸ©
        nrβ€² p πŸ™ πŸ™ 𝟘 𝟘 β‰‘Λ˜βŸ¨ nr≑nrβ€² {πŸ™} {𝟘} {𝟘} p πŸ™ ⟩
        nr  p πŸ™ πŸ™ 𝟘 𝟘 ∎
    where
    open Is-factoring-nr is-factoring-nr renaming (nrβ‚‚ to nrβ‚‚β€³)
    open Has-nr has-nr renaming (nr to nrβ€³; nr-positive to nrβ€³-positive)
    open Addition zero-one-many-semiring-with-meet
    open Meet zero-one-many-semiring-with-meet
    open Natrec zero-one-many-semiring-with-meet renaming (nr-𝟘 to nrβ€³-𝟘)
    open PartialOrder zero-one-many-semiring-with-meet
    open Semiring-with-meet zero-one-many-semiring-with-meet
      hiding (𝟘; πŸ™; Ο‰; _+_; _Β·_; _∧_; _≀_)
    open Tools.Reasoning.PartialOrder ≀-poset
    lemma : nrβ€³ p r z s n ≀ Ο‰ β†’ nrβ€³ p r z s n ≀ nr p r z s n
    lemma {p} {r} {z} {s} {n} nr″≀ω =
      ≀-trans nr″≀ω (ω≀ (nr p r z s n))
    nr-sucβ€² : nrβ€³ p r z s 𝟘 ≀ s + r Β· nrβ€³ p r z s 𝟘
    nr-sucβ€² {p} {r} {z} {s} = begin
      nrβ€³ p r z s 𝟘 β‰€βŸ¨ nr-suc ⟩
      s + p Β· 𝟘 + r Β· nrβ€³ p r z s 𝟘 β‰‘βŸ¨ +-congΛ‘ {s} (+-congΚ³ (Β·-zeroΚ³ p)) ⟩
      s + 𝟘 + r Β· nrβ€³ p r z s 𝟘     β‰‘βŸ¨βŸ©
      s + r Β· nrβ€³ p r z s 𝟘         ∎
    nrβ€³pω≀ : Β¬ (z ≑ 𝟘 Γ— s ≑ 𝟘 Γ— n ≑ 𝟘) β†’ nrβ€³ p Ο‰ z s n ≀ nr p Ο‰ z s n
    nrβ€³pω≀ {z} {s} {n} {p} β‰’πŸ˜ = lemma $ begin
      nrβ€³ p Ο‰ z s n                 β‰€βŸ¨ nr-suc ⟩
      s + p Β· n + Ο‰ Β· nrβ€³ p Ο‰ z s n β‰‘βŸ¨ +-congΛ‘ {s} (+-congΛ‘ (Ο‰Β·β‰’πŸ˜ (β‰’πŸ˜ βˆ˜β†’ nrβ€³-positive))) ⟩
      s + p Β· n + Ο‰                 β‰‘βŸ¨ +-congΛ‘ (+-zeroΚ³ _) ⟩
      s + Ο‰                         β‰‘βŸ¨ +-zeroΚ³ _ ⟩
      Ο‰                             ∎
    nrβ€³przsπŸ™β‰€ : Β¬ (z ≑ 𝟘 Γ— s ≑ 𝟘) β†’ nrβ€³ p r z s πŸ™ ≀ nr p r z s πŸ™
    nrβ€³przsπŸ™β‰€ {z} {s} {p} {r} β‰’πŸ˜ = lemma $ begin
        nrβ€³ p r z s πŸ™                β‰‘βŸ¨ nr-factoring ⟩
        nrβ‚‚β€³ p r Β· πŸ™ + nrβ€³ p r z s 𝟘 β‰‘βŸ¨ +-congΚ³ {nrβ€³ p r z s 𝟘} (Β·-identityΚ³ _) ⟩
        nrβ‚‚β€³ p r + nrβ€³ p r z s 𝟘     β‰‘βŸ¨ β‰’πŸ˜+β‰’πŸ˜ nrβ‚‚β‰’πŸ˜ (Ξ» nrβ€³β‰‘πŸ˜ β†’
                                         let zβ‰‘πŸ˜ , sβ‰‘πŸ˜ , _ = nrβ€³-positive nrβ€³β‰‘πŸ˜
                                         in  β‰’πŸ˜ (zβ‰‘πŸ˜ , sβ‰‘πŸ˜)) ⟩
        Ο‰                            ∎

opaque

  -- The nr function satisfies Linearity-like-nr-for-𝟘.

  nr-linearity-like-for-𝟘 :
    Has-nr.Linearity-like-nr-for-𝟘 zero-one-many-has-nr
  nr-linearity-like-for-𝟘 = refl

opaque

  -- The nr function satisfies Linearity-like-nr-for-πŸ™.

  nr-linearity-like-for-πŸ™ :
    Has-nr.Linearity-like-nr-for-πŸ™ zero-one-many-has-nr
  nr-linearity-like-for-πŸ™ = refl

-- A modality defined using zero-one-many-has-nr.

zero-one-many-modality : Modality-variant β†’ Modality
zero-one-many-modality variant = record
  { variant            = variant
  ; semiring-with-meet = zero-one-many-semiring-with-meet
  ; 𝟘-well-behaved     = Ξ» _ β†’ zero-one-many-has-well-behaved-zero
  }

------------------------------------------------------------------------
-- Subtraction

open Subtraction zero-one-many-semiring-with-meet

opaque

  -- Subtraction of Ο‰ by anything is Ο‰

  Ο‰-p≑ω : βˆ€ p β†’ Ο‰ - p ≑ Ο‰
  Ο‰-p≑ω p = ∞-pβ‰‘βˆž PE.refl p

opaque

  -- Subtraction of πŸ™ by πŸ™ is 𝟘

  πŸ™-πŸ™β‰‘πŸ˜ : πŸ™ - πŸ™ ≑ 𝟘
  πŸ™-πŸ™β‰‘πŸ˜ =
    p-pβ‰€πŸ˜ ,
    Ξ» where
      𝟘 _  β†’ refl
      πŸ™ ()
      Ο‰ ()

opaque

  -- Subtraction of p by Ο‰ is not possible unless p ≑ ω

  p-Ο‰β‰° : p - Ο‰ ≀ q β†’ p ≑ Ο‰
  p-Ο‰β‰° {(𝟘)} {(𝟘)} ()
  p-Ο‰β‰° {(𝟘)} {(πŸ™)} ()
  p-Ο‰β‰° {(𝟘)} {(Ο‰)} ()
  p-Ο‰β‰° {(πŸ™)} {(𝟘)} ()
  p-Ο‰β‰° {(πŸ™)} {(πŸ™)} ()
  p-Ο‰β‰° {(πŸ™)} {(Ο‰)} ()
  p-Ο‰β‰° {(Ο‰)} _ = refl

opaque

  -- Subtraction of p by Ο‰ is not possible unless p ≑ ω

  p-Ο‰β‰’ : p - Ο‰ ≑ q β†’ p ≑ Ο‰
  p-Ο‰β‰’ {q} = p-Ο‰β‰° {q = q} βˆ˜β†’ proj₁

opaque

  -- The semiring supports subtraction with
  --   Ο‰ - p ≑ Ο‰ for all p
  --   p - 𝟘 ≑ p for all p
  --   πŸ™ - πŸ™ ≑ 𝟘
  -- and not defined otherwise

  supports-subtraction : Supports-subtraction
  supports-subtraction {p} {(Ο‰)} {r} x =
    case p-Ο‰β‰° {q = r} x of Ξ» {
      refl β†’
    Ο‰ , Ο‰-p≑ω Ο‰ }
  supports-subtraction {p} {(𝟘)} _ =
    p , p-πŸ˜β‰‘p
  supports-subtraction {(Ο‰)} {q} _ =
    Ο‰ , Ο‰-p≑ω q
  supports-subtraction {(𝟘)} {r} x =
    case 𝟘-p≀q {q = r} x of Ξ» {
      (refl , refl) β†’
    𝟘 , p-πŸ˜β‰‘p }
  supports-subtraction {(πŸ™)} {(πŸ™)} {(r)} x =
    𝟘 , πŸ™-πŸ™β‰‘πŸ˜

-- An alternative definition of the subtraction relation with
--   Ο‰ - p ≑ Ο‰ for all p
--   p - 𝟘 ≑ p for all p
--   πŸ™ - πŸ™ ≑ 𝟘
-- and not defined otherwise

data _-_≑′_ : (p q r : Zero-one-many) β†’ Set where
  Ο‰-p≑′ω : Ο‰ - p ≑′ Ο‰
  p-πŸ˜β‰‘β€²p : p - 𝟘 ≑′ p
  πŸ™-πŸ™β‰‘β€²πŸ˜ : πŸ™ - πŸ™ ≑′ 𝟘

opaque

  -- The two subtraction relations are equivalent.

  -≑↔-≑′ : βˆ€ p q r β†’ (p - q ≑ r) ⇔ (p - q ≑′ r)
  -≑↔-≑′ p q r = left p q r , right
    where
    left : βˆ€ p q r β†’ p - q ≑ r β†’ p - q ≑′ r
    left Ο‰ q r p-q≑r =
      case -≑-functional {q = q} p-q≑r (Ο‰-p≑ω q) of Ξ» {
        refl β†’
      Ο‰-p≑′ω }
    left p 𝟘 r p-q≑r =
      case -≑-functional p-q≑r p-πŸ˜β‰‘p of Ξ» {
        refl β†’
      p-πŸ˜β‰‘β€²p }
    left 𝟘 q r p-q≑r =
      case 𝟘-p≑q p-q≑r of Ξ» {
        (refl , refl) β†’
      p-πŸ˜β‰‘β€²p}
    left πŸ™ πŸ™ r p-q≑r =
      case -≑-functional p-q≑r πŸ™-πŸ™β‰‘πŸ˜ of Ξ» {
        refl β†’
      πŸ™-πŸ™β‰‘β€²πŸ˜ }
    left πŸ™ Ο‰ r p-q≑r =
      case p-Ο‰β‰’ p-q≑r of Ξ» ()
    right : p - q ≑′ r β†’ p - q ≑ r
    right Ο‰-p≑′ω = Ο‰-p≑ω q
    right p-πŸ˜β‰‘β€²p = p-πŸ˜β‰‘p
    right πŸ™-πŸ™β‰‘β€²πŸ˜ = πŸ™-πŸ™β‰‘πŸ˜

------------------------------------------------------------------------
-- Properties of greatest lower bounds

opaque

  -- nr 𝟘 r z s 𝟘 is the greatest lower bound of nrᡒ r z s.

  nr-nrα΅’-GLB :
    let 𝕄 = zero-one-many-semiring-with-meet in
    βˆ€ r β†’ Semiring-with-meet.Greatest-lower-bound
            𝕄 (nr 𝟘 r z s 𝟘) (Semiring-with-meet.nrα΅’ 𝕄 r z s)
  nr-nrα΅’-GLB {z} {s} = Ξ» where
      𝟘 β†’ GLB-congΚ³ (sym (trans (∧-congΚ³ (+-congΚ³ (Β·-zeroΚ³ (πŸ™ ∧ 𝟘))))
            (∧-comm s z))) nrᡒ-𝟘-GLB
      πŸ™ β†’ lemma-πŸ™ _ _
      Ο‰ β†’ lemma-Ο‰ _ _
    where
    open Semiring-with-meet zero-one-many-semiring-with-meet
      hiding (𝟘; πŸ™; Ο‰; _∧_; _Β·_; _+_)
    open GLB zero-one-many-semiring-with-meet
    open Natrec zero-one-many-semiring-with-meet
    open PartialOrder zero-one-many-semiring-with-meet
    lemmaβ€² : βˆ€ {z} i β†’ nrα΅’ πŸ™ z 𝟘 i ≑ z
    lemmaβ€² 0 = refl
    lemmaβ€² (1+ i) =
      trans (Β·-identityΛ‘ _) (lemmaβ€² i)
    lemma : βˆ€ {r z s} i β†’
      nrα΅’ r z s i ≑ Ο‰ β†’ Greatest-lower-bound Ο‰ (nrα΅’ r z s)
    lemma {r} {z} {s} i nrᡒ≑ω =
      (Ξ» i β†’ ω≀ (nrα΅’ r z s i)) , Ξ» q q≀ β†’ ≀-trans (q≀ i) (≀-reflexive nrᡒ≑ω)
    lemma-πŸ™ : βˆ€ z s β†’ Greatest-lower-bound (Ο‰ Β· s + z) (nrα΅’ πŸ™ z s)
    lemma-πŸ™ z 𝟘 =
      GLB-const lemmaβ€²
    lemma-πŸ™ 𝟘 πŸ™ = lemma 2 refl
    lemma-πŸ™ πŸ™ πŸ™ = lemma 1 refl
    lemma-πŸ™ Ο‰ πŸ™ = lemma 0 refl
    lemma-πŸ™ z Ο‰ = lemma 1 refl
    lemma-Ο‰ : βˆ€ z s β†’ Greatest-lower-bound (Ο‰ Β· (s + z)) (nrα΅’ Ο‰ z s)
    lemma-Ο‰ 𝟘 𝟘 = GLB-nrα΅’-𝟘
    lemma-Ο‰ πŸ™ 𝟘 = lemma 1 refl
    lemma-Ο‰ Ο‰ 𝟘 = lemma 0 refl
    lemma-Ο‰ 𝟘 πŸ™ = lemma 2 refl
    lemma-Ο‰ πŸ™ πŸ™ = lemma 1 refl
    lemma-Ο‰ Ο‰ πŸ™ = lemma 0 refl
    lemma-Ο‰ z Ο‰ = lemma 1 refl

opaque

  -- The greatest lower bound for certain nrα΅’ sequences

  nrᡒ-𝟘-GLB :
    let 𝕄 = zero-one-many-semiring-with-meet in
    βˆ€ p q β†’ Semiring-with-meet.Greatest-lower-bound
            𝕄 (p ∧ q) (Semiring-with-meet.nrα΅’ 𝕄 𝟘 p q)
  nrᡒ-𝟘-GLB p q = Natrec.nrᡒ-𝟘-GLB zero-one-many-semiring-with-meet

opaque

  -- The greatest lower bound for certain nrα΅’ sequences

  nrα΅’-πŸ™-GLB :
    let 𝕄 = zero-one-many-semiring-with-meet in
    βˆ€ p q β†’ Semiring-with-meet.Greatest-lower-bound
            𝕄 (p + Ο‰ Β· q) (Semiring-with-meet.nrα΅’ 𝕄 πŸ™ p q)
  nrα΅’-πŸ™-GLB p q =
    GLB.GLB-congΚ³ zero-one-many-semiring-with-meet (+-comm (Ο‰ Β· q) p) (nr-nrα΅’-GLB {z = p} {s = q} πŸ™)
    where
    open Semiring-with-meet zero-one-many-semiring-with-meet
      hiding (πŸ™; Ο‰; _Β·_; _+_)

opaque

  -- The greatest lower bound for certain nrα΅’ sequences

  nrα΅’-Ο‰-GLB :
    let 𝕄 = zero-one-many-semiring-with-meet in
    βˆ€ p q β†’ Semiring-with-meet.Greatest-lower-bound
            𝕄 (Ο‰ Β· (p + q)) (Semiring-with-meet.nrα΅’ 𝕄 Ο‰ p q)
  nrα΅’-Ο‰-GLB p q =
    GLB.GLB-congΚ³ zero-one-many-semiring-with-meet (Β·-congΛ‘ (+-comm q p)) (nr-nrα΅’-GLB {z = p} {s = q} Ο‰)
    where
    open Semiring-with-meet zero-one-many-semiring-with-meet
      hiding (Ο‰; _Β·_; _+_)

opaque

  -- The sequence nrα΅’Β rΒ zΒ s has a greatest lower bound

  nrα΅’-GLB :
    let 𝕄 = zero-one-many-semiring-with-meet in
    βˆ€ r z s β†’ βˆƒ Ξ» p β†’
      Semiring-with-meet.Greatest-lower-bound
        𝕄 p (Semiring-with-meet.nrα΅’ 𝕄 r z s)
  nrα΅’-GLB r z s = _ , nr-nrα΅’-GLB r

opaque

  -- The modality has well-behaved GLBs

  zero-one-many-supports-glb-for-natrec :
    Has-well-behaved-GLBs zero-one-many-semiring-with-meet
  zero-one-many-supports-glb-for-natrec = record
    { +-GLBΛ‘ = +-GLBΛ‘
    ; Β·-GLBΛ‘ = Β·-GLBΛ‘
    ; Β·-GLBΚ³ = comm∧·-GLBΛ‘β‡’Β·-GLBΚ³ Β·-comm Β·-GLBΛ‘
    ; +nrα΅’-GLB = +nrα΅’-GLB
    }
    where
    open Semiring-with-meet zero-one-many-semiring-with-meet
      hiding (_+_; _Β·_; _≀_; 𝟘; πŸ™; Ο‰)
    open GLB zero-one-many-semiring-with-meet
    open Multiplication zero-one-many-semiring-with-meet
    open PartialOrder zero-one-many-semiring-with-meet

    Β·-GLBΛ‘ :
      {pα΅’ : Sequence Zero-one-many} β†’
      Greatest-lower-bound p pα΅’ β†’
      Greatest-lower-bound (q Β· p) (Ξ» i β†’ q Β· pα΅’ i)
    Β·-GLBΛ‘ {q = 𝟘} p-glb = GLB-constβ€²
    Β·-GLBΛ‘ {q = πŸ™} p-glb =
      GLB-cong (sym (Β·-identityΛ‘ _)) (Ξ» _ β†’ sym (Β·-identityΛ‘ _)) p-glb
    Β·-GLBΛ‘ {q = Ο‰} {pα΅’} p-glb = lemma _ p-glb
      where
      lemmaβ€³ : πŸ™ ≀ Ο‰ Β· p β†’ p ≑ 𝟘
      lemmaβ€³ {(𝟘)} _ = refl
      lemmaβ€³ {(πŸ™)} ()
      lemmaβ€³ {(Ο‰)} ()
      lemmaβ€² : 𝟘 ≀ Ο‰ Β· p β†’ p ≑ 𝟘
      lemmaβ€² {(𝟘)} _ = refl
      lemmaβ€² {(πŸ™)} ()
      lemmaβ€² {(Ο‰)} ()
      lemma : βˆ€ p β†’ Greatest-lower-bound p pα΅’ β†’
              Greatest-lower-bound (Ο‰ Β· p) (Ξ» i β†’ Ο‰ Β· pα΅’ i)
      lemma 𝟘 p-glb =
        GLB-const Ξ» i β†’ Β·-congΛ‘ (𝟘-GLB-inv p-glb i)
      lemma πŸ™ p-glb =
          (Ξ» i β†’ ω≀ (pα΅’ i))
        , Ξ» { 𝟘 q≀ β†’ βŠ₯-elim (β‰’p-GLB-inv (Ξ» ()) p-glb (lemmaβ€² βˆ˜β†’ q≀))
            ; πŸ™ q≀ β†’ βŠ₯-elim (β‰’p-GLB-inv (Ξ» ()) p-glb (lemmaβ€³ βˆ˜β†’ q≀))
            ; Ο‰ q≀ β†’ refl}
      lemma Ο‰ p-glb =
          (Ξ» i β†’ ω≀ (pα΅’ i))
        , Ξ» { 𝟘 q≀ β†’ βŠ₯-elim (β‰’p-GLB-inv (Ξ» ()) p-glb (lemmaβ€² βˆ˜β†’ q≀))
            ; πŸ™ q≀ β†’ βŠ₯-elim (β‰’p-GLB-inv (Ξ» ()) p-glb (lemmaβ€³ βˆ˜β†’ q≀))
            ; Ο‰ q≀ β†’ refl}

    +-GLBΛ‘ :
      {pα΅’ : Sequence Zero-one-many} β†’
      Greatest-lower-bound p pα΅’ β†’
      Greatest-lower-bound (q + p) (Ξ» i β†’ q + pα΅’ i)
    +-GLBˑ {q = 𝟘} p-glb = p-glb
    +-GLBΛ‘ {(𝟘)} {q = πŸ™} p-glb =
      GLB-const (Ξ» i β†’ +-congΛ‘ (𝟘-GLB-inv p-glb i))
    +-GLBΛ‘ {q = πŸ™} {pα΅’} p-glb = lemma _ p-glb
      where
      lemmaβ€³ : πŸ™ ≀ πŸ™ + p β†’ p ≑ 𝟘
      lemmaβ€³ {(𝟘)} _ = refl
      lemmaβ€³ {(πŸ™)} ()
      lemmaβ€³ {(Ο‰)} ()
      lemmaβ€² : 𝟘 ≀ πŸ™ + p β†’ p ≑ 𝟘
      lemmaβ€² {(𝟘)} _ = refl
      lemmaβ€² {(πŸ™)} ()
      lemmaβ€² {(Ο‰)} ()
      lemma : βˆ€ p β†’ Greatest-lower-bound p pα΅’ β†’
              Greatest-lower-bound (πŸ™ + p) (Ξ» i β†’ πŸ™ + pα΅’ i)
      lemma 𝟘 p-glb =
        GLB-const (Ξ» i β†’ +-congΛ‘ (𝟘-GLB-inv p-glb i))
      lemma πŸ™ p-glb =
          (Ξ» _ β†’ refl)
        , Ξ» { 𝟘 q≀ β†’ βŠ₯-elim (β‰’p-GLB-inv (Ξ» ()) p-glb (lemmaβ€² βˆ˜β†’ q≀))
            ; πŸ™ q≀ β†’ βŠ₯-elim (β‰’p-GLB-inv (Ξ» ()) p-glb (lemmaβ€³ βˆ˜β†’ q≀))
            ; Ο‰ q≀ β†’ refl}
      lemma Ο‰ p-glb =
          (Ξ» _ β†’ refl)
        , Ξ» { 𝟘 q≀ β†’ βŠ₯-elim (β‰’p-GLB-inv (Ξ» ()) p-glb (lemmaβ€² βˆ˜β†’ q≀))
            ; πŸ™ q≀ β†’ βŠ₯-elim (β‰’p-GLB-inv (Ξ» ()) p-glb (lemmaβ€³ βˆ˜β†’ q≀))
            ; Ο‰ q≀ β†’ refl }
    +-GLBΛ‘ {q = Ο‰} p-glb = GLB-constβ€²

    open Tools.Reasoning.PartialOrder ≀-poset

    +nrα΅’-GLB :
      Greatest-lower-bound p₁ (nrα΅’ r z₁ s₁) β†’
      Greatest-lower-bound pβ‚‚ (nrα΅’ r zβ‚‚ sβ‚‚) β†’
      βˆƒ Ξ» q β†’ Greatest-lower-bound q (nrα΅’ r (z₁ + zβ‚‚) (s₁ + sβ‚‚)) Γ—
          p₁ + pβ‚‚ ≀ q
    +nrα΅’-GLB {p₁} {r} {z₁} {s₁} {pβ‚‚} {zβ‚‚} {sβ‚‚} p₁-glb pβ‚‚-glb =
      _ , nr-nrα΅’-GLB r , (begin
        p₁ + pβ‚‚                         β‰‘βŸ¨ +-cong (GLB-unique p₁-glb (nr-nrα΅’-GLB r))
                                           (GLB-unique pβ‚‚-glb (nr-nrα΅’-GLB r)) ⟩
        nr 𝟘 r z₁ s₁ 𝟘 + nr 𝟘 r zβ‚‚ sβ‚‚ 𝟘 β‰€βŸ¨ Has-nr.nr-+ zero-one-many-has-nr {𝟘} {r} ⟩
        nr 𝟘 r (z₁ + zβ‚‚) (s₁ + sβ‚‚) 𝟘    ∎)